[BACK]Return to aproc.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / aucat

Annotation of src/usr.bin/aucat/aproc.c, Revision 1.74

1.74    ! ratchov     1: /*     $OpenBSD$       */
1.1       ratchov     2: /*
                      3:  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: /*
                     18:  * aproc structures are simple audio processing units. They are
                     19:  * interconnected by abuf structures and form a kind of circuit. aproc
                     20:  * structure have call-backs that do the actual processing.
                     21:  *
                     22:  * This module implements the following processing units:
                     23:  *
                     24:  *  - rpipe: read end of an unix file (pipe, socket, device...)
                     25:  *
                     26:  *  - wpipe: write end of an unix file (pipe, socket, device...)
                     27:  *
                     28:  *  - mix: mix N inputs -> 1 output
                     29:  *
                     30:  *  - sub: from 1 input -> extract/copy N outputs
                     31:  *
                     32:  *  - conv: converts/resamples/remaps a single stream
                     33:  *
1.15      ratchov    34:  *  - resamp: resample streams in native format
                     35:  *
1.1       ratchov    36:  */
                     37: #include <err.h>
                     38: #include <stdlib.h>
                     39: #include <string.h>
                     40:
1.33      ratchov    41: #include "abuf.h"
1.1       ratchov    42: #include "aparams.h"
                     43: #include "aproc.h"
1.33      ratchov    44: #include "conf.h"
1.1       ratchov    45: #include "file.h"
1.38      ratchov    46: #include "midi.h"
1.42      ratchov    47: #ifdef DEBUG
                     48: #include "dbg.h"
                     49: #endif
                     50:
1.51      ratchov    51: /*
                     52:  * Same as ABUF_ROK(), but consider that a buffer is
                     53:  * readable if there's silence pending to be inserted
                     54:  */
                     55: #define MIX_ROK(buf) (ABUF_ROK(buf) || (buf)->r.mix.drop < 0)
                     56:
                     57: /*
                     58:  * Same as ABUF_WOK(), but consider that a buffer is
                     59:  * writeable if there are samples to drop
                     60:  */
                     61: #define SUB_WOK(buf) (ABUF_WOK(buf) || (buf)->w.sub.silence < 0)
1.74    ! ratchov    62:
        !            63: int zomb_in(struct aproc *, struct abuf *);
        !            64: int zomb_out(struct aproc *, struct abuf *);
        !            65: void zomb_eof(struct aproc *, struct abuf *);
        !            66: void zomb_hup(struct aproc *, struct abuf *);
        !            67: void zomb_newin(struct aproc *, struct abuf *);
        !            68: void zomb_newout(struct aproc *, struct abuf *);
        !            69: void zomb_ipos(struct aproc *, struct abuf *, int);
        !            70: void zomb_opos(struct aproc *, struct abuf *, int);
        !            71:
        !            72: int rfile_do(struct aproc *, unsigned int, unsigned int *);
        !            73: int rfile_in(struct aproc *, struct abuf *);
        !            74: int rfile_out(struct aproc *, struct abuf *);
        !            75: void rfile_done(struct aproc *);
        !            76: void rfile_eof(struct aproc *, struct abuf *);
        !            77: void rfile_hup(struct aproc *, struct abuf *);
        !            78:
        !            79: void wfile_done(struct aproc *);
        !            80: int wfile_do(struct aproc *, unsigned int, unsigned int *);
        !            81: int wfile_in(struct aproc *, struct abuf *);
        !            82: int wfile_out(struct aproc *, struct abuf *);
        !            83: void wfile_eof(struct aproc *, struct abuf *);
        !            84: void wfile_hup(struct aproc *, struct abuf *);
        !            85:
        !            86: void mix_drop(struct abuf *, int);
        !            87: void mix_bzero(struct abuf *, unsigned int);
        !            88: unsigned int mix_badd(struct abuf *, struct abuf *);
        !            89: int mix_xrun(struct aproc *, struct abuf *);
        !            90: int mix_in(struct aproc *, struct abuf *);
        !            91: int mix_out(struct aproc *, struct abuf *);
        !            92: void mix_eof(struct aproc *, struct abuf *);
        !            93: void mix_hup(struct aproc *, struct abuf *);
        !            94: void mix_newin(struct aproc *, struct abuf *);
        !            95: void mix_newout(struct aproc *, struct abuf *);
        !            96: void mix_opos(struct aproc *, struct abuf *, int);
        !            97: void mix_setmaster(struct aproc *);
        !            98: void mix_clear(struct aproc *);
        !            99: void mix_quit(struct aproc *);
        !           100:
        !           101: void sub_silence(struct abuf *, int);
        !           102: void sub_bcopy(struct abuf *, struct abuf *);
        !           103: int sub_xrun(struct aproc *, struct abuf *);
        !           104: int sub_in(struct aproc *, struct abuf *);
        !           105: int sub_out(struct aproc *, struct abuf *);
        !           106: void sub_eof(struct aproc *, struct abuf *);
        !           107: void sub_hup(struct aproc *, struct abuf *);
        !           108: void sub_newout(struct aproc *, struct abuf *);
        !           109: void sub_ipos(struct aproc *, struct abuf *, int);
        !           110: void sub_clear(struct aproc *);
        !           111:
        !           112: void resamp_bcopy(struct aproc *, struct abuf *, struct abuf *);
        !           113: int resamp_in(struct aproc *, struct abuf *);
        !           114: int resamp_out(struct aproc *, struct abuf *);
        !           115: void resamp_eof(struct aproc *, struct abuf *);
        !           116: void resamp_hup(struct aproc *, struct abuf *);
        !           117: void resamp_ipos(struct aproc *, struct abuf *, int);
        !           118: void resamp_opos(struct aproc *, struct abuf *, int);
        !           119:
        !           120: void enc_bcopy(struct aproc *, struct abuf *, struct abuf *);
        !           121: int enc_in(struct aproc *, struct abuf *);
        !           122: int enc_out(struct aproc *, struct abuf *);
        !           123: void enc_eof(struct aproc *, struct abuf *);
        !           124: void enc_hup(struct aproc *, struct abuf *);
        !           125:
        !           126: void dec_bcopy(struct aproc *, struct abuf *, struct abuf *);
        !           127: int dec_in(struct aproc *, struct abuf *);
        !           128: int dec_out(struct aproc *, struct abuf *);
        !           129: void dec_eof(struct aproc *, struct abuf *);
        !           130: void dec_hup(struct aproc *, struct abuf *);
        !           131:
        !           132: void join_bcopy(struct aproc *, struct abuf *, struct abuf *);
        !           133: int join_in(struct aproc *, struct abuf *);
        !           134: int join_out(struct aproc *, struct abuf *);
        !           135: void join_eof(struct aproc *, struct abuf *);
        !           136: void join_hup(struct aproc *, struct abuf *);
        !           137:
        !           138: void mon_flush(struct aproc *);
        !           139: void mon_snoop(struct aproc *, struct abuf *, unsigned int, unsigned int);
        !           140: int mon_in(struct aproc *, struct abuf *);
        !           141: void mon_clear(struct aproc *);
        !           142: int mon_out(struct aproc *, struct abuf *);
        !           143: void mon_eof(struct aproc *, struct abuf *);
        !           144: void mon_hup(struct aproc *, struct abuf *);
        !           145: void mon_ipos(struct aproc *, struct abuf *, int);
1.51      ratchov   146:
1.42      ratchov   147: #ifdef DEBUG
                    148: void
                    149: aproc_dbg(struct aproc *p)
                    150: {
                    151:        dbg_puts(p->ops->name);
                    152:        dbg_puts("(");
                    153:        dbg_puts(p->name);
                    154:        dbg_puts(")");
                    155: }
                    156:
                    157: int
                    158: zomb_in(struct aproc *p, struct abuf *ibuf)
                    159: {
                    160:        aproc_dbg(p);
                    161:        dbg_puts(": in: terminated\n");
                    162:        dbg_panic();
                    163:        return 0;
                    164: }
                    165:
1.1       ratchov   166:
1.42      ratchov   167: int
                    168: zomb_out(struct aproc *p, struct abuf *obuf)
                    169: {
                    170:        aproc_dbg(p);
                    171:        dbg_puts(": out: terminated\n");
                    172:        dbg_panic();
                    173:        return 0;
                    174: }
                    175:
                    176: void
                    177: zomb_eof(struct aproc *p, struct abuf *ibuf)
                    178: {
                    179:        aproc_dbg(p);
                    180:        dbg_puts(": eof: terminated\n");
                    181:        dbg_panic();
                    182: }
                    183:
                    184: void
                    185: zomb_hup(struct aproc *p, struct abuf *obuf)
                    186: {
                    187:        aproc_dbg(p);
                    188:        dbg_puts(": hup: terminated\n");
                    189:        dbg_panic();
                    190: }
                    191:
                    192: void
                    193: zomb_newin(struct aproc *p, struct abuf *ibuf)
                    194: {
                    195:        aproc_dbg(p);
                    196:        dbg_puts(": newin: terminated\n");
                    197:        dbg_panic();
                    198: }
                    199:
                    200: void
                    201: zomb_newout(struct aproc *p, struct abuf *obuf)
                    202: {
                    203:        aproc_dbg(p);
                    204:        dbg_puts(": newout: terminated\n");
                    205:        dbg_panic();
                    206: }
                    207:
                    208: void
                    209: zomb_ipos(struct aproc *p, struct abuf *ibuf, int delta)
                    210: {
                    211:        aproc_dbg(p);
                    212:        dbg_puts(": ipos: terminated\n");
                    213:        dbg_panic();
                    214: }
                    215:
                    216: void
                    217: zomb_opos(struct aproc *p, struct abuf *obuf, int delta)
                    218: {
                    219:        aproc_dbg(p);
                    220:        dbg_puts(": opos: terminated\n");
                    221:        dbg_panic();
                    222: }
                    223:
                    224: struct aproc_ops zomb_ops = {
                    225:        "zomb",
                    226:        zomb_in,
                    227:        zomb_out,
                    228:        zomb_eof,
                    229:        zomb_hup,
                    230:        zomb_newin,
                    231:        zomb_newout,
                    232:        zomb_ipos,
                    233:        zomb_opos,
                    234:        NULL
                    235: };
                    236: #endif
1.34      ratchov   237:
1.1       ratchov   238: struct aproc *
                    239: aproc_new(struct aproc_ops *ops, char *name)
                    240: {
                    241:        struct aproc *p;
                    242:
                    243:        p = malloc(sizeof(struct aproc));
                    244:        if (p == NULL)
1.64      ratchov   245:                err(1, "%s", name);
1.54      ratchov   246:        LIST_INIT(&p->ins);
                    247:        LIST_INIT(&p->outs);
1.1       ratchov   248:        p->name = name;
                    249:        p->ops = ops;
1.30      ratchov   250:        p->refs = 0;
1.38      ratchov   251:        p->flags = 0;
1.1       ratchov   252:        return p;
                    253: }
                    254:
                    255: void
                    256: aproc_del(struct aproc *p)
                    257: {
1.12      ratchov   258:        struct abuf *i;
                    259:
1.72      ratchov   260: #ifdef DEBUG
                    261:        if (!p) {
                    262:                dbg_puts("aproc_del: called with NULL argument\n");
                    263:                dbg_panic();
                    264:        }
                    265: #endif
1.38      ratchov   266:        if (!(p->flags & APROC_ZOMB)) {
1.42      ratchov   267: #ifdef DEBUG
                    268:                if (debug_level >= 3) {
                    269:                        aproc_dbg(p);
                    270:                        dbg_puts(": terminating...\n");
                    271:                }
                    272: #endif
1.35      ratchov   273:                if (p->ops->done) {
1.42      ratchov   274: #ifdef DEBUG
                    275:                        if (debug_level >= 3) {
                    276:                                aproc_dbg(p);
                    277:                                dbg_puts(": done\n");
                    278:                        }
                    279: #endif
1.35      ratchov   280:                        p->ops->done(p);
                    281:                }
1.54      ratchov   282:                while (!LIST_EMPTY(&p->ins)) {
                    283:                        i = LIST_FIRST(&p->ins);
1.35      ratchov   284:                        abuf_hup(i);
                    285:                }
1.54      ratchov   286:                while (!LIST_EMPTY(&p->outs)) {
                    287:                        i = LIST_FIRST(&p->outs);
1.35      ratchov   288:                        abuf_eof(i);
                    289:                }
1.38      ratchov   290:                p->flags |= APROC_ZOMB;
1.34      ratchov   291:        }
1.35      ratchov   292:        if (p->refs > 0) {
1.42      ratchov   293: #ifdef DEBUG
                    294:                if (debug_level >= 3) {
                    295:                        aproc_dbg(p);
                    296:                        dbg_puts(": free delayed\n");
                    297:                        p->ops = &zomb_ops;
                    298:                }
                    299: #endif
1.35      ratchov   300:                return;
1.12      ratchov   301:        }
1.42      ratchov   302: #ifdef DEBUG
                    303:        if (debug_level >= 3) {
                    304:                aproc_dbg(p);
                    305:                dbg_puts(": freed\n");
                    306:        }
                    307: #endif
1.1       ratchov   308:        free(p);
                    309: }
                    310:
                    311: void
                    312: aproc_setin(struct aproc *p, struct abuf *ibuf)
                    313: {
1.54      ratchov   314:        LIST_INSERT_HEAD(&p->ins, ibuf, ient);
1.1       ratchov   315:        ibuf->rproc = p;
                    316:        if (p->ops->newin)
                    317:                p->ops->newin(p, ibuf);
                    318: }
                    319:
                    320: void
                    321: aproc_setout(struct aproc *p, struct abuf *obuf)
                    322: {
1.54      ratchov   323:        LIST_INSERT_HEAD(&p->outs, obuf, oent);
1.1       ratchov   324:        obuf->wproc = p;
                    325:        if (p->ops->newout)
                    326:                p->ops->newout(p, obuf);
                    327: }
                    328:
1.12      ratchov   329: void
                    330: aproc_ipos(struct aproc *p, struct abuf *ibuf, int delta)
                    331: {
                    332:        struct abuf *obuf;
                    333:
1.54      ratchov   334:        LIST_FOREACH(obuf, &p->outs, oent) {
1.12      ratchov   335:                abuf_ipos(obuf, delta);
                    336:        }
                    337: }
                    338:
                    339: void
                    340: aproc_opos(struct aproc *p, struct abuf *obuf, int delta)
                    341: {
                    342:        struct abuf *ibuf;
                    343:
1.54      ratchov   344:        LIST_FOREACH(ibuf, &p->ins, ient) {
1.12      ratchov   345:                abuf_opos(ibuf, delta);
                    346:        }
                    347: }
                    348:
1.1       ratchov   349: int
1.28      ratchov   350: aproc_inuse(struct aproc *p)
                    351: {
                    352:        struct abuf *i;
                    353:
1.54      ratchov   354:        LIST_FOREACH(i, &p->ins, ient) {
1.28      ratchov   355:                if (i->inuse)
                    356:                        return 1;
                    357:        }
1.54      ratchov   358:        LIST_FOREACH(i, &p->outs, oent) {
1.28      ratchov   359:                if (i->inuse)
                    360:                        return 1;
                    361:        }
                    362:        return 0;
                    363: }
                    364:
                    365: int
1.32      ratchov   366: aproc_depend(struct aproc *p, struct aproc *dep)
                    367: {
                    368:        struct abuf *i;
                    369:
                    370:        if (p == dep)
                    371:                return 1;
1.67      ratchov   372:        if (p == NULL)
                    373:                return 0;
1.54      ratchov   374:        LIST_FOREACH(i, &p->ins, ient) {
1.32      ratchov   375:                if (i->wproc && aproc_depend(i->wproc, dep))
                    376:                        return 1;
                    377:        }
                    378:        return 0;
                    379: }
                    380:
                    381: int
1.71      ratchov   382: rfile_do(struct aproc *p, unsigned int todo, unsigned int *done)
1.51      ratchov   383: {
1.54      ratchov   384:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.51      ratchov   385:        struct file *f = p->u.io.file;
                    386:        unsigned char *data;
1.71      ratchov   387:        unsigned int n, count, off;
1.51      ratchov   388:
                    389:        off = p->u.io.partial;
                    390:        data = abuf_wgetblk(obuf, &count, 0);
                    391:        if (count > todo)
                    392:                count = todo;
                    393:        n = file_read(f, data + off, count * obuf->bpf - off);
                    394:        if (n == 0)
                    395:                return 0;
                    396:        n += off;
                    397:        p->u.io.partial = n % obuf->bpf;
                    398:        count = n / obuf->bpf;
                    399:        if (count > 0)
                    400:                abuf_wcommit(obuf, count);
                    401:        if (done)
                    402:                *done = count;
                    403:        return 1;
                    404: }
                    405:
                    406: int
1.50      ratchov   407: rfile_in(struct aproc *p, struct abuf *ibuf_dummy)
1.49      ratchov   408: {
1.54      ratchov   409:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.49      ratchov   410:        struct file *f = p->u.io.file;
                    411:
1.51      ratchov   412:        if (!ABUF_WOK(obuf) || !(f->state & FILE_ROK))
1.50      ratchov   413:                return 0;
1.51      ratchov   414:        if (!rfile_do(p, obuf->len, NULL))
1.12      ratchov   415:                return 0;
                    416:        if (!abuf_flush(obuf))
                    417:                return 0;
                    418:        return 1;
1.1       ratchov   419: }
                    420:
                    421: int
1.41      ratchov   422: rfile_out(struct aproc *p, struct abuf *obuf)
1.1       ratchov   423: {
                    424:        struct file *f = p->u.io.file;
                    425:
1.32      ratchov   426:        if (f->state & FILE_RINUSE)
1.12      ratchov   427:                return 0;
1.51      ratchov   428:        if (!ABUF_WOK(obuf) || !(f->state & FILE_ROK))
1.1       ratchov   429:                return 0;
1.51      ratchov   430:        if (!rfile_do(p, obuf->len, NULL))
1.12      ratchov   431:                return 0;
                    432:        return 1;
1.1       ratchov   433: }
                    434:
                    435: void
1.41      ratchov   436: rfile_done(struct aproc *p)
1.1       ratchov   437: {
                    438:        struct file *f = p->u.io.file;
1.39      ratchov   439:        struct abuf *obuf;
1.1       ratchov   440:
1.30      ratchov   441:        if (f == NULL)
                    442:                return;
1.39      ratchov   443:        /*
1.51      ratchov   444:         * disconnect from file structure
                    445:         */
                    446:        f->rproc = NULL;
                    447:        p->u.io.file = NULL;
                    448:
                    449:        /*
1.39      ratchov   450:         * all buffers must be detached before deleting f->wproc,
                    451:         * because otherwise it could trigger this code again
                    452:         */
1.54      ratchov   453:        obuf = LIST_FIRST(&p->outs);
1.39      ratchov   454:        if (obuf)
                    455:                abuf_eof(obuf);
1.37      ratchov   456:        if (f->wproc) {
                    457:                aproc_del(f->wproc);
                    458:        } else
1.12      ratchov   459:                file_del(f);
1.51      ratchov   460:
                    461: #ifdef DEBUG
                    462:        if (debug_level >= 2 && p->u.io.partial > 0) {
                    463:                aproc_dbg(p);
                    464:                dbg_puts(": ");
                    465:                dbg_putu(p->u.io.partial);
                    466:                dbg_puts(" bytes lost in partial read\n");
                    467:        }
                    468: #endif
1.1       ratchov   469: }
                    470:
                    471: void
1.41      ratchov   472: rfile_eof(struct aproc *p, struct abuf *ibuf_dummy)
1.1       ratchov   473: {
1.8       ratchov   474:        aproc_del(p);
1.1       ratchov   475: }
                    476:
                    477: void
1.41      ratchov   478: rfile_hup(struct aproc *p, struct abuf *obuf)
1.1       ratchov   479: {
1.8       ratchov   480:        aproc_del(p);
1.1       ratchov   481: }
                    482:
1.41      ratchov   483: struct aproc_ops rfile_ops = {
1.43      ratchov   484:        "rfile",
1.41      ratchov   485:        rfile_in,
                    486:        rfile_out,
                    487:        rfile_eof,
                    488:        rfile_hup,
1.12      ratchov   489:        NULL, /* newin */
                    490:        NULL, /* newout */
                    491:        aproc_ipos,
                    492:        aproc_opos,
1.41      ratchov   493:        rfile_done
1.1       ratchov   494: };
                    495:
                    496: struct aproc *
1.41      ratchov   497: rfile_new(struct file *f)
1.1       ratchov   498: {
                    499:        struct aproc *p;
                    500:
1.41      ratchov   501:        p = aproc_new(&rfile_ops, f->name);
1.1       ratchov   502:        p->u.io.file = f;
1.51      ratchov   503:        p->u.io.partial = 0;
1.31      ratchov   504:        f->rproc = p;
1.1       ratchov   505:        return p;
                    506: }
                    507:
                    508: void
1.41      ratchov   509: wfile_done(struct aproc *p)
1.1       ratchov   510: {
                    511:        struct file *f = p->u.io.file;
1.39      ratchov   512:        struct abuf *ibuf;
1.1       ratchov   513:
1.30      ratchov   514:        if (f == NULL)
                    515:                return;
1.39      ratchov   516:        /*
1.51      ratchov   517:         * disconnect from file structure
                    518:         */
                    519:        f->wproc = NULL;
                    520:        p->u.io.file = NULL;
                    521:
                    522:        /*
1.39      ratchov   523:         * all buffers must be detached before deleting f->rproc,
                    524:         * because otherwise it could trigger this code again
                    525:         */
1.54      ratchov   526:        ibuf = LIST_FIRST(&p->ins);
1.39      ratchov   527:        if (ibuf)
                    528:                abuf_hup(ibuf);
1.37      ratchov   529:        if (f->rproc) {
                    530:                aproc_del(f->rproc);
                    531:        } else
1.12      ratchov   532:                file_del(f);
1.51      ratchov   533: #ifdef DEBUG
                    534:        if (debug_level >= 2 && p->u.io.partial > 0) {
                    535:                aproc_dbg(p);
                    536:                dbg_puts(": ");
                    537:                dbg_putu(p->u.io.partial);
                    538:                dbg_puts(" bytes lost in partial write\n");
                    539:        }
                    540: #endif
1.1       ratchov   541: }
                    542:
                    543: int
1.71      ratchov   544: wfile_do(struct aproc *p, unsigned int todo, unsigned int *done)
1.51      ratchov   545: {
1.54      ratchov   546:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.51      ratchov   547:        struct file *f = p->u.io.file;
                    548:        unsigned char *data;
1.71      ratchov   549:        unsigned int n, count, off;
1.51      ratchov   550:
                    551:        off = p->u.io.partial;
                    552:        data = abuf_rgetblk(ibuf, &count, 0);
                    553:        if (count > todo)
                    554:                count = todo;
                    555:        n = file_write(f, data + off, count * ibuf->bpf - off);
                    556:        if (n == 0)
                    557:                return 0;
                    558:        n += off;
                    559:        p->u.io.partial = n % ibuf->bpf;
                    560:        count = n / ibuf->bpf;
                    561:        if (count > 0)
                    562:                abuf_rdiscard(ibuf, count);
                    563:        if (done)
                    564:                *done = count;
                    565:        return 1;
                    566: }
                    567: int
1.50      ratchov   568: wfile_in(struct aproc *p, struct abuf *ibuf)
1.49      ratchov   569: {
                    570:        struct file *f = p->u.io.file;
1.1       ratchov   571:
1.32      ratchov   572:        if (f->state & FILE_WINUSE)
1.12      ratchov   573:                return 0;
1.51      ratchov   574:        if (!ABUF_ROK(ibuf) || !(f->state & FILE_WOK))
1.1       ratchov   575:                return 0;
1.51      ratchov   576:        if (!wfile_do(p, ibuf->len, NULL))
1.12      ratchov   577:                return 0;
                    578:        return 1;
1.1       ratchov   579: }
                    580:
                    581: int
1.41      ratchov   582: wfile_out(struct aproc *p, struct abuf *obuf_dummy)
1.1       ratchov   583: {
1.54      ratchov   584:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.1       ratchov   585:        struct file *f = p->u.io.file;
                    586:
1.34      ratchov   587:        if (!abuf_fill(ibuf))
1.12      ratchov   588:                return 0;
1.51      ratchov   589:        if (!ABUF_ROK(ibuf) || !(f->state & FILE_WOK))
1.12      ratchov   590:                return 0;
1.51      ratchov   591:        if (!wfile_do(p, ibuf->len, NULL))
1.12      ratchov   592:                return 0;
1.1       ratchov   593:        return 1;
                    594: }
                    595:
                    596: void
1.41      ratchov   597: wfile_eof(struct aproc *p, struct abuf *ibuf)
1.1       ratchov   598: {
1.8       ratchov   599:        aproc_del(p);
1.1       ratchov   600: }
                    601:
                    602: void
1.41      ratchov   603: wfile_hup(struct aproc *p, struct abuf *obuf_dummy)
1.1       ratchov   604: {
1.8       ratchov   605:        aproc_del(p);
1.1       ratchov   606: }
                    607:
1.41      ratchov   608: struct aproc_ops wfile_ops = {
1.43      ratchov   609:        "wfile",
1.41      ratchov   610:        wfile_in,
                    611:        wfile_out,
                    612:        wfile_eof,
                    613:        wfile_hup,
1.12      ratchov   614:        NULL, /* newin */
                    615:        NULL, /* newout */
                    616:        aproc_ipos,
                    617:        aproc_opos,
1.41      ratchov   618:        wfile_done
1.1       ratchov   619: };
                    620:
                    621: struct aproc *
1.41      ratchov   622: wfile_new(struct file *f)
1.1       ratchov   623: {
                    624:        struct aproc *p;
                    625:
1.41      ratchov   626:        p = aproc_new(&wfile_ops, f->name);
1.1       ratchov   627:        p->u.io.file = f;
1.51      ratchov   628:        p->u.io.partial = 0;
1.1       ratchov   629:        f->wproc = p;
                    630:        return p;
                    631: }
                    632:
                    633: /*
1.51      ratchov   634:  * Drop as much as possible samples from the reader end,
                    635:  * negative values mean ``insert silence''.
                    636:  */
                    637: void
                    638: mix_drop(struct abuf *buf, int extra)
                    639: {
1.71      ratchov   640:        unsigned int count;
1.51      ratchov   641:
                    642:        buf->r.mix.drop += extra;
                    643:        while (buf->r.mix.drop > 0) {
                    644:                count = buf->r.mix.drop;
                    645:                if (count > buf->used)
                    646:                        count = buf->used;
                    647:                if (count == 0) {
                    648: #ifdef DEBUG
                    649:                        if (debug_level >= 4) {
                    650:                                abuf_dbg(buf);
                    651:                                dbg_puts(": drop: no data\n");
                    652:                        }
                    653: #endif
                    654:                        return;
                    655:                }
                    656:                abuf_rdiscard(buf, count);
                    657:                buf->r.mix.drop -= count;
                    658: #ifdef DEBUG
                    659:                if (debug_level >= 4) {
                    660:                        abuf_dbg(buf);
                    661:                        dbg_puts(": dropped ");
                    662:                        dbg_putu(count);
                    663:                        dbg_puts(", to drop = ");
                    664:                        dbg_putu(buf->r.mix.drop);
                    665:                        dbg_puts("\n");
                    666:                }
                    667: #endif
                    668:        }
                    669: }
                    670:
                    671: /*
1.57      ratchov   672:  * Append the necessary amount of silence, in a way
                    673:  * obuf->w.mix.todo doesn't exceed the given value
1.1       ratchov   674:  */
                    675: void
1.71      ratchov   676: mix_bzero(struct abuf *obuf, unsigned int maxtodo)
1.1       ratchov   677: {
1.63      ratchov   678:        adata_t *odata;
1.71      ratchov   679:        unsigned int ocount, todo;
1.1       ratchov   680:
1.57      ratchov   681:        if (obuf->w.mix.todo >= maxtodo)
                    682:                return;
                    683:        todo = maxtodo - obuf->w.mix.todo;
1.63      ratchov   684:        odata = (adata_t *)abuf_wgetblk(obuf, &ocount, obuf->w.mix.todo);
1.57      ratchov   685:        if (ocount > todo)
                    686:                ocount = todo;
1.51      ratchov   687:        if (ocount == 0)
                    688:                return;
                    689:        memset(odata, 0, ocount * obuf->bpf);
                    690:        obuf->w.mix.todo += ocount;
1.42      ratchov   691: #ifdef DEBUG
                    692:        if (debug_level >= 4) {
                    693:                abuf_dbg(obuf);
                    694:                dbg_puts(": bzero(");
1.51      ratchov   695:                dbg_putu(obuf->w.mix.todo);
1.42      ratchov   696:                dbg_puts(")\n");
                    697:        }
                    698: #endif
1.1       ratchov   699: }
                    700:
                    701: /*
                    702:  * Mix an input block over an output block.
                    703:  */
1.71      ratchov   704: unsigned int
1.1       ratchov   705: mix_badd(struct abuf *ibuf, struct abuf *obuf)
                    706: {
1.63      ratchov   707:        adata_t *idata, *odata;
1.73      ratchov   708:        unsigned int i, scount, icount, ocount;
                    709:        int j, cc, cmin, cmax, istart, inext, onext, ostart, onch;
1.66      ratchov   710:        int vol, s;
1.1       ratchov   711:
1.42      ratchov   712: #ifdef DEBUG
                    713:        if (debug_level >= 4) {
                    714:                abuf_dbg(ibuf);
1.43      ratchov   715:                dbg_puts(": badd: done = ");
                    716:                dbg_putu(ibuf->r.mix.done);
                    717:                dbg_puts("/");
1.42      ratchov   718:                dbg_putu(obuf->w.mix.todo);
1.51      ratchov   719:                dbg_puts(", drop = ");
                    720:                dbg_puti(ibuf->r.mix.drop);
1.42      ratchov   721:                dbg_puts("\n");
                    722:        }
                    723: #endif
1.28      ratchov   724:        /*
1.51      ratchov   725:         * Insert silence for xrun correction
                    726:         */
1.57      ratchov   727:        while (ibuf->r.mix.drop < 0) {
1.51      ratchov   728:                icount = -ibuf->r.mix.drop;
1.57      ratchov   729:                mix_bzero(obuf, ibuf->r.mix.done + icount);
                    730:                ocount = obuf->w.mix.todo - ibuf->r.mix.done;
                    731:                if (ocount == 0)
                    732:                        return 0;
1.51      ratchov   733:                scount = (icount < ocount) ? icount : ocount;
                    734:                ibuf->r.mix.done += scount;
                    735:                ibuf->r.mix.drop += scount;
                    736:        }
                    737:
                    738:        /*
1.50      ratchov   739:         * Calculate the maximum we can read.
1.49      ratchov   740:         */
1.63      ratchov   741:        idata = (adata_t *)abuf_rgetblk(ibuf, &icount, 0);
1.50      ratchov   742:        if (icount == 0)
1.51      ratchov   743:                return 0;
1.28      ratchov   744:
                    745:        /*
1.33      ratchov   746:         * Calculate the maximum we can write.
1.28      ratchov   747:         */
1.63      ratchov   748:        odata = (adata_t *)abuf_wgetblk(obuf, &ocount, ibuf->r.mix.done);
1.1       ratchov   749:        if (ocount == 0)
1.51      ratchov   750:                return 0;
1.1       ratchov   751:
1.57      ratchov   752:        scount = (icount < ocount) ? icount : ocount;
                    753:        mix_bzero(obuf, scount + ibuf->r.mix.done);
                    754:
1.63      ratchov   755:        vol = ADATA_MUL(ibuf->r.mix.weight, ibuf->r.mix.vol);
1.52      ratchov   756:        cmin = obuf->cmin > ibuf->cmin ? obuf->cmin : ibuf->cmin;
                    757:        cmax = obuf->cmax < ibuf->cmax ? obuf->cmax : ibuf->cmax;
1.73      ratchov   758:        onch = obuf->cmax - obuf->cmin + 1;
1.52      ratchov   759:        ostart = cmin - obuf->cmin;
1.73      ratchov   760:        if (ostart > onch)
                    761:                ostart = onch;
                    762:        onext = obuf->cmax - cmax;
                    763:        if (onext > onch)
                    764:                onext = onch;
1.52      ratchov   765:        istart = cmin - ibuf->cmin;
1.73      ratchov   766:        inext = ibuf->cmax - cmax;
1.52      ratchov   767:        cc = cmax - cmin + 1;
1.13      ratchov   768:        for (i = scount; i > 0; i--) {
1.73      ratchov   769:                odata += ostart;
                    770:                idata += istart;
1.52      ratchov   771:                for (j = cc; j > 0; j--) {
1.66      ratchov   772:                        s = *odata + ADATA_MUL(*idata, vol);
                    773:                        if (s >= ADATA_UNIT)
                    774:                                s = ADATA_UNIT - 1;
                    775:                        else if (s < -ADATA_UNIT)
                    776:                                s = -ADATA_UNIT;
                    777:                        *odata = s;
1.13      ratchov   778:                        idata++;
                    779:                        odata++;
                    780:                }
                    781:                odata += onext;
1.52      ratchov   782:                idata += inext;
1.13      ratchov   783:        }
1.51      ratchov   784:        abuf_rdiscard(ibuf, scount);
                    785:        ibuf->r.mix.done += scount;
1.1       ratchov   786:
1.42      ratchov   787: #ifdef DEBUG
                    788:        if (debug_level >= 4) {
                    789:                abuf_dbg(ibuf);
                    790:                dbg_puts(": badd: done = ");
                    791:                dbg_putu(ibuf->r.mix.done);
                    792:                dbg_puts("/");
                    793:                dbg_putu(obuf->w.mix.todo);
                    794:                dbg_puts("\n");
                    795:        }
                    796: #endif
1.51      ratchov   797:        return scount;
1.1       ratchov   798: }
                    799:
1.28      ratchov   800: /*
                    801:  * Handle buffer underrun, return 0 if stream died.
                    802:  */
                    803: int
1.51      ratchov   804: mix_xrun(struct aproc *p, struct abuf *i)
1.28      ratchov   805: {
1.54      ratchov   806:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.71      ratchov   807:        unsigned int fdrop, remain;
1.31      ratchov   808:
1.36      ratchov   809:        if (i->r.mix.done > 0)
1.28      ratchov   810:                return 1;
1.36      ratchov   811:        if (i->r.mix.xrun == XRUN_ERROR) {
1.28      ratchov   812:                abuf_hup(i);
                    813:                return 0;
                    814:        }
1.51      ratchov   815:        fdrop = obuf->w.mix.todo;
1.42      ratchov   816: #ifdef DEBUG
                    817:        if (debug_level >= 3) {
                    818:                abuf_dbg(i);
                    819:                dbg_puts(": underrun, dropping ");
                    820:                dbg_putu(fdrop);
                    821:                dbg_puts(" + ");
1.51      ratchov   822:                dbg_putu(i->r.mix.drop);
1.42      ratchov   823:                dbg_puts("\n");
                    824:        }
                    825: #endif
1.51      ratchov   826:        i->r.mix.done += fdrop;
1.36      ratchov   827:        if (i->r.mix.xrun == XRUN_SYNC)
1.51      ratchov   828:                mix_drop(i, fdrop);
1.28      ratchov   829:        else {
1.51      ratchov   830:                remain = fdrop % p->u.mix.round;
                    831:                if (remain)
                    832:                        remain = p->u.mix.round - remain;
                    833:                mix_drop(i, -(int)remain);
                    834:                fdrop += remain;
                    835: #ifdef DEBUG
                    836:                if (debug_level >= 3) {
                    837:                        abuf_dbg(i);
                    838:                        dbg_puts(": underrun, adding ");
                    839:                        dbg_putu(remain);
                    840:                        dbg_puts("\n");
                    841:                }
                    842: #endif
1.28      ratchov   843:                abuf_opos(i, -(int)fdrop);
                    844:                if (i->duplex) {
1.42      ratchov   845: #ifdef DEBUG
                    846:                        if (debug_level >= 3) {
                    847:                                abuf_dbg(i->duplex);
                    848:                                dbg_puts(": full-duplex resync\n");
                    849:                        }
                    850: #endif
1.51      ratchov   851:                        sub_silence(i->duplex, -(int)fdrop);
1.28      ratchov   852:                        abuf_ipos(i->duplex, -(int)fdrop);
                    853:                }
                    854:        }
                    855:        return 1;
                    856: }
                    857:
1.1       ratchov   858: int
                    859: mix_in(struct aproc *p, struct abuf *ibuf)
                    860: {
1.54      ratchov   861:        struct abuf *i, *inext, *obuf = LIST_FIRST(&p->outs);
1.71      ratchov   862:        unsigned int odone;
                    863:        unsigned int maxwrite;
                    864:        unsigned int scount;
1.1       ratchov   865:
1.42      ratchov   866: #ifdef DEBUG
                    867:        if (debug_level >= 4) {
                    868:                aproc_dbg(p);
                    869:                dbg_puts(": used = ");
                    870:                dbg_putu(ibuf->used);
                    871:                dbg_puts("/");
                    872:                dbg_putu(ibuf->len);
1.43      ratchov   873:                dbg_puts(", done = ");
                    874:                dbg_putu(ibuf->r.mix.done);
                    875:                dbg_puts("/");
1.42      ratchov   876:                dbg_putu(obuf->w.mix.todo);
                    877:                dbg_puts("\n");
                    878:        }
                    879: #endif
1.51      ratchov   880:        if (!MIX_ROK(ibuf))
1.1       ratchov   881:                return 0;
1.51      ratchov   882:        scount = 0;
1.58      ratchov   883:        odone = obuf->len;
1.54      ratchov   884:        for (i = LIST_FIRST(&p->ins); i != NULL; i = inext) {
1.28      ratchov   885:                inext = LIST_NEXT(i, ient);
1.51      ratchov   886:                if (i->r.mix.drop >= 0 && !abuf_fill(i))
1.28      ratchov   887:                        continue; /* eof */
1.51      ratchov   888:                mix_drop(i, 0);
                    889:                scount += mix_badd(i, obuf);
1.36      ratchov   890:                if (odone > i->r.mix.done)
                    891:                        odone = i->r.mix.done;
1.28      ratchov   892:        }
1.54      ratchov   893:        if (LIST_EMPTY(&p->ins) || scount == 0)
1.28      ratchov   894:                return 0;
1.51      ratchov   895: #ifdef DEBUG
                    896:        if (debug_level >= 4) {
                    897:                aproc_dbg(p);
                    898:                dbg_puts(": maxwrite = ");
                    899:                dbg_putu(p->u.mix.maxlat);
                    900:                dbg_puts(" - ");
                    901:                dbg_putu(p->u.mix.lat);
                    902:                dbg_puts(" = ");
                    903:                dbg_putu(p->u.mix.maxlat - p->u.mix.lat);
                    904:                dbg_puts("\n");
                    905:        }
                    906: #endif
                    907:        maxwrite = p->u.mix.maxlat - p->u.mix.lat;
                    908:        if (maxwrite > 0) {
                    909:                if (odone > maxwrite)
                    910:                        odone = maxwrite;
                    911:                p->u.mix.lat += odone;
1.54      ratchov   912:                LIST_FOREACH(i, &p->ins, ient) {
1.51      ratchov   913:                        i->r.mix.done -= odone;
                    914:                }
                    915:                abuf_wcommit(obuf, odone);
                    916:                obuf->w.mix.todo -= odone;
                    917:                if (APROC_OK(p->u.mix.mon))
                    918:                        mon_snoop(p->u.mix.mon, obuf, obuf->used - odone, odone);
                    919:                if (!abuf_flush(obuf))
                    920:                        return 0; /* hup */
1.1       ratchov   921:        }
                    922:        return 1;
                    923: }
                    924:
                    925: int
                    926: mix_out(struct aproc *p, struct abuf *obuf)
                    927: {
                    928:        struct abuf *i, *inext;
1.71      ratchov   929:        unsigned int odone;
                    930:        unsigned int maxwrite;
                    931:        unsigned int scount;
1.1       ratchov   932:
1.42      ratchov   933: #ifdef DEBUG
                    934:        if (debug_level >= 4) {
                    935:                aproc_dbg(p);
                    936:                dbg_puts(": used = ");
                    937:                dbg_putu(obuf->used);
                    938:                dbg_puts("/");
                    939:                dbg_putu(obuf->len);
                    940:                dbg_puts(", todo = ");
                    941:                dbg_putu(obuf->w.mix.todo);
                    942:                dbg_puts("/");
                    943:                dbg_putu(obuf->len);
                    944:                dbg_puts("\n");
                    945:        }
                    946: #endif
1.12      ratchov   947:        if (!ABUF_WOK(obuf))
1.31      ratchov   948:                return 0;
1.51      ratchov   949: #ifdef DEBUG
                    950:        if (debug_level >= 4) {
                    951:                aproc_dbg(p);
                    952:                dbg_puts(": maxwrite = ");
                    953:                dbg_putu(p->u.mix.maxlat);
                    954:                dbg_puts(" - ");
                    955:                dbg_putu(p->u.mix.lat);
                    956:                dbg_puts(" = ");
                    957:                dbg_putu(p->u.mix.maxlat - p->u.mix.lat);
                    958:                dbg_puts("\n");
                    959:        }
                    960: #endif
                    961:        maxwrite = p->u.mix.maxlat - p->u.mix.lat;
1.57      ratchov   962:        if (maxwrite > obuf->w.mix.todo) {
                    963:                if ((p->flags & (APROC_QUIT | APROC_DROP)) == APROC_DROP)
                    964:                        mix_bzero(obuf, maxwrite);
                    965:        }
1.51      ratchov   966:        scount = 0;
1.28      ratchov   967:        odone = obuf->len;
1.54      ratchov   968:        for (i = LIST_FIRST(&p->ins); i != NULL; i = inext) {
1.1       ratchov   969:                inext = LIST_NEXT(i, ient);
1.51      ratchov   970:                if (i->r.mix.drop >= 0 && !abuf_fill(i))
1.28      ratchov   971:                        continue; /* eof */
1.51      ratchov   972:                mix_drop(i, 0);
                    973:                if (maxwrite > 0 && !MIX_ROK(i)) {
1.38      ratchov   974:                        if (p->flags & APROC_DROP) {
1.51      ratchov   975:                                if (!mix_xrun(p, i))
1.5       ratchov   976:                                        continue;
                    977:                        }
1.3       ratchov   978:                } else
1.51      ratchov   979:                        scount += mix_badd(i, obuf);
1.36      ratchov   980:                if (odone > i->r.mix.done)
                    981:                        odone = i->r.mix.done;
1.28      ratchov   982:        }
1.57      ratchov   983:        if (LIST_EMPTY(&p->ins) && obuf->w.mix.todo == 0) {
1.38      ratchov   984:                if (p->flags & APROC_QUIT) {
1.28      ratchov   985:                        aproc_del(p);
                    986:                        return 0;
                    987:                }
1.38      ratchov   988:                if (!(p->flags & APROC_DROP))
1.28      ratchov   989:                        return 0;
1.57      ratchov   990:        }
                    991:        if (odone > obuf->w.mix.todo)
1.36      ratchov   992:                odone = obuf->w.mix.todo;
1.57      ratchov   993:        if (odone > maxwrite)
                    994:                odone = maxwrite;
                    995:        if (odone > 0) {
1.51      ratchov   996:                p->u.mix.lat += odone;
1.54      ratchov   997:                LIST_FOREACH(i, &p->ins, ient) {
1.51      ratchov   998:                        i->r.mix.done -= odone;
                    999:                }
                   1000:                abuf_wcommit(obuf, odone);
                   1001:                obuf->w.mix.todo -= odone;
                   1002:                if (APROC_OK(p->u.mix.mon))
                   1003:                        mon_snoop(p->u.mix.mon, obuf, obuf->used - odone, odone);
1.49      ratchov  1004:        }
1.55      ratchov  1005:        if (LIST_EMPTY(&p->ins))
                   1006:                p->u.mix.idle += odone;
1.51      ratchov  1007:        if (scount == 0)
1.50      ratchov  1008:                return 0;
1.1       ratchov  1009:        return 1;
                   1010: }
                   1011:
                   1012: void
                   1013: mix_eof(struct aproc *p, struct abuf *ibuf)
                   1014: {
1.62      ratchov  1015:        struct abuf *i, *obuf = LIST_FIRST(&p->outs);
1.71      ratchov  1016:        unsigned int odone;
1.1       ratchov  1017:
1.12      ratchov  1018:        mix_setmaster(p);
                   1019:
1.28      ratchov  1020:        if (!aproc_inuse(p)) {
1.42      ratchov  1021: #ifdef DEBUG
                   1022:                if (debug_level >= 3) {
                   1023:                        aproc_dbg(p);
                   1024:                        dbg_puts(": running other streams\n");
                   1025:                }
                   1026: #endif
1.28      ratchov  1027:                /*
1.33      ratchov  1028:                 * Find a blocked input.
1.28      ratchov  1029:                 */
                   1030:                odone = obuf->len;
1.62      ratchov  1031:                LIST_FOREACH(i, &p->ins, ient) {
                   1032:                        /*
                   1033:                         * abuf_fill() may trigger mix_eof(), do the job
                   1034:                         * and possibly reorder the list
                   1035:                         */
1.51      ratchov  1036:                        if (!abuf_fill(i))
1.62      ratchov  1037:                                return;
1.51      ratchov  1038:                        if (MIX_ROK(i) && i->r.mix.done < obuf->w.mix.todo) {
1.28      ratchov  1039:                                abuf_run(i);
                   1040:                                return;
                   1041:                        }
1.36      ratchov  1042:                        if (odone > i->r.mix.done)
                   1043:                                odone = i->r.mix.done;
1.28      ratchov  1044:                }
                   1045:                /*
1.33      ratchov  1046:                 * No blocked inputs. Check if output is blocked.
1.28      ratchov  1047:                 */
1.54      ratchov  1048:                if (LIST_EMPTY(&p->ins) || odone == obuf->w.mix.todo)
1.28      ratchov  1049:                        abuf_run(obuf);
                   1050:        }
1.1       ratchov  1051: }
                   1052:
                   1053: void
                   1054: mix_hup(struct aproc *p, struct abuf *obuf)
                   1055: {
                   1056:        aproc_del(p);
                   1057: }
                   1058:
                   1059: void
                   1060: mix_newin(struct aproc *p, struct abuf *ibuf)
                   1061: {
1.22      ratchov  1062:        p->u.mix.idle = 0;
1.36      ratchov  1063:        ibuf->r.mix.done = 0;
                   1064:        ibuf->r.mix.vol = ADATA_UNIT;
                   1065:        ibuf->r.mix.weight = ADATA_UNIT;
                   1066:        ibuf->r.mix.maxweight = ADATA_UNIT;
                   1067:        ibuf->r.mix.xrun = XRUN_IGNORE;
1.51      ratchov  1068:        ibuf->r.mix.drop = 0;
1.1       ratchov  1069: }
                   1070:
                   1071: void
                   1072: mix_newout(struct aproc *p, struct abuf *obuf)
                   1073: {
1.42      ratchov  1074: #ifdef DEBUG
                   1075:        if (debug_level >= 3) {
                   1076:                aproc_dbg(p);
1.61      ratchov  1077:                dbg_puts(": newout, will use ");
1.51      ratchov  1078:                dbg_putu(obuf->len);
1.61      ratchov  1079:                dbg_puts(" fr\n");
1.42      ratchov  1080:        }
                   1081: #endif
1.36      ratchov  1082:        obuf->w.mix.todo = 0;
1.1       ratchov  1083: }
                   1084:
1.12      ratchov  1085: void
                   1086: mix_opos(struct aproc *p, struct abuf *obuf, int delta)
                   1087: {
1.51      ratchov  1088:        p->u.mix.lat -= delta;
1.42      ratchov  1089: #ifdef DEBUG
                   1090:        if (debug_level >= 4) {
                   1091:                aproc_dbg(p);
                   1092:                dbg_puts(": opos: lat = ");
                   1093:                dbg_puti(p->u.mix.lat);
                   1094:                dbg_puts("/");
                   1095:                dbg_puti(p->u.mix.maxlat);
1.51      ratchov  1096:                dbg_puts("\n");
1.42      ratchov  1097:        }
                   1098: #endif
1.12      ratchov  1099:        aproc_opos(p, obuf, delta);
1.51      ratchov  1100:        if (APROC_OK(p->u.mix.mon))
                   1101:                p->u.mix.mon->ops->ipos(p->u.mix.mon, NULL, delta);
1.12      ratchov  1102: }
                   1103:
1.1       ratchov  1104: struct aproc_ops mix_ops = {
1.12      ratchov  1105:        "mix",
                   1106:        mix_in,
                   1107:        mix_out,
                   1108:        mix_eof,
                   1109:        mix_hup,
                   1110:        mix_newin,
                   1111:        mix_newout,
                   1112:        aproc_ipos,
                   1113:        mix_opos,
                   1114:        NULL
1.1       ratchov  1115: };
                   1116:
                   1117: struct aproc *
1.71      ratchov  1118: mix_new(char *name, int maxlat, unsigned int round,
                   1119:     unsigned int autovol, unsigned int master)
1.1       ratchov  1120: {
                   1121:        struct aproc *p;
                   1122:
1.12      ratchov  1123:        p = aproc_new(&mix_ops, name);
1.22      ratchov  1124:        p->u.mix.idle = 0;
1.12      ratchov  1125:        p->u.mix.lat = 0;
1.51      ratchov  1126:        p->u.mix.round = round;
1.12      ratchov  1127:        p->u.mix.maxlat = maxlat;
1.57      ratchov  1128:        p->u.mix.mon = NULL;
1.65      ratchov  1129:        p->u.mix.autovol = autovol;
1.70      ratchov  1130:        p->u.mix.master = master;
1.1       ratchov  1131:        return p;
1.10      ratchov  1132: }
                   1133:
                   1134: /*
1.33      ratchov  1135:  * Normalize input levels.
1.10      ratchov  1136:  */
                   1137: void
                   1138: mix_setmaster(struct aproc *p)
                   1139: {
1.71      ratchov  1140:        unsigned int n;
1.40      ratchov  1141:        struct abuf *i, *j;
1.24      ratchov  1142:        int weight;
1.65      ratchov  1143:
1.54      ratchov  1144:        LIST_FOREACH(i, &p->ins, ient) {
1.69      ratchov  1145:                weight = ADATA_UNIT;
                   1146:                if (p->u.mix.autovol) {
                   1147:                        /*
                   1148:                         * count the number of inputs that have
                   1149:                         * overlapping channel sets
                   1150:                         */
                   1151:                        n = 0;
                   1152:                        LIST_FOREACH(j, &p->ins, ient) {
                   1153:                                if (i->cmin <= j->cmax && i->cmax >= j->cmin)
                   1154:                                        n++;
1.40      ratchov  1155:                        }
1.69      ratchov  1156:                        weight /= n;
1.40      ratchov  1157:                }
                   1158:                if (weight > i->r.mix.maxweight)
                   1159:                        weight = i->r.mix.maxweight;
1.70      ratchov  1160:                i->r.mix.weight = ADATA_MUL(weight, p->u.mix.master);
1.42      ratchov  1161: #ifdef DEBUG
                   1162:                if (debug_level >= 3) {
                   1163:                        abuf_dbg(i);
                   1164:                        dbg_puts(": setmaster: ");
                   1165:                        dbg_puti(i->r.mix.weight);
                   1166:                        dbg_puts("/");
                   1167:                        dbg_puti(i->r.mix.maxweight);
                   1168:                        dbg_puts("\n");
                   1169:                }
                   1170: #endif
1.24      ratchov  1171:        }
1.1       ratchov  1172: }
                   1173:
1.22      ratchov  1174: void
                   1175: mix_clear(struct aproc *p)
                   1176: {
1.54      ratchov  1177:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.22      ratchov  1178:
                   1179:        p->u.mix.lat = 0;
1.36      ratchov  1180:        obuf->w.mix.todo = 0;
1.22      ratchov  1181: }
                   1182:
1.1       ratchov  1183: /*
1.57      ratchov  1184:  * Gracefully terminate the mixer: raise the APROC_QUIT flag
                   1185:  * and let the rest of the code do the job. If there are neither
                   1186:  * inputs nor uncommited data, then terminate right away
                   1187:  */
                   1188: void
                   1189: mix_quit(struct aproc *p)
                   1190: {
                   1191:        struct abuf *obuf = LIST_FIRST(&p->outs);
                   1192:
                   1193:        p->flags |= APROC_QUIT;
                   1194:
                   1195:        /*
                   1196:         * eof the last input will trigger aproc_del()
                   1197:         */
                   1198:        if (!LIST_EMPTY(&p->ins) || obuf->w.mix.todo > 0)
                   1199:                return;
                   1200:        aproc_del(p);
                   1201: }
                   1202:
                   1203: /*
1.51      ratchov  1204:  * Append as much as possible silence on the writer end
                   1205:  */
                   1206: void
                   1207: sub_silence(struct abuf *buf, int extra)
                   1208: {
                   1209:        unsigned char *data;
1.71      ratchov  1210:        unsigned int count;
1.51      ratchov  1211:
                   1212:        buf->w.sub.silence += extra;
                   1213:        if (buf->w.sub.silence > 0) {
                   1214:                data = abuf_wgetblk(buf, &count, 0);
                   1215:                if (count >= buf->w.sub.silence)
                   1216:                        count = buf->w.sub.silence;
                   1217:                if (count == 0) {
                   1218: #ifdef DEBUG
                   1219:                        if (debug_level >= 4) {
                   1220:                                abuf_dbg(buf);
                   1221:                                dbg_puts(": no space for silence\n");
                   1222:                        }
                   1223: #endif
                   1224:                        return;
                   1225:                }
                   1226:                memset(data, 0, count * buf->bpf);
                   1227:                abuf_wcommit(buf, count);
                   1228:                buf->w.sub.silence -= count;
                   1229: #ifdef DEBUG
                   1230:                if (debug_level >= 4) {
                   1231:                        abuf_dbg(buf);
                   1232:                        dbg_puts(": appended ");
                   1233:                        dbg_putu(count);
                   1234:                        dbg_puts(", remaining silence = ");
                   1235:                        dbg_putu(buf->w.sub.silence);
                   1236:                        dbg_puts("\n");
                   1237:                }
                   1238: #endif
                   1239:        }
                   1240: }
                   1241:
                   1242: /*
1.1       ratchov  1243:  * Copy data from ibuf to obuf.
                   1244:  */
                   1245: void
                   1246: sub_bcopy(struct abuf *ibuf, struct abuf *obuf)
                   1247: {
1.63      ratchov  1248:        adata_t *idata, *odata;
1.73      ratchov  1249:        unsigned int i, icount, ocount, scount;
                   1250:        int j, cc, cmin, cmax, istart, inext, onext, ostart, onch;
1.1       ratchov  1251:
1.51      ratchov  1252:        /*
                   1253:         * Drop samples for xrun correction
                   1254:         */
                   1255:        if (obuf->w.sub.silence < 0) {
                   1256:                scount = -obuf->w.sub.silence;
                   1257:                if (scount > ibuf->used)
                   1258:                        scount = ibuf->used;
                   1259:                obuf->w.sub.done += scount;
                   1260:                obuf->w.sub.silence += scount;
                   1261:        }
                   1262:
1.63      ratchov  1263:        idata = (adata_t *)abuf_rgetblk(ibuf, &icount, obuf->w.sub.done);
1.1       ratchov  1264:        if (icount == 0)
                   1265:                return;
1.63      ratchov  1266:        odata = (adata_t *)abuf_wgetblk(obuf, &ocount, 0);
1.1       ratchov  1267:        if (ocount == 0)
                   1268:                return;
1.52      ratchov  1269:        cmin = obuf->cmin > ibuf->cmin ? obuf->cmin : ibuf->cmin;
                   1270:        cmax = obuf->cmax < ibuf->cmax ? obuf->cmax : ibuf->cmax;
1.73      ratchov  1271:        onch = obuf->cmax - obuf->cmin + 1;
1.52      ratchov  1272:        ostart = cmin - obuf->cmin;
1.73      ratchov  1273:        if (ostart > onch)
                   1274:                ostart = onch;
                   1275:        onext = obuf->cmax - cmax;
                   1276:        if (onext > onch)
                   1277:                onext = onch;
1.52      ratchov  1278:        istart = cmin - ibuf->cmin;
1.73      ratchov  1279:        inext = ibuf->cmax - cmax;
1.52      ratchov  1280:        cc = cmax - cmin + 1;
1.1       ratchov  1281:        scount = (icount < ocount) ? icount : ocount;
1.13      ratchov  1282:        for (i = scount; i > 0; i--) {
1.73      ratchov  1283:                idata += istart;
1.52      ratchov  1284:                for (j = ostart; j > 0; j--)
                   1285:                        *odata++ = 0x1111;
                   1286:                for (j = cc; j > 0; j--) {
1.13      ratchov  1287:                        *odata = *idata;
                   1288:                        odata++;
                   1289:                        idata++;
                   1290:                }
1.52      ratchov  1291:                for (j = onext; j > 0; j--)
                   1292:                        *odata++ = 0x2222;
1.13      ratchov  1293:                idata += inext;
                   1294:        }
1.51      ratchov  1295:        abuf_wcommit(obuf, scount);
                   1296:        obuf->w.sub.done += scount;
1.42      ratchov  1297: #ifdef DEBUG
                   1298:        if (debug_level >= 4) {
                   1299:                abuf_dbg(obuf);
                   1300:                dbg_puts(": bcopy ");
                   1301:                dbg_putu(scount);
1.51      ratchov  1302:                dbg_puts("\n");
1.42      ratchov  1303:        }
                   1304: #endif
1.1       ratchov  1305: }
                   1306:
1.28      ratchov  1307: /*
1.33      ratchov  1308:  * Handle buffer overruns. Return 0 if the stream died.
1.28      ratchov  1309:  */
                   1310: int
1.51      ratchov  1311: sub_xrun(struct aproc *p, struct abuf *i)
1.28      ratchov  1312: {
1.54      ratchov  1313:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.71      ratchov  1314:        unsigned int fdrop, remain;
1.28      ratchov  1315:
1.36      ratchov  1316:        if (i->w.sub.done > 0)
1.28      ratchov  1317:                return 1;
1.36      ratchov  1318:        if (i->w.sub.xrun == XRUN_ERROR) {
1.28      ratchov  1319:                abuf_eof(i);
                   1320:                return 0;
                   1321:        }
1.51      ratchov  1322:        fdrop = ibuf->used;
1.42      ratchov  1323: #ifdef DEBUG
                   1324:        if (debug_level >= 3) {
                   1325:                abuf_dbg(i);
                   1326:                dbg_puts(": overrun, silence ");
                   1327:                dbg_putu(fdrop);
                   1328:                dbg_puts(" + ");
1.51      ratchov  1329:                dbg_putu(i->w.sub.silence);
1.42      ratchov  1330:                dbg_puts("\n");
                   1331:        }
                   1332: #endif
1.51      ratchov  1333:        i->w.sub.done += fdrop;
1.36      ratchov  1334:        if (i->w.sub.xrun == XRUN_SYNC)
1.51      ratchov  1335:                sub_silence(i, fdrop);
1.28      ratchov  1336:        else {
1.51      ratchov  1337:                remain = fdrop % p->u.sub.round;
                   1338:                if (remain)
                   1339:                        remain = p->u.sub.round - remain;
                   1340:                sub_silence(i, -(int)remain);
                   1341:                fdrop += remain;
                   1342: #ifdef DEBUG
                   1343:                if (debug_level >= 3) {
                   1344:                        abuf_dbg(i);
                   1345:                        dbg_puts(": overrun, adding ");
                   1346:                        dbg_putu(remain);
                   1347:                        dbg_puts("\n");
                   1348:                }
                   1349: #endif
                   1350:
1.28      ratchov  1351:                abuf_ipos(i, -(int)fdrop);
                   1352:                if (i->duplex) {
1.42      ratchov  1353: #ifdef DEBUG
                   1354:                        if (debug_level >= 3) {
                   1355:                                abuf_dbg(i->duplex);
                   1356:                                dbg_puts(": full-duplex resync\n");
                   1357:                        }
                   1358: #endif
1.51      ratchov  1359:                        mix_drop(i->duplex, -(int)fdrop);
1.28      ratchov  1360:                        abuf_opos(i->duplex, -(int)fdrop);
                   1361:                }
                   1362:        }
                   1363:        return 1;
                   1364: }
                   1365:
1.1       ratchov  1366: int
                   1367: sub_in(struct aproc *p, struct abuf *ibuf)
                   1368: {
                   1369:        struct abuf *i, *inext;
1.71      ratchov  1370:        unsigned int idone;
1.31      ratchov  1371:
1.12      ratchov  1372:        if (!ABUF_ROK(ibuf))
                   1373:                return 0;
1.28      ratchov  1374:        idone = ibuf->len;
1.54      ratchov  1375:        for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) {
1.1       ratchov  1376:                inext = LIST_NEXT(i, oent);
1.51      ratchov  1377:                sub_silence(i, 0);
                   1378:                if (!SUB_WOK(i)) {
1.38      ratchov  1379:                        if (p->flags & APROC_DROP) {
1.51      ratchov  1380:                                if (!sub_xrun(p, i))
1.5       ratchov  1381:                                        continue;
                   1382:                        }
1.12      ratchov  1383:                } else
1.1       ratchov  1384:                        sub_bcopy(ibuf, i);
1.36      ratchov  1385:                if (idone > i->w.sub.done)
                   1386:                        idone = i->w.sub.done;
1.12      ratchov  1387:                if (!abuf_flush(i))
                   1388:                        continue;
1.1       ratchov  1389:        }
1.54      ratchov  1390:        if (LIST_EMPTY(&p->outs)) {
1.38      ratchov  1391:                if (p->flags & APROC_QUIT) {
1.28      ratchov  1392:                        aproc_del(p);
                   1393:                        return 0;
                   1394:                }
1.38      ratchov  1395:                if (!(p->flags & APROC_DROP))
1.28      ratchov  1396:                        return 0;
                   1397:                idone = ibuf->used;
1.51      ratchov  1398:                p->u.sub.idle += idone;
1.28      ratchov  1399:        }
                   1400:        if (idone == 0)
                   1401:                return 0;
1.54      ratchov  1402:        LIST_FOREACH(i, &p->outs, oent) {
1.36      ratchov  1403:                i->w.sub.done -= idone;
1.1       ratchov  1404:        }
1.28      ratchov  1405:        abuf_rdiscard(ibuf, idone);
1.51      ratchov  1406:        abuf_opos(ibuf, idone);
                   1407:        p->u.sub.lat -= idone;
1.12      ratchov  1408:        return 1;
1.1       ratchov  1409: }
                   1410:
                   1411: int
                   1412: sub_out(struct aproc *p, struct abuf *obuf)
                   1413: {
1.54      ratchov  1414:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.1       ratchov  1415:        struct abuf *i, *inext;
1.71      ratchov  1416:        unsigned int idone;
1.1       ratchov  1417:
1.51      ratchov  1418:        if (!SUB_WOK(obuf))
1.12      ratchov  1419:                return 0;
1.28      ratchov  1420:        if (!abuf_fill(ibuf))
                   1421:                return 0; /* eof */
                   1422:        idone = ibuf->len;
1.54      ratchov  1423:        for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) {
1.12      ratchov  1424:                inext = LIST_NEXT(i, oent);
1.51      ratchov  1425:                sub_silence(i, 0);
1.28      ratchov  1426:                sub_bcopy(ibuf, i);
1.36      ratchov  1427:                if (idone > i->w.sub.done)
                   1428:                        idone = i->w.sub.done;
1.12      ratchov  1429:                if (!abuf_flush(i))
                   1430:                        continue;
1.1       ratchov  1431:        }
1.54      ratchov  1432:        if (LIST_EMPTY(&p->outs) || idone == 0)
1.28      ratchov  1433:                return 0;
1.54      ratchov  1434:        LIST_FOREACH(i, &p->outs, oent) {
1.36      ratchov  1435:                i->w.sub.done -= idone;
1.1       ratchov  1436:        }
1.28      ratchov  1437:        abuf_rdiscard(ibuf, idone);
1.51      ratchov  1438:        abuf_opos(ibuf, idone);
                   1439:        p->u.sub.lat -= idone;
1.1       ratchov  1440:        return 1;
                   1441: }
                   1442:
                   1443: void
                   1444: sub_eof(struct aproc *p, struct abuf *ibuf)
                   1445: {
1.8       ratchov  1446:        aproc_del(p);
1.1       ratchov  1447: }
                   1448:
                   1449: void
                   1450: sub_hup(struct aproc *p, struct abuf *obuf)
                   1451: {
1.62      ratchov  1452:        struct abuf *i, *ibuf = LIST_FIRST(&p->ins);
1.71      ratchov  1453:        unsigned int idone;
1.1       ratchov  1454:
1.28      ratchov  1455:        if (!aproc_inuse(p)) {
1.42      ratchov  1456: #ifdef DEBUG
                   1457:                if (debug_level >= 3) {
                   1458:                        aproc_dbg(p);
                   1459:                        dbg_puts(": running other streams\n");
                   1460:                }
                   1461: #endif
1.28      ratchov  1462:                /*
1.33      ratchov  1463:                 * Find a blocked output.
1.28      ratchov  1464:                 */
                   1465:                idone = ibuf->len;
1.62      ratchov  1466:                LIST_FOREACH(i, &p->outs, oent) {
                   1467:                        /*
                   1468:                         * abuf_flush() may trigger sub_hup(), do the job
                   1469:                         * and possibly reorder the list
                   1470:                         */
1.51      ratchov  1471:                        if (!abuf_flush(i))
1.62      ratchov  1472:                                return;
1.51      ratchov  1473:                        if (SUB_WOK(i) && i->w.sub.done < ibuf->used) {
1.28      ratchov  1474:                                abuf_run(i);
                   1475:                                return;
                   1476:                        }
1.36      ratchov  1477:                        if (idone > i->w.sub.done)
                   1478:                                idone = i->w.sub.done;
1.28      ratchov  1479:                }
                   1480:                /*
1.33      ratchov  1481:                 * No blocked outputs. Check if input is blocked.
1.28      ratchov  1482:                 */
1.54      ratchov  1483:                if (LIST_EMPTY(&p->outs) || idone == ibuf->used)
1.28      ratchov  1484:                        abuf_run(ibuf);
                   1485:        }
1.1       ratchov  1486: }
                   1487:
                   1488: void
                   1489: sub_newout(struct aproc *p, struct abuf *obuf)
                   1490: {
1.22      ratchov  1491:        p->u.sub.idle = 0;
1.36      ratchov  1492:        obuf->w.sub.done = 0;
                   1493:        obuf->w.sub.xrun = XRUN_IGNORE;
1.51      ratchov  1494:        obuf->w.sub.silence = 0;
1.1       ratchov  1495: }
                   1496:
1.12      ratchov  1497: void
                   1498: sub_ipos(struct aproc *p, struct abuf *ibuf, int delta)
                   1499: {
                   1500:        p->u.sub.lat += delta;
1.42      ratchov  1501: #ifdef DEBUG
                   1502:        if (debug_level >= 4) {
                   1503:                aproc_dbg(p);
                   1504:                dbg_puts(": ipos: lat = ");
                   1505:                dbg_puti(p->u.sub.lat);
                   1506:                dbg_puts("/");
                   1507:                dbg_puti(p->u.sub.maxlat);
1.51      ratchov  1508:                dbg_puts("\n");
1.42      ratchov  1509:        }
                   1510: #endif
1.12      ratchov  1511:        aproc_ipos(p, ibuf, delta);
                   1512: }
                   1513:
1.1       ratchov  1514: struct aproc_ops sub_ops = {
1.12      ratchov  1515:        "sub",
                   1516:        sub_in,
                   1517:        sub_out,
                   1518:        sub_eof,
                   1519:        sub_hup,
                   1520:        NULL,
                   1521:        sub_newout,
                   1522:        sub_ipos,
                   1523:        aproc_opos,
                   1524:        NULL
1.1       ratchov  1525: };
                   1526:
                   1527: struct aproc *
1.71      ratchov  1528: sub_new(char *name, int maxlat, unsigned int round)
1.1       ratchov  1529: {
                   1530:        struct aproc *p;
                   1531:
1.12      ratchov  1532:        p = aproc_new(&sub_ops, name);
1.22      ratchov  1533:        p->u.sub.idle = 0;
1.12      ratchov  1534:        p->u.sub.lat = 0;
1.51      ratchov  1535:        p->u.sub.round = round;
1.12      ratchov  1536:        p->u.sub.maxlat = maxlat;
1.1       ratchov  1537:        return p;
1.22      ratchov  1538: }
                   1539:
                   1540: void
                   1541: sub_clear(struct aproc *p)
                   1542: {
1.51      ratchov  1543:        p->u.sub.lat = 0;
1.1       ratchov  1544: }
                   1545:
                   1546: /*
                   1547:  * Convert one block.
                   1548:  */
                   1549: void
1.15      ratchov  1550: resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
                   1551: {
1.71      ratchov  1552:        unsigned int inch;
1.63      ratchov  1553:        adata_t *idata;
1.71      ratchov  1554:        unsigned int oblksz;
                   1555:        unsigned int ifr;
                   1556:        unsigned int onch;
1.63      ratchov  1557:        int s, ds, diff;
                   1558:        adata_t *odata;
1.71      ratchov  1559:        unsigned int iblksz;
                   1560:        unsigned int ofr;
                   1561:        unsigned int c;
1.63      ratchov  1562:        adata_t *ctxbuf, *ctx;
1.71      ratchov  1563:        unsigned int ctx_start;
                   1564:        unsigned int icount, ocount;
1.15      ratchov  1565:
                   1566:        /*
                   1567:         * Calculate max frames readable at once from the input buffer.
                   1568:         */
1.63      ratchov  1569:        idata = (adata_t *)abuf_rgetblk(ibuf, &icount, 0);
1.51      ratchov  1570:        ifr = icount;
1.15      ratchov  1571:
1.63      ratchov  1572:        odata = (adata_t *)abuf_wgetblk(obuf, &ocount, 0);
1.51      ratchov  1573:        ofr = ocount;
1.15      ratchov  1574:
                   1575:        /*
                   1576:         * Partially copy structures into local variables, to avoid
                   1577:         * unnecessary indirections; this also allows the compiler to
                   1578:         * order local variables more "cache-friendly".
                   1579:         */
1.27      ratchov  1580:        diff = p->u.resamp.diff;
1.15      ratchov  1581:        inch = ibuf->cmax - ibuf->cmin + 1;
1.26      ratchov  1582:        iblksz = p->u.resamp.iblksz;
1.15      ratchov  1583:        onch = obuf->cmax - obuf->cmin + 1;
1.26      ratchov  1584:        oblksz = p->u.resamp.oblksz;
1.15      ratchov  1585:        ctxbuf = p->u.resamp.ctx;
1.27      ratchov  1586:        ctx_start = p->u.resamp.ctx_start;
1.15      ratchov  1587:
                   1588:        /*
                   1589:         * Start conversion.
                   1590:         */
1.42      ratchov  1591: #ifdef DEBUG
                   1592:        if (debug_level >= 4) {
                   1593:                aproc_dbg(p);
1.61      ratchov  1594:                dbg_puts(": starting diff = ");
1.46      ratchov  1595:                dbg_puti(diff);
                   1596:                dbg_puts(", ifr = ");
1.42      ratchov  1597:                dbg_putu(ifr);
                   1598:                dbg_puts(", ofr = ");
1.46      ratchov  1599:                dbg_putu(ofr);
1.42      ratchov  1600:                dbg_puts(" fr\n");
                   1601:        }
                   1602: #endif
1.15      ratchov  1603:        for (;;) {
1.27      ratchov  1604:                if (diff < 0) {
1.51      ratchov  1605:                        if (ifr == 0)
                   1606:                                break;
1.27      ratchov  1607:                        ctx_start ^= 1;
                   1608:                        ctx = ctxbuf + ctx_start;
1.15      ratchov  1609:                        for (c = inch; c > 0; c--) {
1.29      ratchov  1610:                                *ctx = *idata++;
1.27      ratchov  1611:                                ctx += RESAMP_NCTX;
1.15      ratchov  1612:                        }
1.27      ratchov  1613:                        diff += oblksz;
1.51      ratchov  1614:                        ifr--;
1.56      ratchov  1615:                } else if (diff > 0) {
1.51      ratchov  1616:                        if (ofr == 0)
1.50      ratchov  1617:                                break;
1.27      ratchov  1618:                        ctx = ctxbuf;
                   1619:                        for (c = onch; c > 0; c--) {
1.63      ratchov  1620:                                s = ctx[ctx_start];
                   1621:                                ds = ctx[ctx_start ^ 1] - s;
1.27      ratchov  1622:                                ctx += RESAMP_NCTX;
1.63      ratchov  1623:                                *odata++ = s + ADATA_MULDIV(ds, diff, oblksz);
1.27      ratchov  1624:                        }
                   1625:                        diff -= iblksz;
1.56      ratchov  1626:                        ofr--;
                   1627:                } else {
                   1628:                        if (ifr == 0 || ofr == 0)
                   1629:                                break;
                   1630:                        ctx = ctxbuf + ctx_start;
                   1631:                        for (c = onch; c > 0; c--) {
                   1632:                                *odata++ = *ctx;
                   1633:                                ctx += RESAMP_NCTX;
                   1634:                        }
                   1635:                        ctx_start ^= 1;
                   1636:                        ctx = ctxbuf + ctx_start;
                   1637:                        for (c = inch; c > 0; c--) {
                   1638:                                *ctx = *idata++;
                   1639:                                ctx += RESAMP_NCTX;
                   1640:                        }
                   1641:                        diff -= iblksz;
                   1642:                        diff += oblksz;
                   1643:                        ifr--;
1.51      ratchov  1644:                        ofr--;
1.15      ratchov  1645:                }
                   1646:        }
1.27      ratchov  1647:        p->u.resamp.diff = diff;
                   1648:        p->u.resamp.ctx_start = ctx_start;
1.42      ratchov  1649: #ifdef DEBUG
                   1650:        if (debug_level >= 4) {
                   1651:                aproc_dbg(p);
1.61      ratchov  1652:                dbg_puts(": done delta = ");
1.46      ratchov  1653:                dbg_puti(diff);
                   1654:                dbg_puts(", ifr = ");
1.42      ratchov  1655:                dbg_putu(ifr);
                   1656:                dbg_puts(", ofr = ");
1.46      ratchov  1657:                dbg_putu(ofr);
1.42      ratchov  1658:                dbg_puts(" fr\n");
                   1659:        }
                   1660: #endif
1.15      ratchov  1661:        /*
                   1662:         * Update FIFO pointers.
                   1663:         */
1.51      ratchov  1664:        icount -= ifr;
                   1665:        ocount -= ofr;
1.15      ratchov  1666:        abuf_rdiscard(ibuf, icount);
                   1667:        abuf_wcommit(obuf, ocount);
                   1668: }
                   1669:
                   1670: int
                   1671: resamp_in(struct aproc *p, struct abuf *ibuf)
                   1672: {
1.54      ratchov  1673:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.15      ratchov  1674:
                   1675:        if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
                   1676:                return 0;
                   1677:        resamp_bcopy(p, ibuf, obuf);
                   1678:        if (!abuf_flush(obuf))
                   1679:                return 0;
                   1680:        return 1;
                   1681: }
                   1682:
                   1683: int
                   1684: resamp_out(struct aproc *p, struct abuf *obuf)
                   1685: {
1.54      ratchov  1686:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.15      ratchov  1687:
                   1688:        if (!abuf_fill(ibuf))
                   1689:                return 0;
                   1690:        if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
                   1691:                return 0;
                   1692:        resamp_bcopy(p, ibuf, obuf);
                   1693:        return 1;
                   1694: }
                   1695:
                   1696: void
                   1697: resamp_eof(struct aproc *p, struct abuf *ibuf)
                   1698: {
                   1699:        aproc_del(p);
                   1700: }
                   1701:
                   1702: void
                   1703: resamp_hup(struct aproc *p, struct abuf *obuf)
                   1704: {
                   1705:        aproc_del(p);
                   1706: }
                   1707:
                   1708: void
                   1709: resamp_ipos(struct aproc *p, struct abuf *ibuf, int delta)
                   1710: {
1.54      ratchov  1711:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.15      ratchov  1712:        long long ipos;
1.45      ratchov  1713:
                   1714:        ipos = (long long)delta * p->u.resamp.oblksz + p->u.resamp.idelta;
                   1715:        p->u.resamp.idelta = ipos % p->u.resamp.iblksz;
                   1716:        abuf_ipos(obuf, ipos / (int)p->u.resamp.iblksz);
1.15      ratchov  1717: }
                   1718:
                   1719: void
                   1720: resamp_opos(struct aproc *p, struct abuf *obuf, int delta)
                   1721: {
1.54      ratchov  1722:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.15      ratchov  1723:        long long opos;
                   1724:
1.45      ratchov  1725:        opos = (long long)delta * p->u.resamp.iblksz + p->u.resamp.odelta;
                   1726:        p->u.resamp.odelta = opos % p->u.resamp.oblksz;
                   1727:        abuf_opos(ibuf, opos / p->u.resamp.oblksz);
1.15      ratchov  1728: }
                   1729:
                   1730: struct aproc_ops resamp_ops = {
                   1731:        "resamp",
                   1732:        resamp_in,
                   1733:        resamp_out,
                   1734:        resamp_eof,
                   1735:        resamp_hup,
                   1736:        NULL,
                   1737:        NULL,
                   1738:        resamp_ipos,
                   1739:        resamp_opos,
                   1740:        NULL
                   1741: };
                   1742:
                   1743: struct aproc *
1.71      ratchov  1744: resamp_new(char *name, unsigned int iblksz, unsigned int oblksz)
1.15      ratchov  1745: {
                   1746:        struct aproc *p;
1.71      ratchov  1747:        unsigned int i;
1.15      ratchov  1748:
                   1749:        p = aproc_new(&resamp_ops, name);
1.26      ratchov  1750:        p->u.resamp.iblksz = iblksz;
                   1751:        p->u.resamp.oblksz = oblksz;
1.48      ratchov  1752:        p->u.resamp.diff = 0;
1.15      ratchov  1753:        p->u.resamp.idelta = 0;
                   1754:        p->u.resamp.odelta = 0;
1.27      ratchov  1755:        p->u.resamp.ctx_start = 0;
                   1756:        for (i = 0; i < NCHAN_MAX * RESAMP_NCTX; i++)
1.16      ratchov  1757:                p->u.resamp.ctx[i] = 0;
1.42      ratchov  1758: #ifdef DEBUG
                   1759:        if (debug_level >= 3) {
                   1760:                aproc_dbg(p);
                   1761:                dbg_puts(": new ");
                   1762:                dbg_putu(iblksz);
                   1763:                dbg_puts("/");
                   1764:                dbg_putu(oblksz);
                   1765:                dbg_puts("\n");
                   1766:        }
                   1767: #endif
1.19      ratchov  1768:        return p;
                   1769: }
                   1770:
                   1771: /*
                   1772:  * Convert one block.
                   1773:  */
                   1774: void
                   1775: enc_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
                   1776: {
1.71      ratchov  1777:        unsigned int nch, scount, icount, ocount;
                   1778:        unsigned int f;
1.63      ratchov  1779:        adata_t *idata;
1.19      ratchov  1780:        int s;
1.71      ratchov  1781:        unsigned int oshift;
1.19      ratchov  1782:        int osigbit;
1.71      ratchov  1783:        unsigned int obps;
                   1784:        unsigned int i;
1.19      ratchov  1785:        unsigned char *odata;
                   1786:        int obnext;
                   1787:        int osnext;
                   1788:
                   1789:        /*
                   1790:         * Calculate max frames readable at once from the input buffer.
                   1791:         */
1.63      ratchov  1792:        idata = (adata_t *)abuf_rgetblk(ibuf, &icount, 0);
1.19      ratchov  1793:        if (icount == 0)
                   1794:                return;
                   1795:        odata = abuf_wgetblk(obuf, &ocount, 0);
                   1796:        if (ocount == 0)
                   1797:                return;
                   1798:        scount = (icount < ocount) ? icount : ocount;
                   1799:        nch = ibuf->cmax - ibuf->cmin + 1;
1.42      ratchov  1800: #ifdef DEBUG
                   1801:        if (debug_level >= 4) {
                   1802:                aproc_dbg(p);
                   1803:                dbg_puts(": bcopy ");
                   1804:                dbg_putu(scount);
1.51      ratchov  1805:                dbg_puts(" fr / ");
1.42      ratchov  1806:                dbg_putu(nch);
                   1807:                dbg_puts(" ch\n");
                   1808:        }
                   1809: #endif
1.19      ratchov  1810:        /*
                   1811:         * Partially copy structures into local variables, to avoid
                   1812:         * unnecessary indirections; this also allows the compiler to
                   1813:         * order local variables more "cache-friendly".
                   1814:         */
                   1815:        oshift = p->u.conv.shift;
                   1816:        osigbit = p->u.conv.sigbit;
                   1817:        obps = p->u.conv.bps;
                   1818:        obnext = p->u.conv.bnext;
                   1819:        osnext = p->u.conv.snext;
                   1820:
                   1821:        /*
                   1822:         * Start conversion.
                   1823:         */
                   1824:        odata += p->u.conv.bfirst;
                   1825:        for (f = scount * nch; f > 0; f--) {
                   1826:                s = *idata++;
1.63      ratchov  1827:                s <<= 32 - ADATA_BITS;
1.19      ratchov  1828:                s >>= oshift;
                   1829:                s ^= osigbit;
                   1830:                for (i = obps; i > 0; i--) {
                   1831:                        *odata = (unsigned char)s;
                   1832:                        s >>= 8;
                   1833:                        odata += obnext;
                   1834:                }
                   1835:                odata += osnext;
                   1836:        }
                   1837:
                   1838:        /*
                   1839:         * Update FIFO pointers.
                   1840:         */
1.51      ratchov  1841:        abuf_rdiscard(ibuf, scount);
                   1842:        abuf_wcommit(obuf, scount);
1.19      ratchov  1843: }
                   1844:
                   1845: int
                   1846: enc_in(struct aproc *p, struct abuf *ibuf)
                   1847: {
1.54      ratchov  1848:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.19      ratchov  1849:
                   1850:        if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
                   1851:                return 0;
                   1852:        enc_bcopy(p, ibuf, obuf);
                   1853:        if (!abuf_flush(obuf))
                   1854:                return 0;
                   1855:        return 1;
                   1856: }
                   1857:
                   1858: int
                   1859: enc_out(struct aproc *p, struct abuf *obuf)
                   1860: {
1.54      ratchov  1861:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.19      ratchov  1862:
                   1863:        if (!abuf_fill(ibuf))
                   1864:                return 0;
                   1865:        if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
                   1866:                return 0;
                   1867:        enc_bcopy(p, ibuf, obuf);
                   1868:        return 1;
                   1869: }
                   1870:
                   1871: void
                   1872: enc_eof(struct aproc *p, struct abuf *ibuf)
                   1873: {
                   1874:        aproc_del(p);
                   1875: }
                   1876:
                   1877: void
                   1878: enc_hup(struct aproc *p, struct abuf *obuf)
                   1879: {
                   1880:        aproc_del(p);
                   1881: }
                   1882:
                   1883: struct aproc_ops enc_ops = {
                   1884:        "enc",
                   1885:        enc_in,
                   1886:        enc_out,
                   1887:        enc_eof,
                   1888:        enc_hup,
                   1889:        NULL,
                   1890:        NULL,
                   1891:        aproc_ipos,
                   1892:        aproc_opos,
                   1893:        NULL
                   1894: };
                   1895:
                   1896: struct aproc *
                   1897: enc_new(char *name, struct aparams *par)
                   1898: {
                   1899:        struct aproc *p;
                   1900:
                   1901:        p = aproc_new(&enc_ops, name);
                   1902:        p->u.conv.bps = par->bps;
                   1903:        p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
                   1904:        if (par->msb) {
                   1905:                p->u.conv.shift = 32 - par->bps * 8;
                   1906:        } else {
                   1907:                p->u.conv.shift = 32 - par->bits;
                   1908:        }
                   1909:        if (!par->le) {
                   1910:                p->u.conv.bfirst = par->bps - 1;
                   1911:                p->u.conv.bnext = -1;
                   1912:                p->u.conv.snext = 2 * par->bps;
                   1913:        } else {
                   1914:                p->u.conv.bfirst = 0;
                   1915:                p->u.conv.bnext = 1;
                   1916:                p->u.conv.snext = 0;
                   1917:        }
1.42      ratchov  1918: #ifdef DEBUG
                   1919:        if (debug_level >= 3) {
                   1920:                aproc_dbg(p);
                   1921:                dbg_puts(": new ");
                   1922:                aparams_dbg(par);
                   1923:                dbg_puts("\n");
                   1924:        }
                   1925: #endif
1.19      ratchov  1926:        return p;
                   1927: }
                   1928:
                   1929: /*
                   1930:  * Convert one block.
                   1931:  */
                   1932: void
                   1933: dec_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
                   1934: {
1.71      ratchov  1935:        unsigned int nch, scount, icount, ocount;
                   1936:        unsigned int f;
                   1937:        unsigned int ibps;
                   1938:        unsigned int i;
1.19      ratchov  1939:        int s = 0xdeadbeef;
                   1940:        unsigned char *idata;
                   1941:        int ibnext;
                   1942:        int isnext;
                   1943:        int isigbit;
1.71      ratchov  1944:        unsigned int ishift;
1.63      ratchov  1945:        adata_t *odata;
1.19      ratchov  1946:
                   1947:        /*
                   1948:         * Calculate max frames readable at once from the input buffer.
                   1949:         */
                   1950:        idata = abuf_rgetblk(ibuf, &icount, 0);
                   1951:        if (icount == 0)
                   1952:                return;
1.63      ratchov  1953:        odata = (adata_t *)abuf_wgetblk(obuf, &ocount, 0);
1.19      ratchov  1954:        if (ocount == 0)
                   1955:                return;
                   1956:        scount = (icount < ocount) ? icount : ocount;
                   1957:        nch = obuf->cmax - obuf->cmin + 1;
1.42      ratchov  1958: #ifdef DEBUG
                   1959:        if (debug_level >= 4) {
                   1960:                aproc_dbg(p);
                   1961:                dbg_puts(": bcopy ");
                   1962:                dbg_putu(scount);
1.51      ratchov  1963:                dbg_puts(" fr / ");
1.42      ratchov  1964:                dbg_putu(nch);
                   1965:                dbg_puts(" ch\n");
                   1966:        }
                   1967: #endif
1.19      ratchov  1968:        /*
                   1969:         * Partially copy structures into local variables, to avoid
                   1970:         * unnecessary indirections; this also allows the compiler to
                   1971:         * order local variables more "cache-friendly".
                   1972:         */
                   1973:        ibps = p->u.conv.bps;
                   1974:        ibnext = p->u.conv.bnext;
                   1975:        isigbit = p->u.conv.sigbit;
                   1976:        ishift = p->u.conv.shift;
                   1977:        isnext = p->u.conv.snext;
                   1978:
                   1979:        /*
                   1980:         * Start conversion.
                   1981:         */
                   1982:        idata += p->u.conv.bfirst;
                   1983:        for (f = scount * nch; f > 0; f--) {
                   1984:                for (i = ibps; i > 0; i--) {
                   1985:                        s <<= 8;
                   1986:                        s |= *idata;
                   1987:                        idata += ibnext;
                   1988:                }
                   1989:                idata += isnext;
                   1990:                s ^= isigbit;
                   1991:                s <<= ishift;
1.63      ratchov  1992:                s >>= 32 - ADATA_BITS;
1.19      ratchov  1993:                *odata++ = s;
                   1994:        }
                   1995:
                   1996:        /*
                   1997:         * Update FIFO pointers.
                   1998:         */
1.51      ratchov  1999:        abuf_rdiscard(ibuf, scount);
                   2000:        abuf_wcommit(obuf, scount);
1.19      ratchov  2001: }
                   2002:
                   2003: int
                   2004: dec_in(struct aproc *p, struct abuf *ibuf)
                   2005: {
1.54      ratchov  2006:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.19      ratchov  2007:
                   2008:        if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
                   2009:                return 0;
                   2010:        dec_bcopy(p, ibuf, obuf);
                   2011:        if (!abuf_flush(obuf))
                   2012:                return 0;
                   2013:        return 1;
                   2014: }
                   2015:
                   2016: int
                   2017: dec_out(struct aproc *p, struct abuf *obuf)
                   2018: {
1.54      ratchov  2019:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.19      ratchov  2020:
                   2021:        if (!abuf_fill(ibuf))
                   2022:                return 0;
                   2023:        if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
                   2024:                return 0;
                   2025:        dec_bcopy(p, ibuf, obuf);
                   2026:        return 1;
                   2027: }
                   2028:
                   2029: void
                   2030: dec_eof(struct aproc *p, struct abuf *ibuf)
                   2031: {
                   2032:        aproc_del(p);
                   2033: }
                   2034:
                   2035: void
                   2036: dec_hup(struct aproc *p, struct abuf *obuf)
                   2037: {
                   2038:        aproc_del(p);
                   2039: }
                   2040:
                   2041: struct aproc_ops dec_ops = {
                   2042:        "dec",
                   2043:        dec_in,
                   2044:        dec_out,
                   2045:        dec_eof,
                   2046:        dec_hup,
                   2047:        NULL,
                   2048:        NULL,
                   2049:        aproc_ipos,
                   2050:        aproc_opos,
                   2051:        NULL
                   2052: };
                   2053:
                   2054: struct aproc *
                   2055: dec_new(char *name, struct aparams *par)
                   2056: {
                   2057:        struct aproc *p;
                   2058:
                   2059:        p = aproc_new(&dec_ops, name);
                   2060:        p->u.conv.bps = par->bps;
                   2061:        p->u.conv.sigbit = par->sig ? 0 : 1 << (par->bits - 1);
                   2062:        if (par->msb) {
                   2063:                p->u.conv.shift = 32 - par->bps * 8;
                   2064:        } else {
                   2065:                p->u.conv.shift = 32 - par->bits;
                   2066:        }
                   2067:        if (par->le) {
                   2068:                p->u.conv.bfirst = par->bps - 1;
                   2069:                p->u.conv.bnext = -1;
                   2070:                p->u.conv.snext = 2 * par->bps;
                   2071:        } else {
                   2072:                p->u.conv.bfirst = 0;
                   2073:                p->u.conv.bnext = 1;
                   2074:                p->u.conv.snext = 0;
                   2075:        }
1.42      ratchov  2076: #ifdef DEBUG
                   2077:        if (debug_level >= 3) {
                   2078:                aproc_dbg(p);
                   2079:                dbg_puts(": new ");
                   2080:                aparams_dbg(par);
1.53      ratchov  2081:                dbg_puts("\n");
                   2082:        }
                   2083: #endif
                   2084:        return p;
                   2085: }
                   2086:
                   2087: /*
                   2088:  * Convert one block.
                   2089:  */
                   2090: void
                   2091: join_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf)
                   2092: {
1.71      ratchov  2093:        unsigned int h, hops;
                   2094:        unsigned int inch, inext;
1.63      ratchov  2095:        adata_t *idata;
1.71      ratchov  2096:        unsigned int onch, onext;
1.63      ratchov  2097:        adata_t *odata;
1.53      ratchov  2098:        int scale;
1.71      ratchov  2099:        unsigned int c, f, scount, icount, ocount;
1.53      ratchov  2100:
                   2101:        /*
                   2102:         * Calculate max frames readable at once from the input buffer.
                   2103:         */
1.63      ratchov  2104:        idata = (adata_t *)abuf_rgetblk(ibuf, &icount, 0);
1.53      ratchov  2105:        if (icount == 0)
                   2106:                return;
1.63      ratchov  2107:        odata = (adata_t *)abuf_wgetblk(obuf, &ocount, 0);
1.53      ratchov  2108:        if (ocount == 0)
                   2109:                return;
                   2110:        scount = icount < ocount ? icount : ocount;
                   2111:        inch = ibuf->cmax - ibuf->cmin + 1;
                   2112:        onch = obuf->cmax - obuf->cmin + 1;
                   2113:        if (2 * inch <= onch) {
                   2114:                hops = onch / inch;
                   2115:                inext = inch * hops;
                   2116:                onext = onch - inext;
                   2117:                for (f = scount; f > 0; f--) {
                   2118:                        h = hops;
                   2119:                        for (;;) {
                   2120:                                for (c = inch; c > 0; c--)
                   2121:                                        *odata++ = *idata++;
                   2122:                                if (--h == 0)
                   2123:                                        break;
                   2124:                                idata -= inch;
                   2125:                        }
                   2126:                        for (c = onext; c > 0; c--)
                   2127:                                *odata++ = 0;
                   2128:                }
                   2129:        } else if (inch >= 2 * onch) {
                   2130:                hops = inch / onch;
                   2131:                inext = inch - onch * hops;
                   2132:                scale = ADATA_UNIT / hops;
                   2133:                inch -= onch + inext;
                   2134:                hops--;
                   2135:                for (f = scount; f > 0; f--) {
                   2136:                        for (c = onch; c > 0; c--)
1.63      ratchov  2137:                                *odata++ = ADATA_MUL(*idata++, scale);
1.53      ratchov  2138:                        for (h = hops; h > 0; h--) {
                   2139:                                odata -= onch;
                   2140:                                for (c = onch; c > 0; c--)
1.63      ratchov  2141:                                        *odata++ += ADATA_MUL(*idata++, scale);
1.53      ratchov  2142:                        }
                   2143:                        idata += inext;
                   2144:                }
                   2145:        } else {
                   2146: #ifdef DEBUG
                   2147:                aproc_dbg(p);
                   2148:                dbg_puts(": nothing to do\n");
                   2149:                dbg_panic();
                   2150: #endif
                   2151:        }
                   2152: #ifdef DEBUG
                   2153:        if (debug_level >= 4) {
                   2154:                aproc_dbg(p);
                   2155:                dbg_puts(": bcopy ");
                   2156:                dbg_putu(scount);
                   2157:                dbg_puts(" fr\n");
                   2158:        }
                   2159: #endif
                   2160:        abuf_rdiscard(ibuf, scount);
                   2161:        abuf_wcommit(obuf, scount);
                   2162: }
                   2163:
                   2164: int
                   2165: join_in(struct aproc *p, struct abuf *ibuf)
                   2166: {
1.54      ratchov  2167:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.53      ratchov  2168:
                   2169:        if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
                   2170:                return 0;
                   2171:        join_bcopy(p, ibuf, obuf);
                   2172:        if (!abuf_flush(obuf))
                   2173:                return 0;
                   2174:        return 1;
                   2175: }
                   2176:
                   2177: int
                   2178: join_out(struct aproc *p, struct abuf *obuf)
                   2179: {
1.54      ratchov  2180:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.53      ratchov  2181:
                   2182:        if (!abuf_fill(ibuf))
                   2183:                return 0;
                   2184:        if (!ABUF_WOK(obuf) || !ABUF_ROK(ibuf))
                   2185:                return 0;
                   2186:        join_bcopy(p, ibuf, obuf);
                   2187:        return 1;
                   2188: }
                   2189:
                   2190: void
                   2191: join_eof(struct aproc *p, struct abuf *ibuf)
                   2192: {
                   2193:        aproc_del(p);
                   2194: }
                   2195:
                   2196: void
                   2197: join_hup(struct aproc *p, struct abuf *obuf)
                   2198: {
                   2199:        aproc_del(p);
                   2200: }
                   2201:
                   2202: struct aproc_ops join_ops = {
                   2203:        "join",
                   2204:        join_in,
                   2205:        join_out,
                   2206:        join_eof,
                   2207:        join_hup,
                   2208:        NULL,
                   2209:        NULL,
                   2210:        aproc_ipos,
                   2211:        aproc_opos,
                   2212:        NULL
                   2213: };
                   2214:
                   2215: struct aproc *
                   2216: join_new(char *name)
                   2217: {
                   2218:        struct aproc *p;
                   2219:
                   2220:        p = aproc_new(&join_ops, name);
                   2221: #ifdef DEBUG
                   2222:        if (debug_level >= 3) {
                   2223:                aproc_dbg(p);
1.61      ratchov  2224:                dbg_puts(": new\n");
1.51      ratchov  2225:        }
                   2226: #endif
                   2227:        return p;
                   2228: }
                   2229:
                   2230: /*
                   2231:  * Commit and flush part of the output buffer
                   2232:  */
                   2233: void
                   2234: mon_flush(struct aproc *p)
                   2235: {
1.54      ratchov  2236:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.71      ratchov  2237:        unsigned int count;
1.51      ratchov  2238:
                   2239: #ifdef DEBUG
                   2240:        if (debug_level >= 4) {
                   2241:                aproc_dbg(p);
                   2242:                dbg_puts(": delta = ");
                   2243:                dbg_puti(p->u.mon.delta);
                   2244:                dbg_puts("/");
                   2245:                dbg_putu(p->u.mon.bufsz);
                   2246:                dbg_puts(" pending = ");
                   2247:                dbg_puti(p->u.mon.pending);
                   2248:                dbg_puts("\n");
                   2249:        }
                   2250: #endif
                   2251:        if (p->u.mon.delta <= 0 || p->u.mon.pending == 0)
                   2252:                return;
                   2253:        count = p->u.mon.delta;
                   2254:        if (count > p->u.mon.pending)
                   2255:                count = p->u.mon.pending;
                   2256:        abuf_wcommit(obuf, count);
                   2257:        p->u.mon.pending -= count;
                   2258:        p->u.mon.delta -= count;
                   2259:        abuf_flush(obuf);
                   2260: }
                   2261:
                   2262: /*
                   2263:  * Copy one block.
                   2264:  */
                   2265: void
1.71      ratchov  2266: mon_snoop(struct aproc *p, struct abuf *ibuf,
                   2267:     unsigned int pos, unsigned int todo)
1.51      ratchov  2268: {
1.54      ratchov  2269:        struct abuf *obuf = LIST_FIRST(&p->outs);
1.71      ratchov  2270:        unsigned int scount, icount, ocount;
1.63      ratchov  2271:        adata_t *idata, *odata;
1.51      ratchov  2272:
                   2273: #ifdef DEBUG
                   2274:        if (debug_level >= 4) {
                   2275:                aproc_dbg(p);
1.61      ratchov  2276:                dbg_puts(": snooping ");
1.51      ratchov  2277:                dbg_putu(pos);
                   2278:                dbg_puts("..");
                   2279:                dbg_putu(todo);
                   2280:                dbg_puts("\n");
                   2281:        }
                   2282: #endif
                   2283:        if (!abuf_flush(obuf))
                   2284:                return;
                   2285:
                   2286:        while (todo > 0) {
                   2287:                /*
                   2288:                 * Calculate max frames readable at once from the input buffer.
                   2289:                 */
1.63      ratchov  2290:                idata = (adata_t *)abuf_rgetblk(ibuf, &icount, pos);
                   2291:                odata = (adata_t *)abuf_wgetblk(obuf, &ocount, p->u.mon.pending);
1.51      ratchov  2292:                scount = (icount < ocount) ? icount : ocount;
                   2293: #ifdef DEBUG
                   2294:                if (debug_level >= 4) {
                   2295:                        aproc_dbg(p);
                   2296:                        dbg_puts(": snooping ");
                   2297:                        dbg_putu(scount);
                   2298:                        dbg_puts(" fr\n");
                   2299:                }
                   2300:                if (scount == 0) {
                   2301:                        dbg_puts("monitor xrun, not allowed\n");
                   2302:                        dbg_panic();
                   2303:                }
                   2304: #endif
                   2305:                memcpy(odata, idata, scount * obuf->bpf);
                   2306:                p->u.mon.pending += scount;
                   2307:                todo -= scount;
                   2308:                pos += scount;
                   2309:        }
                   2310:        mon_flush(p);
                   2311: }
                   2312:
                   2313: int
                   2314: mon_in(struct aproc *p, struct abuf *ibuf)
                   2315: {
                   2316: #ifdef DEBUG
                   2317:        dbg_puts("monitor can't have inputs to read\n");
                   2318:        dbg_panic();
                   2319: #endif
                   2320:        return 0;
                   2321: }
                   2322:
                   2323: /*
                   2324:  * put the monitor into ``empty'' state
                   2325:  */
                   2326: void
                   2327: mon_clear(struct aproc *p)
                   2328: {
                   2329:        p->u.mon.pending = 0;
                   2330:        p->u.mon.delta = 0;
                   2331: }
                   2332:
                   2333: int
                   2334: mon_out(struct aproc *p, struct abuf *obuf)
                   2335: {
                   2336:        /*
                   2337:         * can't trigger monitored stream to produce data
                   2338:         */
                   2339:        return 0;
                   2340: }
                   2341:
                   2342: void
                   2343: mon_eof(struct aproc *p, struct abuf *ibuf)
                   2344: {
                   2345: #ifdef DEBUG
                   2346:        dbg_puts("monitor can't have inputs to eof\n");
                   2347:        dbg_panic();
                   2348: #endif
                   2349: }
                   2350:
                   2351: void
                   2352: mon_hup(struct aproc *p, struct abuf *obuf)
                   2353: {
                   2354:        aproc_del(p);
                   2355: }
                   2356:
                   2357: void
                   2358: mon_ipos(struct aproc *p, struct abuf *ibuf, int delta)
                   2359: {
                   2360:        aproc_ipos(p, ibuf, delta);
                   2361:        p->u.mon.delta += delta;
                   2362:        mon_flush(p);
                   2363: }
                   2364:
                   2365: struct aproc_ops mon_ops = {
                   2366:        "mon",
                   2367:        mon_in,
                   2368:        mon_out,
                   2369:        mon_eof,
                   2370:        mon_hup,
                   2371:        NULL,
                   2372:        NULL,
                   2373:        mon_ipos,
                   2374:        aproc_opos,
                   2375:        NULL
                   2376: };
                   2377:
                   2378: struct aproc *
1.71      ratchov  2379: mon_new(char *name, unsigned int bufsz)
1.51      ratchov  2380: {
                   2381:        struct aproc *p;
                   2382:
                   2383:        p = aproc_new(&mon_ops, name);
                   2384:        p->u.mon.pending = 0;
                   2385:        p->u.mon.delta = 0;
                   2386:        p->u.mon.bufsz = bufsz;
                   2387: #ifdef DEBUG
                   2388:        if (debug_level >= 3) {
                   2389:                aproc_dbg(p);
                   2390:                dbg_puts(": new\n");
1.42      ratchov  2391:        }
                   2392: #endif
1.1       ratchov  2393:        return p;
                   2394: }