[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.29

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