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

Annotation of src/usr.bin/aucat/dev.c, Revision 1.27

1.27    ! ratchov     1: /*     $OpenBSD: dev.c,v 1.26 2009/02/06 08:26:34 ratchov Exp $        */
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:  */
1.27    ! ratchov    17:
1.1       ratchov    18: #include <stdio.h>
                     19: #include <stdlib.h>
                     20: #include <unistd.h>
                     21:
                     22: #include "abuf.h"
                     23: #include "aproc.h"
1.27    ! ratchov    24: #include "conf.h"
        !            25: #include "dev.h"
1.3       ratchov    26: #include "pipe.h"
                     27: #include "safile.h"
1.1       ratchov    28:
1.3       ratchov    29: unsigned dev_bufsz, dev_round, dev_rate;
1.1       ratchov    30: struct aparams dev_ipar, dev_opar;
                     31: struct aproc *dev_mix, *dev_sub, *dev_rec, *dev_play;
1.24      ratchov    32:
                     33: /*
1.27    ! ratchov    34:  * Same as dev_init(), but create a fake device that records what is
        !            35:  * played.
1.24      ratchov    36:  */
                     37: void
                     38: dev_loopinit(struct aparams *dipar, struct aparams *dopar, unsigned bufsz)
                     39: {
                     40:        struct abuf *buf;
                     41:        struct aparams par;
                     42:        unsigned cmin, cmax, rate;
                     43:
                     44:        cmin = (dipar->cmin < dopar->cmin) ? dipar->cmin : dopar->cmin;
                     45:        cmax = (dipar->cmax > dopar->cmax) ? dipar->cmax : dopar->cmax;
                     46:        rate = (dipar->rate > dopar->rate) ? dipar->rate : dopar->rate;
                     47:        aparams_init(&par, cmin, cmax, rate);
                     48:        dev_ipar = par;
                     49:        dev_opar = par;
                     50:        dev_round = (bufsz + 1) / 2;
                     51:        dev_bufsz = dev_round * 2;
1.25      ratchov    52:        dev_rate  = rate;
1.24      ratchov    53:        dev_rec = NULL;
                     54:        dev_play = NULL;
1.25      ratchov    55:
1.24      ratchov    56:        buf = abuf_new(dev_bufsz, &par);
                     57:        dev_mix = mix_new("mix", dev_bufsz);
                     58:        dev_mix->refs++;
                     59:        dev_sub = sub_new("sub", dev_bufsz);
                     60:        dev_sub->refs++;
                     61:        aproc_setout(dev_mix, buf);
                     62:        aproc_setin(dev_sub, buf);
                     63:
                     64:        dev_mix->u.mix.flags |= MIX_AUTOQUIT;
                     65:        dev_sub->u.sub.flags |= SUB_AUTOQUIT;
                     66:
                     67:        *dipar = dev_ipar;
                     68:        *dopar = dev_opar;
                     69: }
                     70:
                     71: /*
1.27    ! ratchov    72:  * Same as dev_done(), but destroy a loopback device.
1.24      ratchov    73:  */
                     74: void
                     75: dev_loopdone(void)
                     76: {
                     77:        struct file *f;
                     78:
                     79:        DPRINTF("dev_loopdone:\n");
                     80:
                     81:        dev_sub->refs--;
                     82:        dev_sub = NULL;
                     83:        dev_mix->refs--;
                     84:        dev_mix = NULL;
                     85:        /*
1.27    ! ratchov    86:         * Generate EOF on all inputs.
1.24      ratchov    87:         */
                     88:  restart:
                     89:        LIST_FOREACH(f, &file_list, entry) {
                     90:                if (f->rproc != NULL) {
                     91:                        file_eof(f);
                     92:                        goto restart;
                     93:                }
                     94:        }
                     95:        while (file_poll())
                     96:                ; /* nothing */
                     97: }
1.1       ratchov    98:
1.20      ratchov    99: unsigned
                    100: dev_roundof(unsigned newrate)
1.1       ratchov   101: {
1.20      ratchov   102:        return (dev_round * newrate + dev_rate / 2) / dev_rate;
1.1       ratchov   103: }
                    104:
                    105: /*
1.27    ! ratchov   106:  * Open the device with the given hardware parameters and create a mixer
1.1       ratchov   107:  * and a multiplexer connected to it with all necessary conversions
1.27    ! ratchov   108:  * setup.
1.1       ratchov   109:  */
1.26      ratchov   110: int
1.3       ratchov   111: dev_init(char *devpath,
1.20      ratchov   112:     struct aparams *dipar, struct aparams *dopar, unsigned bufsz)
1.1       ratchov   113: {
1.23      ratchov   114:        struct file *f;
1.1       ratchov   115:        struct aparams ipar, opar;
                    116:        struct aproc *conv;
                    117:        struct abuf *buf;
1.3       ratchov   118:        unsigned nfr, ibufsz, obufsz;
1.25      ratchov   119:
1.3       ratchov   120:        /*
1.27    ! ratchov   121:         * Ask for 1/4 of the buffer for the kernel ring and
        !           122:         * limit the block size to 1/4 of the requested buffer.
1.3       ratchov   123:         */
                    124:        dev_bufsz = (bufsz + 3) / 4;
1.11      ratchov   125:        dev_round = (bufsz + 3) / 4;
1.23      ratchov   126:        f = (struct file *)safile_new(&safile_ops, devpath,
1.20      ratchov   127:            dipar, dopar, &dev_bufsz, &dev_round);
1.23      ratchov   128:        if (f == NULL)
1.26      ratchov   129:                return 0;
1.3       ratchov   130:        if (dipar) {
1.19      ratchov   131: #ifdef DEBUG
1.3       ratchov   132:                if (debug_level > 0) {
1.9       ratchov   133:                        fprintf(stderr, "dev_init: hw recording ");
1.3       ratchov   134:                        aparams_print(dipar);
1.9       ratchov   135:                        fprintf(stderr, "\n");
1.3       ratchov   136:                }
1.19      ratchov   137: #endif
1.20      ratchov   138:                dev_rate = dipar->rate;
1.3       ratchov   139:        }
                    140:        if (dopar) {
1.19      ratchov   141: #ifdef DEBUG
1.3       ratchov   142:                if (debug_level > 0) {
1.9       ratchov   143:                        fprintf(stderr, "dev_init: hw playing ");
1.3       ratchov   144:                        aparams_print(dopar);
1.9       ratchov   145:                        fprintf(stderr, "\n");
1.3       ratchov   146:                }
1.19      ratchov   147: #endif
1.20      ratchov   148:                dev_rate = dopar->rate;
1.3       ratchov   149:        }
1.11      ratchov   150:        ibufsz = obufsz = dev_bufsz;
                    151:        bufsz = (bufsz > dev_bufsz) ? bufsz - dev_bufsz : 0;
1.1       ratchov   152:
                    153:        /*
1.27    ! ratchov   154:         * Use 1/8 of the buffer for the mixer/converters.  Since we
1.11      ratchov   155:         * already consumed 1/4 for the device, bufsz represents the
1.27    ! ratchov   156:         * remaining 3/4. So 1/8 is 1/6 of 3/4.
1.11      ratchov   157:         */
                    158:        nfr = (bufsz + 5) / 6;
                    159:        nfr += dev_round - 1;
                    160:        nfr -= nfr % dev_round;
                    161:        if (nfr == 0)
                    162:                nfr = dev_round;
                    163:
                    164:        /*
1.27    ! ratchov   165:         * Create record chain.
1.1       ratchov   166:         */
                    167:        if (dipar) {
                    168:                aparams_init(&ipar, dipar->cmin, dipar->cmax, dipar->rate);
                    169:                /*
1.27    ! ratchov   170:                 * Create the read end.
1.1       ratchov   171:                 */
1.23      ratchov   172:                dev_rec = rpipe_new(f);
1.22      ratchov   173:                dev_rec->refs++;
1.4       ratchov   174:                buf = abuf_new(nfr, dipar);
1.1       ratchov   175:                aproc_setout(dev_rec, buf);
1.3       ratchov   176:                ibufsz += nfr;
1.1       ratchov   177:
                    178:                /*
1.27    ! ratchov   179:                 * Append a converter, if needed.
1.1       ratchov   180:                 */
1.4       ratchov   181:                if (!aparams_eqenc(dipar, &ipar)) {
1.9       ratchov   182:                        conv = dec_new("subin", dipar);
1.1       ratchov   183:                        aproc_setin(conv, buf);
1.4       ratchov   184:                        buf = abuf_new(nfr, &ipar);
1.1       ratchov   185:                        aproc_setout(conv, buf);
1.3       ratchov   186:                        ibufsz += nfr;
1.1       ratchov   187:                }
                    188:                dev_ipar = ipar;
                    189:
                    190:                /*
1.27    ! ratchov   191:                 * Append a "sub" to which clients will connect.
1.1       ratchov   192:                 */
1.3       ratchov   193:                dev_sub = sub_new("sub", nfr);
1.22      ratchov   194:                dev_sub->refs++;
1.1       ratchov   195:                aproc_setin(dev_sub, buf);
                    196:        } else {
                    197:                dev_rec = NULL;
                    198:                dev_sub = NULL;
                    199:        }
                    200:
                    201:        /*
1.27    ! ratchov   202:         * Create play chain.
1.1       ratchov   203:         */
                    204:        if (dopar) {
                    205:                aparams_init(&opar, dopar->cmin, dopar->cmax, dopar->rate);
                    206:                /*
1.27    ! ratchov   207:                 * Create the write end.
1.1       ratchov   208:                 */
1.23      ratchov   209:                dev_play = wpipe_new(f);
1.22      ratchov   210:                dev_play->refs++;
1.4       ratchov   211:                buf = abuf_new(nfr, dopar);
1.1       ratchov   212:                aproc_setin(dev_play, buf);
1.3       ratchov   213:                obufsz += nfr;
1.25      ratchov   214:
1.1       ratchov   215:                /*
1.27    ! ratchov   216:                 * Append a converter, if needed.
1.1       ratchov   217:                 */
1.4       ratchov   218:                if (!aparams_eqenc(&opar, dopar)) {
1.9       ratchov   219:                        conv = enc_new("mixout", dopar);
1.1       ratchov   220:                        aproc_setout(conv, buf);
1.4       ratchov   221:                        buf = abuf_new(nfr, &opar);
1.1       ratchov   222:                        aproc_setin(conv, buf);
1.3       ratchov   223:                        obufsz += nfr;
1.1       ratchov   224:                }
                    225:                dev_opar = opar;
                    226:
                    227:                /*
1.27    ! ratchov   228:                 * Append a "mix" to which clients will connect.
1.1       ratchov   229:                 */
1.3       ratchov   230:                dev_mix = mix_new("mix", nfr);
1.22      ratchov   231:                dev_mix->refs++;
1.1       ratchov   232:                aproc_setout(dev_mix, buf);
                    233:        } else {
                    234:                dev_play = NULL;
                    235:                dev_mix = NULL;
                    236:        }
1.3       ratchov   237:        dev_bufsz = (dopar) ? obufsz : ibufsz;
                    238:        DPRINTF("dev_init: using %u fpb\n", dev_bufsz);
                    239:        dev_start();
1.26      ratchov   240:        return 1;
1.1       ratchov   241: }
                    242:
                    243: /*
1.27    ! ratchov   244:  * Cleanly stop and drain everything and close the device
        !           245:  * once both play chain and record chain are gone.
1.1       ratchov   246:  */
                    247: void
                    248: dev_done(void)
                    249: {
                    250:        struct file *f;
                    251:
1.15      ratchov   252:        DPRINTF("dev_done: dev_mix = %p, dev_sub = %p\n", dev_mix, dev_sub);
1.3       ratchov   253:        if (dev_mix) {
1.22      ratchov   254:                dev_mix->refs--;
1.17      ratchov   255:                dev_mix->u.mix.flags |= MIX_AUTOQUIT;
1.22      ratchov   256:                dev_mix = NULL;
1.3       ratchov   257:                /*
1.27    ! ratchov   258:                 * Generate EOF on all inputs (but not the device), and
1.3       ratchov   259:                 * put the mixer in ``autoquit'' state, so once buffers
                    260:                 * are drained the mixer will terminate and shutdown the
1.27    ! ratchov   261:                 * write-end of the device.
1.3       ratchov   262:                 *
                    263:                 * NOTE: since file_eof() can destroy the file and
                    264:                 * reorder the file_list, we have to restart the loop
1.27    ! ratchov   265:                 * after each call to file_eof().
1.3       ratchov   266:                 */
                    267:        restart:
                    268:                LIST_FOREACH(f, &file_list, entry) {
1.23      ratchov   269:                        if (f->rproc != NULL && f->rproc != dev_rec) {
1.3       ratchov   270:                                file_eof(f);
                    271:                                goto restart;
                    272:                        }
                    273:                }
                    274:
                    275:                /*
1.27    ! ratchov   276:                 * Wait for play chain to terminate.
1.3       ratchov   277:                 */
1.23      ratchov   278:                if (dev_play) {
                    279:                        while (!LIST_EMPTY(&dev_play->ibuflist)) {
                    280:                                if (!file_poll())
                    281:                                        break;
                    282:                        }
                    283:                        dev_play->refs--;
                    284:                        aproc_del(dev_play);
                    285:                        dev_play = NULL;
1.3       ratchov   286:                }
1.1       ratchov   287:        }
1.3       ratchov   288:        if (dev_sub) {
1.22      ratchov   289:                dev_sub->refs--;
1.17      ratchov   290:                dev_sub->u.sub.flags |= SUB_AUTOQUIT;
1.22      ratchov   291:                dev_sub = NULL;
1.3       ratchov   292:                /*
1.27    ! ratchov   293:                 * Same as above, but for the record chain: generate eof
1.3       ratchov   294:                 * on the read-end of the device and wait record buffers
1.27    ! ratchov   295:                 * to disappear.  We must stop the device first, because
1.3       ratchov   296:                 * play-end will underrun (and xrun correction code will
1.27    ! ratchov   297:                 * insert silence on the record-end of the device).
1.3       ratchov   298:                 */
1.23      ratchov   299:                if (dev_rec) {
                    300:                        dev_stop();
                    301:                        if (dev_rec->u.io.file)
                    302:                                file_eof(dev_rec->u.io.file);
                    303:                        while (!LIST_EMPTY(&dev_rec->obuflist)) {
                    304:                                if (!file_poll())
                    305:                                        break;
                    306:                        }
                    307:                        dev_rec->refs--;
                    308:                        aproc_del(dev_rec);
                    309:                        dev_rec = NULL;
1.3       ratchov   310:                }
1.1       ratchov   311:        }
                    312: }
                    313:
                    314: /*
1.27    ! ratchov   315:  * Start the (paused) device. By default it's paused.
1.1       ratchov   316:  */
                    317: void
                    318: dev_start(void)
                    319: {
1.22      ratchov   320:        struct file *f;
                    321:
1.1       ratchov   322:        if (dev_mix)
                    323:                dev_mix->u.mix.flags |= MIX_DROP;
                    324:        if (dev_sub)
                    325:                dev_sub->u.sub.flags |= SUB_DROP;
1.22      ratchov   326:        if (dev_play && dev_play->u.io.file) {
                    327:                f = dev_play->u.io.file;
                    328:                f->ops->start(f);
                    329:        } else if (dev_rec && dev_rec->u.io.file) {
                    330:                f = dev_rec->u.io.file;
                    331:                f->ops->start(f);
                    332:        }
1.1       ratchov   333: }
                    334:
                    335: /*
1.27    ! ratchov   336:  * Pause the device.
1.1       ratchov   337:  */
                    338: void
                    339: dev_stop(void)
                    340: {
1.22      ratchov   341:        struct file *f;
                    342:
                    343:        if (dev_play && dev_play->u.io.file) {
                    344:                f = dev_play->u.io.file;
                    345:                f->ops->stop(f);
                    346:        } else if (dev_rec && dev_rec->u.io.file) {
                    347:                f = dev_rec->u.io.file;
                    348:                f->ops->stop(f);
                    349:        }
1.1       ratchov   350:        if (dev_mix)
                    351:                dev_mix->u.mix.flags &= ~MIX_DROP;
                    352:        if (dev_sub)
                    353:                dev_sub->u.sub.flags &= ~SUB_DROP;
                    354: }
                    355:
                    356: /*
1.27    ! ratchov   357:  * Find the end points connected to the mix/sub.
1.14      ratchov   358:  */
                    359: int
                    360: dev_getep(struct abuf **sibuf, struct abuf **sobuf)
                    361: {
                    362:        struct abuf *ibuf, *obuf;
                    363:
                    364:        if (sibuf) {
                    365:                ibuf = *sibuf;
                    366:                for (;;) {
                    367:                        if (!ibuf || !ibuf->rproc) {
                    368:                                DPRINTF("dev_getep: reader desappeared\n");
                    369:                                return 0;
                    370:                        }
                    371:                        if (ibuf->rproc == dev_mix)
                    372:                                break;
                    373:                        ibuf = LIST_FIRST(&ibuf->rproc->obuflist);
                    374:                }
1.21      ratchov   375:                *sibuf = ibuf;
1.14      ratchov   376:        }
                    377:        if (sobuf) {
                    378:                obuf = *sobuf;
                    379:                for (;;) {
                    380:                        if (!obuf || !obuf->wproc) {
                    381:                                DPRINTF("dev_getep: writer desappeared\n");
                    382:                                return 0;
                    383:                        }
                    384:                        if (obuf->wproc == dev_sub)
                    385:                                break;
                    386:                        obuf = LIST_FIRST(&obuf->wproc->ibuflist);
                    387:                }
1.21      ratchov   388:                *sobuf = obuf;
1.14      ratchov   389:        }
                    390:        return 1;
                    391: }
                    392:
                    393: /*
1.27    ! ratchov   394:  * Sync play buffer to rec buffer (for instance when one of
        !           395:  * them underruns/overruns).
1.1       ratchov   396:  */
                    397: void
1.3       ratchov   398: dev_sync(struct abuf *ibuf, struct abuf *obuf)
1.1       ratchov   399: {
1.3       ratchov   400:        struct abuf *pbuf, *rbuf;
                    401:        int delta;
                    402:
                    403:        if (!dev_mix || !dev_sub)
                    404:                return;
                    405:        pbuf = LIST_FIRST(&dev_mix->obuflist);
                    406:        if (!pbuf)
                    407:                return;
                    408:        rbuf = LIST_FIRST(&dev_sub->ibuflist);
                    409:        if (!rbuf)
                    410:                return;
1.14      ratchov   411:        if (!dev_getep(&ibuf, &obuf))
                    412:                return;
1.3       ratchov   413:
                    414:        /*
1.27    ! ratchov   415:         * Calculate delta, the number of frames the play chain is ahead
1.3       ratchov   416:         * of the record chain. It's necessary to schedule silences (or
                    417:         * drops) in order to start playback and record in sync.
                    418:         */
1.25      ratchov   419:        delta =
                    420:            rbuf->bpf * (pbuf->abspos + pbuf->used) -
1.3       ratchov   421:            pbuf->bpf *  rbuf->abspos;
                    422:        delta /= pbuf->bpf * rbuf->bpf;
                    423:        DPRINTF("dev_sync: delta = %d, ppos = %u, pused = %u, rpos = %u\n",
                    424:            delta, pbuf->abspos, pbuf->used, rbuf->abspos);
                    425:
                    426:        if (delta > 0) {
                    427:                /*
1.27    ! ratchov   428:                 * If the play chain is ahead (most cases) drop some of
        !           429:                 * the recorded input, to get both in sync.
1.3       ratchov   430:                 */
                    431:                obuf->drop += delta * obuf->bpf;
                    432:                abuf_ipos(obuf, -delta);
                    433:        } else if (delta < 0) {
                    434:                /*
1.27    ! ratchov   435:                 * If record chain is ahead (should never happen,
        !           436:                 * right?) then insert silence to play.
1.3       ratchov   437:                 */
                    438:                ibuf->silence += -delta * ibuf->bpf;
                    439:                abuf_opos(ibuf, delta);
                    440:        } else
                    441:                DPRINTF("dev_sync: nothing to do\n");
1.1       ratchov   442: }
                    443:
                    444: /*
1.27    ! ratchov   445:  * Attach the given input and output buffers to the mixer and the
1.1       ratchov   446:  * multiplexer respectively. The operation is done synchronously, so
                    447:  * both buffers enter in sync. If buffers do not match play
1.27    ! ratchov   448:  * and rec.
1.1       ratchov   449:  */
                    450: void
1.25      ratchov   451: dev_attach(char *name,
                    452:     struct abuf *ibuf, struct aparams *sipar, unsigned underrun,
1.18      ratchov   453:     struct abuf *obuf, struct aparams *sopar, unsigned overrun, int vol)
1.1       ratchov   454: {
                    455:        struct abuf *pbuf = NULL, *rbuf = NULL;
1.12      ratchov   456:        struct aparams ipar, opar;
1.1       ratchov   457:        struct aproc *conv;
1.20      ratchov   458:        unsigned round, nblk;
                    459:
1.1       ratchov   460:        if (ibuf) {
1.12      ratchov   461:                ipar = *sipar;
1.20      ratchov   462:                pbuf = LIST_FIRST(&dev_mix->obuflist);
                    463:                nblk = (dev_bufsz / dev_round + 3) / 4;
                    464:                round = dev_roundof(ipar.rate);
1.10      ratchov   465:                if (!aparams_eqenc(&ipar, &dev_opar)) {
                    466:                        conv = dec_new(name, &ipar);
                    467:                        ipar.bps = dev_opar.bps;
                    468:                        ipar.bits = dev_opar.bits;
                    469:                        ipar.sig = dev_opar.sig;
                    470:                        ipar.le = dev_opar.le;
                    471:                        ipar.msb = dev_opar.msb;
1.25      ratchov   472:                        aproc_setin(conv, ibuf);
1.20      ratchov   473:                        ibuf = abuf_new(nblk * round, &ipar);
1.9       ratchov   474:                        aproc_setout(conv, ibuf);
1.8       ratchov   475:                }
1.10      ratchov   476:                if (!aparams_subset(&ipar, &dev_opar)) {
                    477:                        conv = cmap_new(name, &ipar, &dev_opar);
                    478:                        ipar.cmin = dev_opar.cmin;
                    479:                        ipar.cmax = dev_opar.cmax;
1.7       ratchov   480:                        aproc_setin(conv, ibuf);
1.20      ratchov   481:                        ibuf = abuf_new(nblk * round, &ipar);
1.7       ratchov   482:                        aproc_setout(conv, ibuf);
1.6       ratchov   483:                }
1.10      ratchov   484:                if (!aparams_eqrate(&ipar, &dev_opar)) {
1.20      ratchov   485:                        conv = resamp_new(name, round, dev_round);
1.10      ratchov   486:                        ipar.rate = dev_opar.rate;
1.20      ratchov   487:                        round = dev_round;
1.5       ratchov   488:                        aproc_setin(conv, ibuf);
1.20      ratchov   489:                        ibuf = abuf_new(nblk * round, &ipar);
1.5       ratchov   490:                        aproc_setout(conv, ibuf);
1.1       ratchov   491:                }
                    492:                aproc_setin(dev_mix, ibuf);
1.3       ratchov   493:                abuf_opos(ibuf, -dev_mix->u.mix.lat);
1.1       ratchov   494:                ibuf->xrun = underrun;
1.18      ratchov   495:                ibuf->mixmaxweight = vol;
                    496:                mix_setmaster(dev_mix);
1.1       ratchov   497:        }
                    498:        if (obuf) {
1.12      ratchov   499:                opar = *sopar;
1.1       ratchov   500:                rbuf = LIST_FIRST(&dev_sub->ibuflist);
1.20      ratchov   501:                round = dev_roundof(opar.rate);
                    502:                nblk = (dev_bufsz / dev_round + 3) / 4;
1.10      ratchov   503:                if (!aparams_eqenc(&opar, &dev_ipar)) {
                    504:                        conv = enc_new(name, &opar);
                    505:                        opar.bps = dev_ipar.bps;
                    506:                        opar.bits = dev_ipar.bits;
                    507:                        opar.sig = dev_ipar.sig;
                    508:                        opar.le = dev_ipar.le;
                    509:                        opar.msb = dev_ipar.msb;
1.9       ratchov   510:                        aproc_setout(conv, obuf);
1.20      ratchov   511:                        obuf = abuf_new(nblk * round, &opar);
1.9       ratchov   512:                        aproc_setin(conv, obuf);
1.8       ratchov   513:                }
1.10      ratchov   514:                if (!aparams_subset(&opar, &dev_ipar)) {
                    515:                        conv = cmap_new(name, &dev_ipar, &opar);
                    516:                        opar.cmin = dev_ipar.cmin;
                    517:                        opar.cmax = dev_ipar.cmax;
1.7       ratchov   518:                        aproc_setout(conv, obuf);
1.20      ratchov   519:                        obuf = abuf_new(nblk * round, &opar);
1.7       ratchov   520:                        aproc_setin(conv, obuf);
1.6       ratchov   521:                }
1.10      ratchov   522:                if (!aparams_eqrate(&opar, &dev_ipar)) {
1.20      ratchov   523:                        conv = resamp_new(name, dev_round, round);
1.10      ratchov   524:                        opar.rate = dev_ipar.rate;
1.20      ratchov   525:                        round = dev_round;
1.1       ratchov   526:                        aproc_setout(conv, obuf);
1.20      ratchov   527:                        obuf = abuf_new(nblk * round, &opar);
1.1       ratchov   528:                        aproc_setin(conv, obuf);
                    529:                }
                    530:                aproc_setout(dev_sub, obuf);
1.3       ratchov   531:                abuf_ipos(obuf, -dev_sub->u.sub.lat);
1.1       ratchov   532:                obuf->xrun = overrun;
                    533:        }
                    534:
                    535:        /*
1.27    ! ratchov   536:         * Sync play to record.
1.1       ratchov   537:         */
                    538:        if (ibuf && obuf) {
1.3       ratchov   539:                ibuf->duplex = obuf;
                    540:                obuf->duplex = ibuf;
                    541:                dev_sync(ibuf, obuf);
1.13      ratchov   542:        }
1.14      ratchov   543: }
                    544:
                    545: /*
1.27    ! ratchov   546:  * Change the playback volume of the given stream.
1.14      ratchov   547:  */
                    548: void
                    549: dev_setvol(struct abuf *ibuf, int vol)
                    550: {
1.21      ratchov   551:        DPRINTF("dev_setvol: %p\n", ibuf);
1.16      ratchov   552:        if (!dev_getep(&ibuf, NULL)) {
                    553:                DPRINTF("dev_setvol: not connected yet\n");
1.14      ratchov   554:                return;
1.16      ratchov   555:        }
1.14      ratchov   556:        ibuf->mixvol = vol;
1.21      ratchov   557:        DPRINTF("dev_setvol: %p -> %d\n", ibuf, vol);
1.13      ratchov   558: }
                    559:
                    560: /*
1.27    ! ratchov   561:  * Clear buffers of the play and record chains so that when the device
        !           562:  * is started, playback and record start in sync.
1.13      ratchov   563:  */
                    564: void
                    565: dev_clear(void)
                    566: {
                    567:        struct abuf *buf;
                    568:
                    569:        if (dev_mix) {
1.25      ratchov   570:                if (!LIST_EMPTY(&dev_mix->ibuflist)) {
1.13      ratchov   571:                        fprintf(stderr, "dev_clear: mixer not idle\n");
                    572:                        abort();
                    573:                }
                    574:                buf = LIST_FIRST(&dev_mix->obuflist);
                    575:                while (buf) {
                    576:                        abuf_clear(buf);
                    577:                        buf = LIST_FIRST(&buf->rproc->obuflist);
                    578:                }
                    579:                mix_clear(dev_mix);
                    580:        }
                    581:        if (dev_sub) {
1.25      ratchov   582:                if (!LIST_EMPTY(&dev_sub->obuflist)) {
1.13      ratchov   583:                        fprintf(stderr, "dev_suspend: demux not idle\n");
                    584:                        abort();
                    585:                }
                    586:                buf = LIST_FIRST(&dev_sub->ibuflist);
                    587:                while (buf) {
                    588:                        abuf_clear(buf);
                    589:                        buf = LIST_FIRST(&buf->wproc->ibuflist);
                    590:                }
                    591:                sub_clear(dev_sub);
1.1       ratchov   592:        }
                    593: }