Annotation of src/usr.bin/aucat/dev.c, Revision 1.57
1.57 ! ratchov 1: /* $OpenBSD: dev.c,v 1.56 2010/05/08 15:35:45 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.51 ratchov 17: /*
18: * Device abstraction module
19: *
20: * This module exposes a ``enhanced device'' that uses aproc
21: * structures framework; it does conversions on the fly and can
22: * handle multiple streams. The enhanced device starts and stops
23: * automatically, when streams are attached, and provides
24: * primitives for MIDI control
25: *
26: * From the main loop, the device is used as follows:
27: *
1.57 ! ratchov 28: * 1. create the device using dev_new_xxx()
1.51 ratchov 29: * 2. call dev_run() in the event loop
1.57 ! ratchov 30: * 3. destroy the device using dev_del()
1.51 ratchov 31: * 4. continue running the event loop to drain
32: *
33: * The device is used as follows from aproc context:
34: *
35: * 1. open the device with dev_ref()
36: * 2. negociate parameters (mode, rate, ...)
37: * 3. create your stream (ie allocate and fill abufs)
38: * 4. attach your stream atomically:
39: * - first call dev_wakeup() to ensure device is not suspended
40: * - possibly fetch dynamic parameters (eg. dev_getpos())
41: * - attach your buffers with dev_attach()
42: * 5. close your stream, ie abuf_eof() or abuf_hup()
43: * 6. close the device with dev_unref()
44: *
45: * The device has the following states:
46: *
47: * CLOSED sio_open() is not called, it's not ready and
48: * no streams can be attached; dev_ref() must
49: * be called to open the device
50: *
51: * INIT device is opened, processing chain is ready, but
52: * DMA is not started yet. Streams can attach,
53: * in which case device will automatically switch
54: * to the START state
55: *
56: * START at least one stream is attached, play buffers
57: * are primed (if necessary) DMA is ready and
58: * will start immeadiately (next cycle)
59: *
60: * RUN DMA is started. New streams can attach. If the
61: * device is idle (all streams are closed and
62: * finished draining), then the device
63: * automatically switches to INIT or CLOSED
64: */
65: /*
66: * TODO:
67: *
68: * priming buffer is not ok, because it will insert silence and
69: * break synchronization to other programs.
70: *
71: * priming buffer in server mode is required, because f->bufsz may
72: * be smaller than the server buffer and may cause underrun in the
73: * dev_bufsz part of the buffer, in turn causing apps to break. It
74: * doesn't hurt because we care only in synchronization between
75: * clients.
76: *
77: * Priming is not required in non-server mode, because streams
78: * actually start when they are in the READY state, and their
79: * buffer is large enough to never cause underruns of dev_bufsz.
80: *
81: * Fix sock.c to allocate dev_bufsz, but to use only appbufsz --
82: * or whatever -- but to avoid underruns in dev_bufsz. Then remove
83: * this ugly hack.
84: *
85: */
1.1 ratchov 86: #include <stdio.h>
87: #include <stdlib.h>
88: #include <unistd.h>
89:
90: #include "abuf.h"
91: #include "aproc.h"
1.27 ratchov 92: #include "conf.h"
93: #include "dev.h"
1.3 ratchov 94: #include "pipe.h"
1.38 ratchov 95: #include "miofile.h"
1.42 ratchov 96: #include "siofile.h"
1.28 ratchov 97: #include "midi.h"
1.46 ratchov 98: #include "opt.h"
1.39 ratchov 99: #ifdef DEBUG
100: #include "dbg.h"
101: #endif
1.1 ratchov 102:
1.57 ! ratchov 103: int dev_open(struct dev *);
! 104: void dev_close(struct dev *);
! 105: void dev_start(struct dev *);
! 106: void dev_stop(struct dev *);
! 107: void dev_clear(struct dev *);
! 108: void dev_prime(struct dev *);
! 109:
! 110: struct dev *dev_list = NULL;
1.38 ratchov 111:
112: /*
1.51 ratchov 113: * Create a sndio device
1.28 ratchov 114: */
1.57 ! ratchov 115: struct dev *
! 116: dev_new_sio(char *path,
! 117: unsigned mode, struct aparams *dipar, struct aparams *dopar,
! 118: unsigned bufsz, unsigned round, unsigned hold, unsigned prime)
! 119: {
! 120: struct dev *d;
! 121:
! 122: d = malloc(sizeof(struct dev));
! 123: if (d == NULL) {
! 124: perror("malloc");
! 125: exit(1);
! 126: }
! 127: d->path = path;
! 128: d->reqmode = mode;
1.51 ratchov 129: if (mode & MODE_PLAY)
1.57 ! ratchov 130: d->reqopar = *dopar;
1.51 ratchov 131: if (mode & MODE_RECMASK)
1.57 ! ratchov 132: d->reqipar = *dipar;
! 133: d->reqbufsz = bufsz;
! 134: d->reqround = round;
! 135: d->prime = prime;
! 136: d->hold = hold;
! 137: d->pstate = DEV_CLOSED;
! 138: d->next = dev_list;
! 139: dev_list = d;
! 140: if (d->hold && !dev_open(d)) {
! 141: dev_del(d);
! 142: return NULL;
! 143: }
! 144: return d;
1.28 ratchov 145: }
1.24 ratchov 146:
147: /*
1.51 ratchov 148: * Create a loopback synchronous device
1.24 ratchov 149: */
1.57 ! ratchov 150: struct dev *
! 151: dev_new_loop(struct aparams *dipar, struct aparams *dopar, unsigned bufsz)
1.24 ratchov 152: {
153: struct aparams par;
154: unsigned cmin, cmax, rate;
1.57 ! ratchov 155: struct dev *d;
1.24 ratchov 156:
1.57 ! ratchov 157: d = malloc(sizeof(struct dev));
! 158: if (d == NULL) {
! 159: perror("malloc");
! 160: exit(1);
! 161: }
1.24 ratchov 162: cmin = (dipar->cmin < dopar->cmin) ? dipar->cmin : dopar->cmin;
163: cmax = (dipar->cmax > dopar->cmax) ? dipar->cmax : dopar->cmax;
164: rate = (dipar->rate > dopar->rate) ? dipar->rate : dopar->rate;
165: aparams_init(&par, cmin, cmax, rate);
1.57 ! ratchov 166: d->reqipar = par;
! 167: d->reqopar = par;
! 168: d->rate = rate;
! 169: d->reqround = (bufsz + 1) / 2;
! 170: d->reqbufsz = d->reqround * 2;
! 171: d->reqmode = MODE_PLAY | MODE_REC | MODE_LOOP;
! 172: d->pstate = DEV_CLOSED;
! 173: d->hold = 0;
! 174: d->prime = 0;
! 175: d->next = dev_list;
! 176: dev_list = d;
! 177: return d;
1.24 ratchov 178: }
1.1 ratchov 179:
1.51 ratchov 180: /*
181: * Create a MIDI thru box device
182: */
1.57 ! ratchov 183: struct dev *
! 184: dev_new_thru(void)
1.1 ratchov 185: {
1.57 ! ratchov 186: struct dev *d;
! 187:
! 188: d = malloc(sizeof(struct dev));
! 189: if (d == NULL) {
! 190: perror("malloc");
! 191: exit(1);
! 192: }
! 193: d->reqmode = 0;
! 194: d->pstate = DEV_CLOSED;
! 195: d->hold = 0;
! 196: d->prime = 0;
! 197: d->next = dev_list;
! 198: dev_list = d;
! 199: return d;
1.1 ratchov 200: }
201:
202: /*
1.51 ratchov 203: * Open the device with the dev_reqxxx capabilities. Setup a mixer, demuxer,
204: * monitor, midi control, and any necessary conversions.
1.1 ratchov 205: */
1.26 ratchov 206: int
1.57 ! ratchov 207: dev_open(struct dev *d)
1.1 ratchov 208: {
1.23 ratchov 209: struct file *f;
1.51 ratchov 210: struct aparams par;
1.1 ratchov 211: struct aproc *conv;
212: struct abuf *buf;
1.51 ratchov 213: unsigned siomode;
214:
1.57 ! ratchov 215: d->mode = d->reqmode;
! 216: d->round = d->reqround;
! 217: d->bufsz = d->reqbufsz;
! 218: d->ipar = d->reqipar;
! 219: d->opar = d->reqopar;
! 220: d->rec = NULL;
! 221: d->play = NULL;
! 222: d->mon = NULL;
! 223: d->submon = NULL;
! 224: d->rate = 0;
1.36 ratchov 225:
1.3 ratchov 226: /*
1.51 ratchov 227: * If needed, open the device (ie create dev_rec and dev_play)
1.3 ratchov 228: */
1.57 ! ratchov 229: if ((d->mode & (MODE_PLAY | MODE_REC)) && !(d->mode & MODE_LOOP)) {
! 230: siomode = d->mode & (MODE_PLAY | MODE_REC);
1.51 ratchov 231: f = (struct file *)siofile_new(&siofile_ops,
1.57 ! ratchov 232: d->path,
1.51 ratchov 233: &siomode,
1.57 ! ratchov 234: &d->ipar,
! 235: &d->opar,
! 236: &d->bufsz,
! 237: &d->round);
1.51 ratchov 238: if (f == NULL) {
1.39 ratchov 239: #ifdef DEBUG
1.51 ratchov 240: if (debug_level >= 1) {
1.57 ! ratchov 241: dbg_puts(d->path ? d->path : "default");
1.51 ratchov 242: dbg_puts(": failed to open audio device\n");
243: }
244: #endif
245: return 0;
1.39 ratchov 246: }
1.51 ratchov 247: if (!(siomode & MODE_PLAY))
1.57 ! ratchov 248: d->mode &= ~(MODE_PLAY | MODE_MON);
1.51 ratchov 249: if (!(siomode & MODE_REC))
1.57 ! ratchov 250: d->mode &= ~MODE_REC;
! 251: if ((d->mode & (MODE_PLAY | MODE_REC)) == 0) {
1.51 ratchov 252: #ifdef DEBUG
253: if (debug_level >= 1) {
1.57 ! ratchov 254: dbg_puts(d->path ? d->path : "default");
1.51 ratchov 255: dbg_puts(": mode not supported by device\n");
256: }
1.39 ratchov 257: #endif
1.51 ratchov 258: return 0;
259: }
1.57 ! ratchov 260: d->rate = d->mode & MODE_REC ? d->ipar.rate : d->opar.rate;
1.39 ratchov 261: #ifdef DEBUG
262: if (debug_level >= 2) {
1.57 ! ratchov 263: if (d->mode & MODE_REC) {
1.51 ratchov 264: dbg_puts("hw recording ");
1.57 ! ratchov 265: aparams_dbg(&d->ipar);
1.51 ratchov 266: dbg_puts("\n");
267: }
1.57 ! ratchov 268: if (d->mode & MODE_PLAY) {
1.51 ratchov 269: dbg_puts("hw playing ");
1.57 ! ratchov 270: aparams_dbg(&d->opar);
1.51 ratchov 271: dbg_puts("\n");
272: }
1.39 ratchov 273: }
274: #endif
1.57 ! ratchov 275: if (d->mode & MODE_REC) {
! 276: d->rec = rsio_new(f);
! 277: d->rec->refs++;
! 278: }
! 279: if (d->mode & MODE_PLAY) {
! 280: d->play = wsio_new(f);
! 281: d->play->refs++;
1.51 ratchov 282: }
1.3 ratchov 283: }
1.11 ratchov 284:
285: /*
1.51 ratchov 286: * Create the midi control end, or a simple thru box
287: * if there's no device
288: */
1.57 ! ratchov 289: d->midi = (d->mode == 0) ? thru_new("thru") : ctl_new("ctl", d);
! 290: d->midi->refs++;
1.51 ratchov 291:
292: /*
293: * Create mixer, demuxer and monitor
1.1 ratchov 294: */
1.57 ! ratchov 295: if (d->mode & MODE_PLAY) {
! 296: d->mix = mix_new("play", d->bufsz, d->round);
! 297: d->mix->refs++;
! 298: d->mix->u.mix.ctl = d->midi;
! 299: }
! 300: if (d->mode & MODE_REC) {
! 301: d->sub = sub_new("rec", d->bufsz, d->round);
! 302: d->sub->refs++;
1.51 ratchov 303: /*
304: * If not playing, use the record end as clock source
305: */
1.57 ! ratchov 306: if (!(d->mode & MODE_PLAY))
! 307: d->sub->u.sub.ctl = d->midi;
1.51 ratchov 308: }
1.57 ! ratchov 309: if (d->mode & MODE_LOOP) {
1.51 ratchov 310: /*
311: * connect mixer out to demuxer in
312: */
1.57 ! ratchov 313: buf = abuf_new(d->bufsz, &d->opar);
! 314: aproc_setout(d->mix, buf);
! 315: aproc_setin(d->sub, buf);
! 316:
! 317: d->mix->flags |= APROC_QUIT;
! 318: d->sub->flags |= APROC_QUIT;
! 319: d->rate = d->opar.rate;
1.51 ratchov 320: }
1.57 ! ratchov 321: if (d->rec) {
! 322: aparams_init(&par, d->ipar.cmin, d->ipar.cmax, d->rate);
1.51 ratchov 323:
1.1 ratchov 324: /*
1.51 ratchov 325: * Create device <-> demuxer buffer
1.1 ratchov 326: */
1.57 ! ratchov 327: buf = abuf_new(d->bufsz, &d->ipar);
! 328: aproc_setout(d->rec, buf);
1.1 ratchov 329:
330: /*
1.51 ratchov 331: * Insert a converter, if needed.
1.1 ratchov 332: */
1.57 ! ratchov 333: if (!aparams_eqenc(&d->ipar, &par)) {
! 334: conv = dec_new("rec", &d->ipar);
1.1 ratchov 335: aproc_setin(conv, buf);
1.57 ! ratchov 336: buf = abuf_new(d->round, &par);
1.1 ratchov 337: aproc_setout(conv, buf);
338: }
1.57 ! ratchov 339: d->ipar = par;
! 340: aproc_setin(d->sub, buf);
1.1 ratchov 341: }
1.57 ! ratchov 342: if (d->play) {
! 343: aparams_init(&par, d->opar.cmin, d->opar.cmax, d->rate);
1.1 ratchov 344:
345: /*
1.51 ratchov 346: * Create device <-> mixer buffer
1.1 ratchov 347: */
1.57 ! ratchov 348: buf = abuf_new(d->bufsz, &d->opar);
! 349: aproc_setin(d->play, buf);
1.25 ratchov 350:
1.1 ratchov 351: /*
1.27 ratchov 352: * Append a converter, if needed.
1.1 ratchov 353: */
1.57 ! ratchov 354: if (!aparams_eqenc(&par, &d->opar)) {
! 355: conv = enc_new("play", &d->opar);
1.1 ratchov 356: aproc_setout(conv, buf);
1.57 ! ratchov 357: buf = abuf_new(d->round, &par);
1.1 ratchov 358: aproc_setin(conv, buf);
359: }
1.57 ! ratchov 360: d->opar = par;
! 361: aproc_setout(d->mix, buf);
1.1 ratchov 362: }
1.57 ! ratchov 363: if (d->mode & MODE_MON) {
! 364: d->mon = mon_new("mon", d->bufsz);
! 365: d->mon->refs++;
! 366: buf = abuf_new(d->bufsz, &d->opar);
! 367: aproc_setout(d->mon, buf);
1.46 ratchov 368:
369: /*
370: * Append a "sub" to which clients will connect.
371: */
1.57 ! ratchov 372: d->submon = sub_new("mon", d->bufsz, d->round);
! 373: d->submon->refs++;
! 374: aproc_setin(d->submon, buf);
1.46 ratchov 375:
376: /*
1.51 ratchov 377: * Attach to the mixer
1.46 ratchov 378: */
1.57 ! ratchov 379: d->mix->u.mix.mon = d->mon;
! 380: d->mon->refs++;
1.46 ratchov 381: }
1.39 ratchov 382: #ifdef DEBUG
1.51 ratchov 383: if (debug_level >= 2) {
1.57 ! ratchov 384: if (d->mode & (MODE_PLAY | MODE_RECMASK)) {
1.51 ratchov 385: dbg_puts("device block size is ");
1.57 ! ratchov 386: dbg_putu(d->round);
1.51 ratchov 387: dbg_puts(" frames, using ");
1.57 ! ratchov 388: dbg_putu(d->bufsz / d->round);
1.51 ratchov 389: dbg_puts(" blocks\n");
390: }
1.39 ratchov 391: }
392: #endif
1.57 ! ratchov 393: d->pstate = DEV_INIT;
! 394: if (d->prime)
! 395: dev_prime(d);
1.26 ratchov 396: return 1;
1.1 ratchov 397: }
398:
399: /*
1.27 ratchov 400: * Cleanly stop and drain everything and close the device
401: * once both play chain and record chain are gone.
1.1 ratchov 402: */
403: void
1.57 ! ratchov 404: dev_close(struct dev *d)
1.1 ratchov 405: {
406: struct file *f;
407:
1.50 ratchov 408: /*
409: * if the device is starting, ensure it actually starts
410: * so buffers are drained, else clear any buffers
411: */
1.57 ! ratchov 412: switch (d->pstate) {
1.50 ratchov 413: case DEV_START:
414: #ifdef DEBUG
415: if (debug_level >= 3)
416: dbg_puts("draining device\n");
417: #endif
1.57 ! ratchov 418: dev_start(d);
1.50 ratchov 419: break;
420: case DEV_INIT:
421: #ifdef DEBUG
422: if (debug_level >= 3)
423: dbg_puts("flushing device\n");
424: #endif
1.57 ! ratchov 425: dev_clear(d);
1.50 ratchov 426: break;
427: }
1.39 ratchov 428: #ifdef DEBUG
429: if (debug_level >= 2)
1.51 ratchov 430: dbg_puts("closing device\n");
1.39 ratchov 431: #endif
1.51 ratchov 432:
1.57 ! ratchov 433: if (d->mix) {
1.3 ratchov 434: /*
1.32 ratchov 435: * Put the mixer in ``autoquit'' state and generate
436: * EOF on all inputs connected it. Once buffers are
437: * drained the mixer will terminate and shutdown the
438: * device.
1.3 ratchov 439: *
440: * NOTE: since file_eof() can destroy the file and
441: * reorder the file_list, we have to restart the loop
1.27 ratchov 442: * after each call to file_eof().
1.3 ratchov 443: */
1.57 ! ratchov 444: if (APROC_OK(d->mix))
! 445: mix_quit(d->mix);
1.51 ratchov 446:
447: /*
448: * XXX: handle this in mix_done()
449: */
1.57 ! ratchov 450: if (APROC_OK(d->mix->u.mix.mon)) {
! 451: d->mix->u.mix.mon->refs--;
! 452: aproc_del(d->mix->u.mix.mon);
! 453: d->mix->u.mix.mon = NULL;
1.46 ratchov 454: }
1.32 ratchov 455: restart_mix:
1.3 ratchov 456: LIST_FOREACH(f, &file_list, entry) {
1.32 ratchov 457: if (f->rproc != NULL &&
1.57 ! ratchov 458: aproc_depend(d->mix, f->rproc)) {
1.3 ratchov 459: file_eof(f);
1.32 ratchov 460: goto restart_mix;
1.3 ratchov 461: }
462: }
1.57 ! ratchov 463: } else if (d->sub || d->submon) {
1.3 ratchov 464: /*
1.32 ratchov 465: * Same as above, but since there's no mixer,
466: * we generate EOF on the record-end of the
467: * device.
468: */
469: restart_sub:
470: LIST_FOREACH(f, &file_list, entry) {
471: if (f->rproc != NULL &&
1.57 ! ratchov 472: (aproc_depend(d->sub, f->rproc) ||
! 473: aproc_depend(d->submon, f->rproc))) {
1.32 ratchov 474: file_eof(f);
475: goto restart_sub;
1.23 ratchov 476: }
1.32 ratchov 477: }
478: }
1.57 ! ratchov 479: if (d->midi) {
! 480: d->midi->flags |= APROC_QUIT;
! 481: if (LIST_EMPTY(&d->midi->ins))
! 482: aproc_del(d->midi);
1.36 ratchov 483: restart_midi:
484: LIST_FOREACH(f, &file_list, entry) {
485: if (f->rproc &&
1.57 ! ratchov 486: aproc_depend(d->midi, f->rproc)) {
1.36 ratchov 487: file_eof(f);
488: goto restart_midi;
489: }
490: }
491: }
1.57 ! ratchov 492: if (d->mix) {
! 493: if (--d->mix->refs == 0 && (d->mix->flags & APROC_ZOMB))
! 494: aproc_del(d->mix);
! 495: d->mix = NULL;
! 496: }
! 497: if (d->play) {
! 498: if (--d->play->refs == 0 && (d->play->flags & APROC_ZOMB))
! 499: aproc_del(d->play);
! 500: d->play = NULL;
! 501: }
! 502: if (d->sub) {
! 503: if (--d->sub->refs == 0 && (d->sub->flags & APROC_ZOMB))
! 504: aproc_del(d->sub);
! 505: d->sub = NULL;
! 506: }
! 507: if (d->rec) {
! 508: if (--d->rec->refs == 0 && (d->rec->flags & APROC_ZOMB))
! 509: aproc_del(d->rec);
! 510: d->rec = NULL;
! 511: }
! 512: if (d->submon) {
! 513: if (--d->submon->refs == 0 && (d->submon->flags & APROC_ZOMB))
! 514: aproc_del(d->submon);
! 515: d->submon = NULL;
! 516: }
! 517: if (d->mon) {
! 518: if (--d->mon->refs == 0 && (d->mon->flags & APROC_ZOMB))
! 519: aproc_del(d->mon);
! 520: d->mon = NULL;
! 521: }
! 522: if (d->midi) {
! 523: if (--d->midi->refs == 0 && (d->midi->flags & APROC_ZOMB))
! 524: aproc_del(d->midi);
! 525: d->midi = NULL;
1.32 ratchov 526: }
1.57 ! ratchov 527: d->pstate = DEV_CLOSED;
1.51 ratchov 528: }
529:
530: /*
531: * Free the device
532: */
533: void
1.57 ! ratchov 534: dev_del(struct dev *d)
1.51 ratchov 535: {
1.57 ! ratchov 536: struct dev **p;
! 537:
! 538: if (d->pstate != DEV_CLOSED)
! 539: dev_close(d);
! 540: for (p = &dev_list; *p != d; p = &(*p)->next) {
! 541: #ifdef DEBUG
! 542: if (*p == NULL) {
! 543: dbg_puts("device to delete not on the list\n");
! 544: dbg_panic();
! 545: }
! 546: #endif
! 547: }
! 548: *p = d->next;
! 549: free(d);
1.51 ratchov 550: }
551:
552: /*
553: * Open a MIDI device and connect it to the thru box
554: */
555: int
1.57 ! ratchov 556: dev_thruadd(struct dev *d, char *name, int in, int out)
1.51 ratchov 557: {
558: struct file *f;
559: struct abuf *rbuf = NULL, *wbuf = NULL;
560: struct aproc *rproc, *wproc;
561:
1.57 ! ratchov 562: if (!dev_ref(d))
1.51 ratchov 563: return 0;
564: f = (struct file *)miofile_new(&miofile_ops, name, in, out);
565: if (f == NULL)
566: return 0;
567: if (in) {
568: rproc = rfile_new(f);
569: rbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
570: aproc_setout(rproc, rbuf);
571: }
572: if (out) {
573: wproc = wfile_new(f);
574: wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
575: aproc_setin(wproc, wbuf);
576: }
1.57 ! ratchov 577: dev_midiattach(d, rbuf, wbuf);
1.51 ratchov 578: return 1;
579: }
580:
581: /*
582: * Attach a bi-directional MIDI stream to the MIDI device
583: */
584: void
1.57 ! ratchov 585: dev_midiattach(struct dev *d, struct abuf *ibuf, struct abuf *obuf)
1.51 ratchov 586: {
587: if (ibuf)
1.57 ! ratchov 588: aproc_setin(d->midi, ibuf);
1.51 ratchov 589: if (obuf) {
1.57 ! ratchov 590: aproc_setout(d->midi, obuf);
1.51 ratchov 591: if (ibuf) {
592: ibuf->duplex = obuf;
593: obuf->duplex = ibuf;
594: }
1.1 ratchov 595: }
596: }
597:
1.51 ratchov 598: unsigned
1.57 ! ratchov 599: dev_roundof(struct dev *d, unsigned newrate)
1.51 ratchov 600: {
1.57 ! ratchov 601: return (d->round * newrate + d->rate / 2) / d->rate;
1.51 ratchov 602: }
603:
1.1 ratchov 604: /*
1.27 ratchov 605: * Start the (paused) device. By default it's paused.
1.1 ratchov 606: */
607: void
1.57 ! ratchov 608: dev_start(struct dev *d)
1.1 ratchov 609: {
1.22 ratchov 610: struct file *f;
611:
1.46 ratchov 612: #ifdef DEBUG
613: if (debug_level >= 2)
1.51 ratchov 614: dbg_puts("starting device\n");
1.46 ratchov 615: #endif
1.57 ! ratchov 616: d->pstate = DEV_RUN;
! 617: if (d->mode & MODE_LOOP)
1.52 ratchov 618: return;
1.57 ! ratchov 619: if (APROC_OK(d->mix))
! 620: d->mix->flags |= APROC_DROP;
! 621: if (APROC_OK(d->sub))
! 622: d->sub->flags |= APROC_DROP;
! 623: if (APROC_OK(d->submon))
! 624: d->submon->flags |= APROC_DROP;
! 625: if (APROC_OK(d->play) && d->play->u.io.file) {
! 626: f = d->play->u.io.file;
1.22 ratchov 627: f->ops->start(f);
1.57 ! ratchov 628: } else if (APROC_OK(d->rec) && d->rec->u.io.file) {
! 629: f = d->rec->u.io.file;
1.22 ratchov 630: f->ops->start(f);
631: }
1.1 ratchov 632: }
633:
634: /*
1.46 ratchov 635: * Pause the device. This may trigger context switches,
636: * so it shouldn't be called from aproc methods
1.1 ratchov 637: */
638: void
1.57 ! ratchov 639: dev_stop(struct dev *d)
1.1 ratchov 640: {
1.22 ratchov 641: struct file *f;
642:
1.52 ratchov 643: #ifdef DEBUG
644: if (debug_level >= 2)
1.57 ! ratchov 645: dbg_puts("device stopped\n");
1.52 ratchov 646: #endif
1.57 ! ratchov 647: d->pstate = DEV_INIT;
! 648: if (d->mode & MODE_LOOP)
1.52 ratchov 649: return;
1.57 ! ratchov 650: if (APROC_OK(d->play) && d->play->u.io.file) {
! 651: f = d->play->u.io.file;
1.22 ratchov 652: f->ops->stop(f);
1.57 ! ratchov 653: } else if (APROC_OK(d->rec) && d->rec->u.io.file) {
! 654: f = d->rec->u.io.file;
1.22 ratchov 655: f->ops->stop(f);
656: }
1.57 ! ratchov 657: if (APROC_OK(d->mix))
! 658: d->mix->flags &= ~APROC_DROP;
! 659: if (APROC_OK(d->sub))
! 660: d->sub->flags &= ~APROC_DROP;
! 661: if (APROC_OK(d->submon))
! 662: d->submon->flags &= ~APROC_DROP;
1.51 ratchov 663: }
664:
665: int
1.57 ! ratchov 666: dev_ref(struct dev *d)
1.51 ratchov 667: {
668: #ifdef DEBUG
669: if (debug_level >= 3)
670: dbg_puts("device requested\n");
671: #endif
1.57 ! ratchov 672: if (d->pstate == DEV_CLOSED && !dev_open(d)) {
! 673: if (d->hold)
! 674: dev_del(d);
1.51 ratchov 675: return 0;
1.57 ! ratchov 676: }
! 677: d->refcnt++;
1.51 ratchov 678: return 1;
679: }
680:
681: void
1.57 ! ratchov 682: dev_unref(struct dev *d)
1.51 ratchov 683: {
684: #ifdef DEBUG
685: if (debug_level >= 3)
686: dbg_puts("device released\n");
687: #endif
1.57 ! ratchov 688: d->refcnt--;
! 689: if (d->refcnt == 0 && d->pstate == DEV_INIT && !d->hold)
! 690: dev_close(d);
1.51 ratchov 691: }
692:
693: /*
694: * There are actions (like start/stop/close ... ) that may trigger aproc
695: * operations, a thus cannot be started from aproc context.
696: * To avoid problems, aprocs only change the s!tate of the device,
697: * and actual operations are triggered from the main loop,
698: * outside the aproc code path.
699: *
700: * The following routine invokes pending actions, returns 0
701: * on fatal error
702: */
703: int
1.57 ! ratchov 704: dev_run(struct dev *d)
1.51 ratchov 705: {
1.57 ! ratchov 706: if (d->pstate == DEV_CLOSED)
1.51 ratchov 707: return 1;
708: /*
709: * check if device isn't gone
710: */
1.57 ! ratchov 711: if (((d->mode & MODE_PLAY) && !APROC_OK(d->mix)) ||
! 712: ((d->mode & MODE_REC) && !APROC_OK(d->sub)) ||
! 713: ((d->mode & MODE_MON) && !APROC_OK(d->submon))) {
1.51 ratchov 714: #ifdef DEBUG
715: if (debug_level >= 1)
716: dbg_puts("device disappeared\n");
717: #endif
1.57 ! ratchov 718: if (d->hold) {
! 719: dev_del(d);
! 720: return 0;
! 721: }
! 722: dev_close(d);
! 723: return 1;
1.51 ratchov 724: }
1.57 ! ratchov 725: switch (d->pstate) {
1.51 ratchov 726: case DEV_INIT:
727: /* nothing */
728: break;
729: case DEV_START:
1.57 ! ratchov 730: dev_start(d);
1.51 ratchov 731: /* PASSTHROUGH */
732: case DEV_RUN:
733: /*
734: * if the device is not used, then stop it
735: */
1.57 ! ratchov 736: if ((!APROC_OK(d->mix) ||
! 737: d->mix->u.mix.idle > 2 * d->bufsz) &&
! 738: (!APROC_OK(d->sub) ||
! 739: d->sub->u.sub.idle > 2 * d->bufsz) &&
! 740: (!APROC_OK(d->submon) ||
! 741: d->submon->u.sub.idle > 2 * d->bufsz) &&
! 742: (!APROC_OK(d->midi) ||
! 743: d->midi->u.ctl.tstate != CTL_RUN)) {
1.51 ratchov 744: #ifdef DEBUG
745: if (debug_level >= 3)
746: dbg_puts("device idle, suspending\n");
1.46 ratchov 747: #endif
1.57 ! ratchov 748: dev_stop(d);
! 749: if (d->refcnt == 0 && !d->hold)
! 750: dev_close(d);
1.56 ratchov 751: else {
1.57 ! ratchov 752: dev_clear(d);
! 753: if (d->prime)
! 754: dev_prime(d);
1.56 ratchov 755: }
1.51 ratchov 756: }
757: break;
758: }
759: return 1;
760: }
761:
762: /*
763: * If the device is paused, then resume it. If the caller is using
764: * full-duplex and its buffers are small, the ``prime'' flag
765: * could be set to initialize device buffers with silence
766: *
767: * This routine can be called from aproc context.
768: */
769: void
1.57 ! ratchov 770: dev_wakeup(struct dev *d)
1.51 ratchov 771: {
1.57 ! ratchov 772: if (d->pstate == DEV_INIT)
! 773: d->pstate = DEV_START;
1.1 ratchov 774: }
775:
776: /*
1.27 ratchov 777: * Find the end points connected to the mix/sub.
1.14 ratchov 778: */
779: int
1.57 ! ratchov 780: dev_getep(struct dev *d,
! 781: unsigned mode, struct abuf **sibuf, struct abuf **sobuf)
1.14 ratchov 782: {
783: struct abuf *ibuf, *obuf;
784:
1.46 ratchov 785: if (mode & MODE_PLAY) {
1.57 ! ratchov 786: if (!APROC_OK(d->mix))
1.46 ratchov 787: return 0;
1.14 ratchov 788: ibuf = *sibuf;
789: for (;;) {
790: if (!ibuf || !ibuf->rproc) {
1.39 ratchov 791: #ifdef DEBUG
792: if (debug_level >= 3) {
793: abuf_dbg(*sibuf);
794: dbg_puts(": not connected to device\n");
795: }
796: #endif
1.14 ratchov 797: return 0;
798: }
1.57 ! ratchov 799: if (ibuf->rproc == d->mix)
1.14 ratchov 800: break;
1.49 ratchov 801: ibuf = LIST_FIRST(&ibuf->rproc->outs);
1.14 ratchov 802: }
1.21 ratchov 803: *sibuf = ibuf;
1.14 ratchov 804: }
1.46 ratchov 805: if (mode & MODE_REC) {
1.57 ! ratchov 806: if (!APROC_OK(d->sub))
1.46 ratchov 807: return 0;
1.14 ratchov 808: obuf = *sobuf;
809: for (;;) {
810: if (!obuf || !obuf->wproc) {
1.39 ratchov 811: #ifdef DEBUG
812: if (debug_level >= 3) {
813: abuf_dbg(*sobuf);
814: dbg_puts(": not connected to device\n");
815: }
816: #endif
1.14 ratchov 817: return 0;
818: }
1.57 ! ratchov 819: if (obuf->wproc == d->sub)
1.14 ratchov 820: break;
1.49 ratchov 821: obuf = LIST_FIRST(&obuf->wproc->ins);
1.14 ratchov 822: }
1.21 ratchov 823: *sobuf = obuf;
1.14 ratchov 824: }
1.46 ratchov 825: if (mode & MODE_MON) {
1.57 ! ratchov 826: if (!APROC_OK(d->submon))
1.46 ratchov 827: return 0;
828: obuf = *sobuf;
829: for (;;) {
830: if (!obuf || !obuf->wproc) {
831: #ifdef DEBUG
832: if (debug_level >= 3) {
833: abuf_dbg(*sobuf);
834: dbg_puts(": not connected to device\n");
835: }
836: #endif
837: return 0;
838: }
1.57 ! ratchov 839: if (obuf->wproc == d->submon)
1.46 ratchov 840: break;
1.49 ratchov 841: obuf = LIST_FIRST(&obuf->wproc->ins);
1.46 ratchov 842: }
843: *sobuf = obuf;
844: }
1.14 ratchov 845: return 1;
846: }
847:
848: /*
1.27 ratchov 849: * Sync play buffer to rec buffer (for instance when one of
850: * them underruns/overruns).
1.1 ratchov 851: */
852: void
1.57 ! ratchov 853: dev_sync(struct dev *d, unsigned mode, struct abuf *ibuf, struct abuf *obuf)
1.1 ratchov 854: {
1.53 ratchov 855: int delta, offs;
1.57 ! ratchov 856: struct abuf *mbuf = NULL;
1.3 ratchov 857:
1.57 ! ratchov 858: if (!dev_getep(d, mode, &ibuf, &obuf))
1.3 ratchov 859: return;
860: /*
1.27 ratchov 861: * Calculate delta, the number of frames the play chain is ahead
1.3 ratchov 862: * of the record chain. It's necessary to schedule silences (or
863: * drops) in order to start playback and record in sync.
864: */
1.53 ratchov 865: offs = 0;
866: delta = 0;
1.57 ! ratchov 867: if (APROC_OK(d->mix)) {
! 868: mbuf = LIST_FIRST(&d->mix->outs);
1.53 ratchov 869: offs += mbuf->w.mix.todo;
1.57 ! ratchov 870: delta += d->mix->u.mix.lat;
1.53 ratchov 871: }
1.57 ! ratchov 872: if (APROC_OK(d->sub))
! 873: delta += d->sub->u.sub.lat;
1.39 ratchov 874: #ifdef DEBUG
875: if (debug_level >= 3) {
1.53 ratchov 876: dbg_puts("syncing device");
1.57 ! ratchov 877: if (APROC_OK(d->mix)) {
1.51 ratchov 878: dbg_puts(", ");
1.57 ! ratchov 879: aproc_dbg(d->mix);
1.53 ratchov 880: dbg_puts(": todo = ");
881: dbg_putu(mbuf->w.mix.todo);
882: dbg_puts(": lat = ");
1.57 ! ratchov 883: dbg_putu(d->mix->u.mix.lat);
1.46 ratchov 884: }
1.57 ! ratchov 885: if (APROC_OK(d->sub)) {
1.51 ratchov 886: dbg_puts(", ");
1.57 ! ratchov 887: aproc_dbg(d->sub);
1.53 ratchov 888: dbg_puts(": lat = ");
1.57 ! ratchov 889: dbg_putu(d->sub->u.sub.lat);
1.46 ratchov 890: }
1.39 ratchov 891: dbg_puts("\n");
892: }
893: #endif
1.53 ratchov 894: if (mode & MODE_PLAY)
895: mix_drop(ibuf, -offs);
896: if (mode & MODE_RECMASK)
897: sub_silence(obuf, -(offs + delta));
1.36 ratchov 898: }
899:
900: /*
901: * return the current latency (in frames), ie the latency that
902: * a stream would have if dev_attach() is called on it.
903: */
904: int
1.57 ! ratchov 905: dev_getpos(struct dev *d)
1.36 ratchov 906: {
1.53 ratchov 907: struct abuf *mbuf = NULL;
1.36 ratchov 908:
1.57 ! ratchov 909: if (APROC_OK(d->mix)) {
! 910: mbuf = LIST_FIRST(&d->mix->outs);
! 911: return -(mbuf->w.mix.todo + d->mix->u.mix.lat);
1.54 ratchov 912: } else
913: return 0;
1.1 ratchov 914: }
915:
916: /*
1.27 ratchov 917: * Attach the given input and output buffers to the mixer and the
1.1 ratchov 918: * multiplexer respectively. The operation is done synchronously, so
919: * both buffers enter in sync. If buffers do not match play
1.27 ratchov 920: * and rec.
1.1 ratchov 921: */
922: void
1.57 ! ratchov 923: dev_attach(struct dev *d, char *name, unsigned mode,
1.48 ratchov 924: struct abuf *ibuf, struct aparams *sipar, unsigned inch,
925: struct abuf *obuf, struct aparams *sopar, unsigned onch,
1.46 ratchov 926: unsigned xrun, int vol)
1.1 ratchov 927: {
928: struct abuf *pbuf = NULL, *rbuf = NULL;
1.12 ratchov 929: struct aparams ipar, opar;
1.1 ratchov 930: struct aproc *conv;
1.48 ratchov 931: unsigned round, nblk, nch;
1.20 ratchov 932:
1.46 ratchov 933: #ifdef DEBUG
1.57 ! ratchov 934: if ((!APROC_OK(d->mix) && (mode & MODE_PLAY)) ||
! 935: (!APROC_OK(d->sub) && (mode & MODE_REC)) ||
! 936: (!APROC_OK(d->submon) && (mode & MODE_MON))) {
1.46 ratchov 937: dbg_puts("mode beyond device mode, not attaching\n");
938: return;
939: }
940: #endif
941: if (mode & MODE_PLAY) {
1.12 ratchov 942: ipar = *sipar;
1.57 ! ratchov 943: pbuf = LIST_FIRST(&d->mix->outs);
! 944: nblk = (d->bufsz / d->round + 3) / 4;
! 945: round = dev_roundof(d, ipar.rate);
1.48 ratchov 946: nch = ipar.cmax - ipar.cmin + 1;
1.57 ! ratchov 947: if (!aparams_eqenc(&ipar, &d->opar)) {
1.10 ratchov 948: conv = dec_new(name, &ipar);
1.57 ! ratchov 949: ipar.bps = d->opar.bps;
! 950: ipar.bits = d->opar.bits;
! 951: ipar.sig = d->opar.sig;
! 952: ipar.le = d->opar.le;
! 953: ipar.msb = d->opar.msb;
1.25 ratchov 954: aproc_setin(conv, ibuf);
1.20 ratchov 955: ibuf = abuf_new(nblk * round, &ipar);
1.9 ratchov 956: aproc_setout(conv, ibuf);
1.8 ratchov 957: }
1.48 ratchov 958: if (inch > 0 && nch >= inch * 2) {
959: conv = join_new(name);
960: aproc_setin(conv, ibuf);
961: ipar.cmax = ipar.cmin + inch - 1;
962: ibuf = abuf_new(nblk * round, &ipar);
963: aproc_setout(conv, ibuf);
964: }
1.57 ! ratchov 965: if (!aparams_eqrate(&ipar, &d->opar)) {
! 966: conv = resamp_new(name, round, d->round);
! 967: ipar.rate = d->opar.rate;
! 968: round = d->round;
1.5 ratchov 969: aproc_setin(conv, ibuf);
1.20 ratchov 970: ibuf = abuf_new(nblk * round, &ipar);
1.5 ratchov 971: aproc_setout(conv, ibuf);
1.1 ratchov 972: }
1.48 ratchov 973: if (inch > 0 && nch * 2 <= inch) {
974: conv = join_new(name);
975: aproc_setin(conv, ibuf);
976: ipar.cmax = ipar.cmin + inch - 1;
977: ibuf = abuf_new(nblk * round, &ipar);
978: aproc_setout(conv, ibuf);
979: }
1.57 ! ratchov 980: aproc_setin(d->mix, ibuf);
1.46 ratchov 981: ibuf->r.mix.xrun = xrun;
1.31 ratchov 982: ibuf->r.mix.maxweight = vol;
1.57 ! ratchov 983: mix_setmaster(d->mix);
1.1 ratchov 984: }
1.46 ratchov 985: if (mode & MODE_REC) {
1.12 ratchov 986: opar = *sopar;
1.57 ! ratchov 987: rbuf = LIST_FIRST(&d->sub->ins);
! 988: round = dev_roundof(d, opar.rate);
! 989: nblk = (d->bufsz / d->round + 3) / 4;
1.48 ratchov 990: nch = opar.cmax - opar.cmin + 1;
1.57 ! ratchov 991: if (!aparams_eqenc(&opar, &d->ipar)) {
1.10 ratchov 992: conv = enc_new(name, &opar);
1.57 ! ratchov 993: opar.bps = d->ipar.bps;
! 994: opar.bits = d->ipar.bits;
! 995: opar.sig = d->ipar.sig;
! 996: opar.le = d->ipar.le;
! 997: opar.msb = d->ipar.msb;
1.9 ratchov 998: aproc_setout(conv, obuf);
1.20 ratchov 999: obuf = abuf_new(nblk * round, &opar);
1.9 ratchov 1000: aproc_setin(conv, obuf);
1.8 ratchov 1001: }
1.48 ratchov 1002: if (onch > 0 && nch >= onch * 2) {
1003: conv = join_new(name);
1004: aproc_setout(conv, obuf);
1005: opar.cmax = opar.cmin + onch - 1;
1006: obuf = abuf_new(nblk * round, &opar);
1007: aproc_setin(conv, obuf);
1008: }
1.57 ! ratchov 1009: if (!aparams_eqrate(&opar, &d->ipar)) {
! 1010: conv = resamp_new(name, d->round, round);
! 1011: opar.rate = d->ipar.rate;
! 1012: round = d->round;
1.1 ratchov 1013: aproc_setout(conv, obuf);
1.20 ratchov 1014: obuf = abuf_new(nblk * round, &opar);
1.1 ratchov 1015: aproc_setin(conv, obuf);
1016: }
1.48 ratchov 1017: if (onch > 0 && nch * 2 <= onch) {
1018: conv = join_new(name);
1019: aproc_setout(conv, obuf);
1020: opar.cmax = opar.cmin + onch - 1;
1021: obuf = abuf_new(nblk * round, &opar);
1022: aproc_setin(conv, obuf);
1023: }
1.57 ! ratchov 1024: aproc_setout(d->sub, obuf);
1.46 ratchov 1025: obuf->w.sub.xrun = xrun;
1026: }
1027: if (mode & MODE_MON) {
1028: opar = *sopar;
1.57 ! ratchov 1029: rbuf = LIST_FIRST(&d->submon->ins);
! 1030: round = dev_roundof(d, opar.rate);
! 1031: nblk = (d->bufsz / d->round + 3) / 4;
1.48 ratchov 1032: nch = opar.cmax - opar.cmin + 1;
1.57 ! ratchov 1033: if (!aparams_eqenc(&opar, &d->opar)) {
1.46 ratchov 1034: conv = enc_new(name, &opar);
1.57 ! ratchov 1035: opar.bps = d->opar.bps;
! 1036: opar.bits = d->opar.bits;
! 1037: opar.sig = d->opar.sig;
! 1038: opar.le = d->opar.le;
! 1039: opar.msb = d->opar.msb;
1.46 ratchov 1040: aproc_setout(conv, obuf);
1041: obuf = abuf_new(nblk * round, &opar);
1042: aproc_setin(conv, obuf);
1043: }
1.48 ratchov 1044: if (onch > 0 && nch >= onch * 2) {
1045: conv = join_new(name);
1046: aproc_setout(conv, obuf);
1047: opar.cmax = opar.cmin + onch - 1;
1048: obuf = abuf_new(nblk * round, &opar);
1049: aproc_setin(conv, obuf);
1050: }
1.57 ! ratchov 1051: if (!aparams_eqrate(&opar, &d->opar)) {
! 1052: conv = resamp_new(name, d->round, round);
! 1053: opar.rate = d->opar.rate;
! 1054: round = d->round;
1.46 ratchov 1055: aproc_setout(conv, obuf);
1.48 ratchov 1056: obuf = abuf_new(nblk * round, &opar);
1057: aproc_setin(conv, obuf);
1058: }
1059: if (onch > 0 && nch * 2 <= onch) {
1060: conv = join_new(name);
1061: aproc_setout(conv, obuf);
1062: opar.cmax = opar.cmin + onch - 1;
1.46 ratchov 1063: obuf = abuf_new(nblk * round, &opar);
1064: aproc_setin(conv, obuf);
1065: }
1.57 ! ratchov 1066: aproc_setout(d->submon, obuf);
1.46 ratchov 1067: obuf->w.sub.xrun = xrun;
1.1 ratchov 1068: }
1069:
1070: /*
1.27 ratchov 1071: * Sync play to record.
1.1 ratchov 1072: */
1.46 ratchov 1073: if ((mode & MODE_PLAY) && (mode & MODE_RECMASK)) {
1.3 ratchov 1074: ibuf->duplex = obuf;
1075: obuf->duplex = ibuf;
1.13 ratchov 1076: }
1.57 ! ratchov 1077: dev_sync(d, mode, ibuf, obuf);
1.14 ratchov 1078: }
1079:
1080: /*
1.27 ratchov 1081: * Change the playback volume of the given stream.
1.14 ratchov 1082: */
1083: void
1.57 ! ratchov 1084: dev_setvol(struct dev *d, struct abuf *ibuf, int vol)
1.14 ratchov 1085: {
1.39 ratchov 1086: #ifdef DEBUG
1087: if (debug_level >= 3) {
1088: abuf_dbg(ibuf);
1089: dbg_puts(": setting volume to ");
1090: dbg_putu(vol);
1091: dbg_puts("\n");
1092: }
1093: #endif
1.57 ! ratchov 1094: if (!dev_getep(d, MODE_PLAY, &ibuf, NULL)) {
1.14 ratchov 1095: return;
1.16 ratchov 1096: }
1.31 ratchov 1097: ibuf->r.mix.vol = vol;
1.13 ratchov 1098: }
1099:
1100: /*
1.27 ratchov 1101: * Clear buffers of the play and record chains so that when the device
1102: * is started, playback and record start in sync.
1.13 ratchov 1103: */
1104: void
1.57 ! ratchov 1105: dev_clear(struct dev *d)
1.13 ratchov 1106: {
1107: struct abuf *buf;
1108:
1.57 ! ratchov 1109: if (APROC_OK(d->mix)) {
1.39 ratchov 1110: #ifdef DEBUG
1.57 ! ratchov 1111: if (!LIST_EMPTY(&d->mix->ins)) {
1.39 ratchov 1112: dbg_puts("play end not idle, can't clear device\n");
1113: dbg_panic();
1114: }
1115: #endif
1.57 ! ratchov 1116: buf = LIST_FIRST(&d->mix->outs);
1.13 ratchov 1117: while (buf) {
1118: abuf_clear(buf);
1.49 ratchov 1119: buf = LIST_FIRST(&buf->rproc->outs);
1.13 ratchov 1120: }
1.57 ! ratchov 1121: mix_clear(d->mix);
1.13 ratchov 1122: }
1.57 ! ratchov 1123: if (APROC_OK(d->sub)) {
1.39 ratchov 1124: #ifdef DEBUG
1.57 ! ratchov 1125: if (!LIST_EMPTY(&d->sub->outs)) {
1.39 ratchov 1126: dbg_puts("record end not idle, can't clear device\n");
1127: dbg_panic();
1128: }
1129: #endif
1.57 ! ratchov 1130: buf = LIST_FIRST(&d->sub->ins);
1.13 ratchov 1131: while (buf) {
1132: abuf_clear(buf);
1.49 ratchov 1133: buf = LIST_FIRST(&buf->wproc->ins);
1.13 ratchov 1134: }
1.57 ! ratchov 1135: sub_clear(d->sub);
1.40 ratchov 1136: }
1.57 ! ratchov 1137: if (APROC_OK(d->submon)) {
1.46 ratchov 1138: #ifdef DEBUG
1139: dbg_puts("clearing monitor\n");
1.57 ! ratchov 1140: if (!LIST_EMPTY(&d->submon->outs)) {
1.46 ratchov 1141: dbg_puts("monitoring end not idle, can't clear device\n");
1142: dbg_panic();
1143: }
1144: #endif
1.57 ! ratchov 1145: buf = LIST_FIRST(&d->submon->ins);
1.46 ratchov 1146: while (buf) {
1147: abuf_clear(buf);
1.49 ratchov 1148: buf = LIST_FIRST(&buf->wproc->ins);
1.46 ratchov 1149: }
1.57 ! ratchov 1150: sub_clear(d->submon);
! 1151: mon_clear(d->mon);
1.46 ratchov 1152: }
1.40 ratchov 1153: }
1154:
1155: /*
1156: * Fill with silence play buffers and schedule the same amount of recorded
1157: * samples to drop
1158: */
1159: void
1.57 ! ratchov 1160: dev_prime(struct dev *d)
1.40 ratchov 1161: {
1.51 ratchov 1162:
1163: #ifdef DEBUG
1164: if (debug_level >= 3)
1165: dbg_puts("priming device\n");
1166: #endif
1.57 ! ratchov 1167: if (APROC_OK(d->mix)) {
1.40 ratchov 1168: #ifdef DEBUG
1.57 ! ratchov 1169: if (!LIST_EMPTY(&d->mix->ins)) {
1.40 ratchov 1170: dbg_puts("play end not idle, can't prime device\n");
1171: dbg_panic();
1172: }
1173: #endif
1.57 ! ratchov 1174: mix_prime(d->mix);
1.1 ratchov 1175: }
1176: }