=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/aucat/Attic/aproc.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- src/usr.bin/aucat/Attic/aproc.c 2008/08/20 14:22:50 1.11 +++ src/usr.bin/aucat/Attic/aproc.c 2008/10/26 08:49:43 1.12 @@ -1,4 +1,4 @@ -/* $OpenBSD: aproc.c,v 1.11 2008/08/20 14:22:50 ratchov Exp $ */ +/* $OpenBSD: aproc.c,v 1.12 2008/10/26 08:49:43 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov * @@ -39,6 +39,7 @@ * * (hard) add a lowpass filter for the resampler. Quality is * not acceptable as is. + * */ #include #include @@ -70,9 +71,22 @@ void aproc_del(struct aproc *p) { + struct abuf *i; + + DPRINTF("aproc_del: %s(%s): terminating...\n", p->ops->name, p->name); + if (p->ops->done) p->ops->done(p); - DPRINTF("aproc_del: %s: %s: deleted\n", p->ops->name, p->name); + + while (!LIST_EMPTY(&p->ibuflist)) { + i = LIST_FIRST(&p->ibuflist); + abuf_hup(i); + } + while (!LIST_EMPTY(&p->obuflist)) { + i = LIST_FIRST(&p->obuflist); + abuf_eof(i); + } + DPRINTF("aproc_del: %s(%s): freed\n", p->ops->name, p->name); free(p); } @@ -94,6 +108,30 @@ p->ops->newout(p, obuf); } +void +aproc_ipos(struct aproc *p, struct abuf *ibuf, int delta) +{ + struct abuf *obuf; + + DPRINTFN(3, "aproc_ipos: %s: delta = %d\n", p->name, delta); + + LIST_FOREACH(obuf, &p->obuflist, oent) { + abuf_ipos(obuf, delta); + } +} + +void +aproc_opos(struct aproc *p, struct abuf *obuf, int delta) +{ + struct abuf *ibuf; + + DPRINTFN(3, "aproc_opos: %s: delta = %d\n", p->name, delta); + + LIST_FOREACH(ibuf, &p->ibuflist, ient) { + abuf_opos(ibuf, delta); + } +} + int rpipe_in(struct aproc *p, struct abuf *ibuf_dummy) { @@ -104,13 +142,16 @@ DPRINTFN(3, "rpipe_in: %s\n", p->name); - if (ABUF_FULL(obuf)) + 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); - abuf_flush(obuf); - return !ABUF_FULL(obuf); + if (!abuf_flush(obuf)) + return 0; + return 1; } int @@ -120,14 +161,18 @@ unsigned char *data; unsigned count; + if (f->refs > 0) + return 0; DPRINTFN(3, "rpipe_out: %s\n", p->name); - - if (!(f->state & FILE_ROK)) + + 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 f->state & FILE_ROK; + return 1; } void @@ -136,14 +181,14 @@ struct file *f = p->u.io.file; f->rproc = NULL; - f->events &= ~POLLIN; + if (f->wproc == NULL) + file_del(f); } void rpipe_eof(struct aproc *p, struct abuf *ibuf_dummy) { DPRINTFN(3, "rpipe_eof: %s\n", p->name); - abuf_eof(LIST_FIRST(&p->obuflist)); aproc_del(p); } @@ -155,7 +200,16 @@ } struct aproc_ops rpipe_ops = { - "rpipe", rpipe_in, rpipe_out, rpipe_eof, rpipe_hup, NULL, NULL, rpipe_done + "rpipe", + rpipe_in, + rpipe_out, + rpipe_eof, + rpipe_hup, + NULL, /* newin */ + NULL, /* newout */ + aproc_ipos, + aproc_opos, + rpipe_done }; struct aproc * @@ -165,8 +219,7 @@ p = aproc_new(&rpipe_ops, f->name); p->u.io.file = f; - f->rproc = p; - f->events |= POLLIN; + f->rproc = p; return p; } @@ -176,7 +229,8 @@ struct file *f = p->u.io.file; f->wproc = NULL; - f->events &= ~POLLOUT; + if (f->rproc == NULL) + file_del(f); } int @@ -186,15 +240,18 @@ unsigned char *data; unsigned count; + if (f->refs > 0) + return 0; DPRINTFN(3, "wpipe_in: %s\n", p->name); - if (!(f->state & FILE_WOK)) + if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK)) return 0; - data = abuf_rgetblk(ibuf, &count, 0); count = file_write(f, data, count); + if (count == 0) + return 0; abuf_rdiscard(ibuf, count); - return f->state & FILE_WOK; + return 1; } int @@ -207,17 +264,21 @@ DPRINTFN(3, "wpipe_out: %s\n", p->name); - if (ABUF_EMPTY(ibuf)) + if (!abuf_fill(ibuf)) { + DPRINTFN(3, "wpipe_out: fill failed\n"); return 0; + } + if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK)) + return 0; data = abuf_rgetblk(ibuf, &count, 0); - count = file_write(f, data, count); - abuf_rdiscard(ibuf, count); - if (ABUF_EOF(ibuf)) { - abuf_hup(ibuf); - aproc_del(p); + if (count == 0) { + DPRINTF("wpipe_out: %s: underrun\n", p->name); return 0; } - abuf_fill(ibuf); + count = file_write(f, data, count); + if (count == 0) + return 0; + abuf_rdiscard(ibuf, count); return 1; } @@ -232,12 +293,20 @@ wpipe_hup(struct aproc *p, struct abuf *obuf_dummy) { DPRINTFN(3, "wpipe_hup: %s\n", p->name); - abuf_hup(LIST_FIRST(&p->ibuflist)); aproc_del(p); } struct aproc_ops wpipe_ops = { - "wpipe", wpipe_in, wpipe_out, wpipe_eof, wpipe_hup, NULL, NULL, wpipe_done + "wpipe", + wpipe_in, + wpipe_out, + wpipe_eof, + wpipe_hup, + NULL, /* newin */ + NULL, /* newout */ + aproc_ipos, + aproc_opos, + wpipe_done }; struct aproc * @@ -248,7 +317,6 @@ p = aproc_new(&wpipe_ops, f->name); p->u.io.file = f; f->wproc = p; - f->events |= POLLOUT; return p; } @@ -265,6 +333,7 @@ DPRINTFN(4, "mix_bzero: used = %u, todo = %u\n", obuf->used, obuf->mixtodo); odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->mixtodo); + ocount -= ocount % obuf->bpf; if (ocount == 0) return; memset(odata, 0, ocount); @@ -286,10 +355,12 @@ obuf->mixtodo, ibuf->mixdone); idata = (short *)abuf_rgetblk(ibuf, &icount, 0); + icount -= icount % ibuf->bpf; if (icount == 0) return; odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->mixdone); + ocount -= ocount % obuf->bpf; if (ocount == 0) return; @@ -306,16 +377,6 @@ scount, ibuf->mixdone, obuf->mixtodo); } -/* - * Remove an input stream from the mixer. - */ -void -mix_rm(struct aproc *p, struct abuf *ibuf) -{ - LIST_REMOVE(ibuf, ient); - DPRINTF("mix_rm: %s\n", p->name); -} - int mix_in(struct aproc *p, struct abuf *ibuf) { @@ -325,8 +386,9 @@ DPRINTFN(4, "mix_in: used = %u, done = %u, todo = %u\n", ibuf->used, ibuf->mixdone, obuf->mixtodo); - if (ibuf->mixdone >= obuf->mixtodo) + if (!ABUF_ROK(ibuf) || ibuf->mixdone == obuf->mixtodo) return 0; + mix_badd(ibuf, obuf); ocount = obuf->mixtodo; LIST_FOREACH(i, &p->ibuflist, ient) { @@ -337,21 +399,18 @@ return 0; abuf_wcommit(obuf, ocount); + p->u.mix.lat += ocount / obuf->bpf; obuf->mixtodo -= ocount; - abuf_flush(obuf); + if (!abuf_flush(obuf)) + return 0; /* hup */ mix_bzero(p); - for (i = LIST_FIRST(&p->ibuflist); i != LIST_END(&p->ibuflist); i = inext) { + for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) { inext = LIST_NEXT(i, ient); i->mixdone -= ocount; - if (i != ibuf && i->mixdone < obuf->mixtodo) { - if (ABUF_EOF(i)) { - mix_rm(p, i); - abuf_hup(i); - continue; - } + if (i->mixdone < obuf->mixtodo) mix_badd(i, obuf); - abuf_fill(i); - } + if (!abuf_fill(i)) + continue; } return 1; } @@ -365,14 +424,18 @@ DPRINTFN(4, "mix_out: used = %u, todo = %u\n", obuf->used, obuf->mixtodo); + if (!ABUF_WOK(obuf)) + return 0; + mix_bzero(p); ocount = obuf->mixtodo; - for (i = LIST_FIRST(&p->ibuflist); i != LIST_END(&p->ibuflist); i = inext) { + for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) { inext = LIST_NEXT(i, ient); + if (!abuf_fill(i)) + continue; if (!ABUF_ROK(i)) { if ((p->u.mix.flags & MIX_DROP) && i->mixdone == 0) { if (i->xrun == XRUN_ERROR) { - mix_rm(p, i); abuf_hup(i); continue; } @@ -380,28 +443,33 @@ i->mixdone += drop; if (i->xrun == XRUN_SYNC) i->drop += drop; + else { + abuf_opos(i, -(int)(drop / i->bpf)); + if (i->duplex) { + DPRINTF("mix_out: duplex %u\n", + drop); + i->duplex->drop += drop * + i->duplex->bpf / i->bpf; + abuf_ipos(i->duplex, + -(int)(drop / i->bpf)); + } + } DPRINTF("mix_out: drop = %u\n", i->drop); } } else mix_badd(i, obuf); if (ocount > i->mixdone) ocount = i->mixdone; - if (ABUF_EOF(i)) { - mix_rm(p, i); - abuf_hup(i); - continue; - } - abuf_fill(i); } if (ocount == 0) return 0; if (LIST_EMPTY(&p->ibuflist) && (p->u.mix.flags & MIX_AUTOQUIT)) { DPRINTF("mix_out: nothing more to do...\n"); - obuf->wproc = NULL; aproc_del(p); return 0; } abuf_wcommit(obuf, ocount); + p->u.mix.lat += ocount / obuf->bpf; obuf->mixtodo -= ocount; LIST_FOREACH(i, &p->ibuflist, ient) { i->mixdone -= ocount; @@ -415,7 +483,8 @@ struct abuf *obuf = LIST_FIRST(&p->obuflist); DPRINTF("mix_eof: %s: detached\n", p->name); - mix_rm(p, ibuf); + mix_setmaster(p); + /* * If there's no more inputs, abuf_run() will trigger the eof * condition and propagate it, so no need to handle it here. @@ -431,7 +500,6 @@ while (!LIST_EMPTY(&p->ibuflist)) { ibuf = LIST_FIRST(&p->ibuflist); - mix_rm(p, ibuf); abuf_hup(ibuf); } DPRINTF("mix_hup: %s: done\n", p->name); @@ -444,6 +512,7 @@ ibuf->mixdone = 0; ibuf->mixvol = ADATA_UNIT; ibuf->xrun = XRUN_IGNORE; + mix_setmaster(p); } void @@ -453,17 +522,36 @@ mix_bzero(p); } +void +mix_opos(struct aproc *p, struct abuf *obuf, int delta) +{ + DPRINTFN(3, "mix_opos: lat = %d/%d\n", p->u.mix.lat, p->u.mix.maxlat); + p->u.mix.lat -= delta; + aproc_opos(p, obuf, delta); +} + struct aproc_ops mix_ops = { - "mix", mix_in, mix_out, mix_eof, mix_hup, mix_newin, mix_newout, NULL + "mix", + mix_in, + mix_out, + mix_eof, + mix_hup, + mix_newin, + mix_newout, + aproc_ipos, + mix_opos, + NULL }; struct aproc * -mix_new(void) +mix_new(char *name, int maxlat) { struct aproc *p; - p = aproc_new(&mix_ops, "softmix"); + p = aproc_new(&mix_ops, name); p->u.mix.flags = 0; + p->u.mix.lat = 0; + p->u.mix.maxlat = maxlat; return p; } @@ -473,6 +561,7 @@ struct abuf *obuf = LIST_FIRST(&p->obuflist); abuf_wcommit(obuf, obuf->mixtodo); + p->u.mix.lat += obuf->mixtodo / obuf->bpf; obuf->mixtodo = 0; abuf_run(obuf); mix_bzero(p); @@ -504,63 +593,67 @@ unsigned icount, ocount, scount; idata = abuf_rgetblk(ibuf, &icount, obuf->subdone); + icount -= icount % ibuf->bpf; if (icount == 0) return; odata = abuf_wgetblk(obuf, &ocount, 0); + ocount -= icount % obuf->bpf; if (ocount == 0) return; scount = (icount < ocount) ? icount : ocount; memcpy(odata, idata, scount); - abuf_wcommit(obuf, scount); + abuf_wcommit(obuf, scount); obuf->subdone += scount; DPRINTFN(4, "sub_bcopy: %u bytes\n", scount); } -void -sub_rm(struct aproc *p, struct abuf *obuf) -{ - LIST_REMOVE(obuf, oent); - DPRINTF("sub_rm: %s\n", p->name); -} - int sub_in(struct aproc *p, struct abuf *ibuf) { struct abuf *i, *inext; unsigned done, drop; - int again; - - again = 1; + + if (!ABUF_ROK(ibuf)) + return 0; done = ibuf->used; - for (i = LIST_FIRST(&p->obuflist); i != LIST_END(&p->obuflist); i = inext) { + for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) { inext = LIST_NEXT(i, oent); if (!ABUF_WOK(i)) { if ((p->u.sub.flags & SUB_DROP) && i->subdone == 0) { if (i->xrun == XRUN_ERROR) { - sub_rm(p, i); abuf_eof(i); continue; } drop = ibuf->used; if (i->xrun == XRUN_SYNC) i->silence += drop; + else { + abuf_ipos(i, -(int)(drop / i->bpf)); + if (i->duplex) { + DPRINTF("sub_in: duplex %u\n", + drop); + i->duplex->silence += drop * + i->duplex->bpf / i->bpf; + abuf_opos(i->duplex, + -(int)(drop / i->bpf)); + } + } i->subdone += drop; - DPRINTF("sub_in: silence = %u\n", i->silence); + DPRINTF("sub_in: silence = %u\n", i->silence); } - } else { + } else sub_bcopy(ibuf, i); - abuf_flush(i); - } - if (!ABUF_WOK(i)) - again = 0; if (done > i->subdone) done = i->subdone; + if (!abuf_flush(i)) + continue; } LIST_FOREACH(i, &p->obuflist, oent) { i->subdone -= done; } abuf_rdiscard(ibuf, done); - return again; + p->u.sub.lat -= done / ibuf->bpf; + return 1; } int @@ -570,40 +663,28 @@ struct abuf *i, *inext; unsigned done; - if (obuf->subdone >= ibuf->used) + if (!ABUF_WOK(obuf)) return 0; + if (!abuf_fill(ibuf)) { + return 0; + } + if (obuf->subdone == ibuf->used) + return 0; - sub_bcopy(ibuf, obuf); - done = ibuf->used; - LIST_FOREACH(i, &p->obuflist, oent) { - if (i != obuf && ABUF_WOK(i)) { - sub_bcopy(ibuf, i); - abuf_flush(i); - } + for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) { + inext = LIST_NEXT(i, oent); + if (!abuf_flush(i)) + continue; + sub_bcopy(ibuf, i); if (done > i->subdone) done = i->subdone; } - if (done == 0) - return 0; LIST_FOREACH(i, &p->obuflist, oent) { i->subdone -= done; } abuf_rdiscard(ibuf, done); - if (ABUF_EOF(ibuf)) { - abuf_hup(ibuf); - for (i = LIST_FIRST(&p->obuflist); - i != LIST_END(&p->obuflist); - i = inext) { - inext = LIST_NEXT(i, oent); - if (i != ibuf) - abuf_eof(i); - } - ibuf->wproc = NULL; - aproc_del(p); - return 0; - } - abuf_fill(ibuf); + p->u.sub.lat -= done / ibuf->bpf; return 1; } @@ -614,7 +695,6 @@ while (!LIST_EMPTY(&p->obuflist)) { obuf = LIST_FIRST(&p->obuflist); - sub_rm(p, obuf); abuf_eof(obuf); } aproc_del(p); @@ -626,12 +706,7 @@ struct abuf *ibuf = LIST_FIRST(&p->ibuflist); DPRINTF("sub_hup: %s: detached\n", p->name); - sub_rm(p, obuf); - if (LIST_EMPTY(&p->obuflist) && (p->u.sub.flags & SUB_AUTOQUIT)) { - abuf_hup(ibuf); - aproc_del(p); - } else - abuf_run(ibuf); + abuf_run(ibuf); DPRINTF("sub_hup: done\n"); } @@ -642,21 +717,39 @@ obuf->xrun = XRUN_IGNORE; } +void +sub_ipos(struct aproc *p, struct abuf *ibuf, int delta) +{ + p->u.sub.lat += delta; + DPRINTFN(3, "sub_ipos: lat = %d/%d\n", p->u.sub.lat, p->u.sub.maxlat); + aproc_ipos(p, ibuf, delta); +} + struct aproc_ops sub_ops = { - "sub", sub_in, sub_out, sub_eof, sub_hup, NULL, sub_newout, NULL + "sub", + sub_in, + sub_out, + sub_eof, + sub_hup, + NULL, + sub_newout, + sub_ipos, + aproc_opos, + NULL }; struct aproc * -sub_new(void) +sub_new(char *name, int maxlat) { struct aproc *p; - p = aproc_new(&sub_ops, "copy"); + p = aproc_new(&sub_ops, name); p->u.sub.flags = 0; + p->u.sub.lat = 0; + p->u.sub.maxlat = maxlat; return p; } - /* * Convert one block. */ @@ -695,9 +788,11 @@ */ idata = abuf_rgetblk(ibuf, &icount, 0); ifr = icount / ibuf->bpf; + icount = ifr * ibuf->bpf; odata = abuf_wgetblk(obuf, &ocount, 0); ofr = ocount / obuf->bpf; + ocount = ofr * obuf->bpf; /* * Partially copy structures into local variables, to avoid @@ -784,11 +879,14 @@ { struct abuf *obuf = LIST_FIRST(&p->obuflist); - if (!ABUF_WOK(obuf)) + DPRINTFN(4, "conv_in: %s\n", p->name); + + if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf)) return 0; conv_bcopy(&p->u.conv.ist, &p->u.conv.ost, ibuf, obuf); - abuf_flush(obuf); - return ABUF_WOK(obuf); + if (!abuf_flush(obuf)) + return 0; + return 1; } int @@ -796,30 +894,29 @@ { struct abuf *ibuf = LIST_FIRST(&p->ibuflist); - if (!ABUF_ROK(ibuf)) + DPRINTFN(4, "conv_out: %s\n", p->name); + + if (!abuf_fill(ibuf)) return 0; - conv_bcopy(&p->u.conv.ist, &p->u.conv.ost, ibuf, obuf); - if (ABUF_EOF(ibuf)) { - obuf->wproc = NULL; - abuf_hup(ibuf); - aproc_del(p); + if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf)) return 0; - } - abuf_fill(ibuf); + conv_bcopy(&p->u.conv.ist, &p->u.conv.ost, ibuf, obuf); return 1; } void conv_eof(struct aproc *p, struct abuf *ibuf) { - abuf_eof(LIST_FIRST(&p->obuflist)); + DPRINTFN(4, "conv_eof: %s\n", p->name); + aproc_del(p); } void conv_hup(struct aproc *p, struct abuf *obuf) { - abuf_hup(LIST_FIRST(&p->ibuflist)); + DPRINTFN(4, "conv_hup: %s\n", p->name); + aproc_del(p); } @@ -850,12 +947,55 @@ st->rate = par->rate; st->pos = 0; - for (i = 0; i < CHAN_MAX; i++) + for (i = 0; i < NCHAN_MAX; i++) st->ctx[i] = 0; } +void +conv_ipos(struct aproc *p, struct abuf *ibuf, int delta) +{ + struct abuf *obuf = LIST_FIRST(&p->obuflist); + long long ipos; + int ifac, ofac; + + DPRINTFN(3, "conv_ipos: %d\n", delta); + + ifac = p->u.conv.ist.rate; + ofac = p->u.conv.ost.rate; + ipos = p->u.conv.idelta + (long long)delta * ofac; + delta = (ipos + ifac - 1) / ifac; + p->u.conv.idelta = ipos - (long long)delta * ifac; + abuf_ipos(obuf, delta); +} + +void +conv_opos(struct aproc *p, struct abuf *obuf, int delta) +{ + struct abuf *ibuf = LIST_FIRST(&p->ibuflist); + long long opos; + int ifac, ofac; + + DPRINTFN(3, "conv_opos: %d\n", delta); + + ifac = p->u.conv.ist.rate; + ofac = p->u.conv.ost.rate; + opos = p->u.conv.odelta + (long long)delta * ifac; + delta = (opos + ofac - 1) / ofac; + p->u.conv.odelta = opos - (long long)delta * ofac; + abuf_opos(ibuf, delta); +} + struct aproc_ops conv_ops = { - "conv", conv_in, conv_out, conv_eof, conv_hup, NULL, NULL, NULL + "conv", + conv_in, + conv_out, + conv_eof, + conv_hup, + NULL, + NULL, + conv_ipos, + conv_opos, + NULL }; struct aproc * @@ -866,5 +1006,12 @@ p = aproc_new(&conv_ops, name); aconv_init(&p->u.conv.ist, ipar, 1); aconv_init(&p->u.conv.ost, opar, 0); + p->u.conv.idelta = 0; + p->u.conv.odelta = 0; + if (debug_level > 0) { + DPRINTF("conv_new: %s: ", p->name); + aparams_print2(ipar, opar); + DPRINTF("\n"); + } return p; }