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