Annotation of src/usr.bin/aucat/dev.c, Revision 1.85
1.85 ! ratchov 1: /* $OpenBSD: dev.c,v 1.84 2013/11/18 17:37: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: */
1.1 ratchov 65: #include <stdio.h>
66: #include <stdlib.h>
1.71 ratchov 67: #include <string.h>
1.1 ratchov 68: #include <unistd.h>
69:
70: #include "abuf.h"
71: #include "aproc.h"
1.27 ratchov 72: #include "conf.h"
73: #include "dev.h"
1.3 ratchov 74: #include "pipe.h"
1.38 ratchov 75: #include "miofile.h"
1.42 ratchov 76: #include "siofile.h"
1.28 ratchov 77: #include "midi.h"
1.39 ratchov 78: #ifdef DEBUG
79: #include "dbg.h"
80: #endif
1.1 ratchov 81:
1.57 ratchov 82: int dev_open(struct dev *);
83: void dev_close(struct dev *);
84: void dev_start(struct dev *);
85: void dev_stop(struct dev *);
86: void dev_clear(struct dev *);
1.71 ratchov 87: void dev_onmove(void *, int);
1.66 ratchov 88: int devctl_open(struct dev *, struct devctl *);
1.84 ratchov 89: int dev_getep(struct dev *, unsigned int, struct abuf **, struct abuf **);
90: void dev_sync(struct dev *, unsigned int, struct abuf *, struct abuf *);
91: int dev_mkslot(struct dev *, char *);
92: int dev_try(struct dev *, int);
93:
1.57 ratchov 94:
95: struct dev *dev_list = NULL;
1.79 ratchov 96: unsigned int dev_sndnum = 0, dev_thrnum = 0;
1.68 ratchov 97:
98: #ifdef DEBUG
99: void
100: dev_dbg(struct dev *d)
101: {
102: if (d->num >= DEV_NMAX) {
103: dbg_puts("thr");
104: dbg_putu(d->num - DEV_NMAX);
105: } else {
106: dbg_puts("snd");
107: dbg_putu(d->num);
108: }
109: }
110: #endif
1.38 ratchov 111:
112: /*
1.51 ratchov 113: * Create a sndio device
1.28 ratchov 114: */
1.57 ratchov 115: struct dev *
1.79 ratchov 116: dev_new(char *path, unsigned int mode, unsigned int bufsz, unsigned int round,
117: unsigned int hold, unsigned int autovol)
1.57 ratchov 118: {
119: struct dev *d;
1.79 ratchov 120: unsigned int *pnum, i;
1.57 ratchov 121:
1.68 ratchov 122: pnum = (mode & MODE_THRU) ? &dev_thrnum : &dev_sndnum;
123: if (*pnum == DEV_NMAX) {
124: #ifdef DEBUG
125: if (debug_level >= 1)
126: dbg_puts("too many devices\n");
127: #endif
128: return NULL;
1.78 ratchov 129: }
130: d = malloc(sizeof(struct dev));
131: if (d == NULL) {
132: perror("malloc");
133: exit(1);
1.68 ratchov 134: }
135: d->num = (*pnum)++;
136: if (mode & MODE_THRU)
137: d->num += DEV_NMAX;
1.66 ratchov 138: d->ctl_list = NULL;
1.57 ratchov 139: d->path = path;
140: d->reqmode = mode;
1.67 ratchov 141: aparams_init(&d->reqopar, NCHAN_MAX, 0, 0);
142: aparams_init(&d->reqipar, NCHAN_MAX, 0, 0);
1.57 ratchov 143: d->reqbufsz = bufsz;
144: d->reqround = round;
145: d->hold = hold;
1.65 ratchov 146: d->autovol = autovol;
1.67 ratchov 147: d->autostart = 0;
1.72 ratchov 148: d->refcnt = 0;
1.57 ratchov 149: d->pstate = DEV_CLOSED;
1.71 ratchov 150: d->serial = 0;
151: for (i = 0; i < CTL_NSLOT; i++) {
152: d->slot[i].unit = i;
153: d->slot[i].ops = NULL;
154: d->slot[i].vol = MIDI_MAXCTL;
155: d->slot[i].tstate = CTL_OFF;
156: d->slot[i].serial = d->serial++;
157: d->slot[i].name[0] = '\0';
158: }
1.77 ratchov 159: d->master = MIDI_MAXCTL;
1.71 ratchov 160: d->origin = 0;
161: d->tstate = CTL_STOP;
1.57 ratchov 162: d->next = dev_list;
1.68 ratchov 163: dev_list = d;
1.57 ratchov 164: return d;
1.28 ratchov 165: }
1.24 ratchov 166:
167: /*
1.67 ratchov 168: * adjust device parameters and mode
1.24 ratchov 169: */
1.67 ratchov 170: void
1.79 ratchov 171: dev_adjpar(struct dev *d, unsigned int mode,
1.67 ratchov 172: struct aparams *ipar, struct aparams *opar)
1.24 ratchov 173: {
1.67 ratchov 174: d->reqmode |= (mode | MODE_MIDIMASK);
175: if (mode & MODE_REC)
176: aparams_grow(&d->reqipar, ipar);
177: if (mode & MODE_PLAY)
178: aparams_grow(&d->reqopar, opar);
1.24 ratchov 179: }
1.1 ratchov 180:
1.51 ratchov 181: /*
1.67 ratchov 182: * Initialize the device with the current parameters
1.51 ratchov 183: */
1.67 ratchov 184: int
185: dev_init(struct dev *d)
1.1 ratchov 186: {
1.67 ratchov 187: if ((d->reqmode & (MODE_AUDIOMASK | MODE_MIDIMASK)) == 0) {
188: #ifdef DEBUG
1.68 ratchov 189: dev_dbg(d);
1.67 ratchov 190: dbg_puts(": has no streams, skipped\n");
191: #endif
192: return 1;
193: }
194: if (d->hold && d->pstate == DEV_CLOSED && !dev_open(d)) {
195: dev_del(d);
196: return 0;
1.57 ratchov 197: }
1.67 ratchov 198: return 1;
1.1 ratchov 199: }
200:
201: /*
1.66 ratchov 202: * Add a MIDI port to the device
203: */
204: int
1.79 ratchov 205: devctl_add(struct dev *d, char *path, unsigned int mode)
1.66 ratchov 206: {
207: struct devctl *c;
208:
209: c = malloc(sizeof(struct devctl));
210: if (c == NULL) {
211: perror("malloc");
212: exit(1);
213: }
1.68 ratchov 214: c->path = path;
1.66 ratchov 215: c->mode = mode;
216: c->next = d->ctl_list;
217: d->ctl_list = c;
1.67 ratchov 218: if (d->pstate != DEV_CLOSED && !devctl_open(d, c))
219: return 0;
1.66 ratchov 220: return 1;
221: }
222:
223: /*
224: * Open a MIDI device and connect it to the thru box
225: */
226: int
227: devctl_open(struct dev *d, struct devctl *c)
228: {
229: struct file *f;
230: struct abuf *rbuf = NULL, *wbuf = NULL;
231: struct aproc *rproc, *wproc;
232:
233: f = (struct file *)miofile_new(&miofile_ops, c->path, c->mode);
234: if (f == NULL)
235: return 0;
236: if (c->mode & MODE_MIDIIN) {
237: rproc = rfile_new(f);
238: rbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
239: aproc_setout(rproc, rbuf);
240: }
241: if (c->mode & MODE_MIDIOUT) {
242: wproc = wfile_new(f);
243: wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
244: aproc_setin(wproc, wbuf);
245: }
246: dev_midiattach(d, rbuf, wbuf);
247: return 1;
248: }
249:
250: /*
1.51 ratchov 251: * Open the device with the dev_reqxxx capabilities. Setup a mixer, demuxer,
252: * monitor, midi control, and any necessary conversions.
1.1 ratchov 253: */
1.26 ratchov 254: int
1.57 ratchov 255: dev_open(struct dev *d)
1.1 ratchov 256: {
1.23 ratchov 257: struct file *f;
1.66 ratchov 258: struct devctl *c;
1.51 ratchov 259: struct aparams par;
1.1 ratchov 260: struct aproc *conv;
261: struct abuf *buf;
1.79 ratchov 262: unsigned int siomode, cmin, cmax, rate;
1.51 ratchov 263:
1.57 ratchov 264: d->mode = d->reqmode;
265: d->round = d->reqround;
266: d->bufsz = d->reqbufsz;
267: d->ipar = d->reqipar;
268: d->opar = d->reqopar;
269: d->rec = NULL;
270: d->play = NULL;
271: d->mon = NULL;
1.61 jakemsr 272: d->mix = NULL;
273: d->sub = NULL;
1.57 ratchov 274: d->submon = NULL;
1.61 jakemsr 275: d->midi = NULL;
1.57 ratchov 276: d->rate = 0;
1.36 ratchov 277:
1.67 ratchov 278: if (d->opar.cmin > d->opar.cmax) {
279: d->opar.cmin = 0;
280: d->opar.cmax = 1;
281: }
282: if (d->ipar.cmin > d->ipar.cmax) {
283: d->ipar.cmin = 0;
284: d->ipar.cmax = 1;
285: }
286: if (d->opar.rate > d->ipar.rate)
287: d->ipar.rate = d->opar.rate;
288: else
289: d->opar.rate = d->ipar.rate;
290: if (d->opar.rate == 0)
1.76 ratchov 291: d->opar.rate = d->ipar.rate = 48000; /* XXX */
1.67 ratchov 292:
293: if (d->mode & MODE_THRU)
294: d->mode &= ~MODE_AUDIOMASK;
295:
1.3 ratchov 296: /*
1.51 ratchov 297: * If needed, open the device (ie create dev_rec and dev_play)
1.3 ratchov 298: */
1.57 ratchov 299: if ((d->mode & (MODE_PLAY | MODE_REC)) && !(d->mode & MODE_LOOP)) {
300: siomode = d->mode & (MODE_PLAY | MODE_REC);
1.51 ratchov 301: f = (struct file *)siofile_new(&siofile_ops,
1.57 ratchov 302: d->path,
1.51 ratchov 303: &siomode,
1.57 ratchov 304: &d->ipar,
305: &d->opar,
306: &d->bufsz,
307: &d->round);
1.51 ratchov 308: if (f == NULL) {
1.39 ratchov 309: #ifdef DEBUG
1.51 ratchov 310: if (debug_level >= 1) {
1.68 ratchov 311: dev_dbg(d);
312: dbg_puts(": ");
1.62 ratchov 313: dbg_puts(d->path);
1.51 ratchov 314: dbg_puts(": failed to open audio device\n");
315: }
316: #endif
317: return 0;
1.39 ratchov 318: }
1.51 ratchov 319: if (!(siomode & MODE_PLAY))
1.57 ratchov 320: d->mode &= ~(MODE_PLAY | MODE_MON);
1.51 ratchov 321: if (!(siomode & MODE_REC))
1.57 ratchov 322: d->mode &= ~MODE_REC;
323: if ((d->mode & (MODE_PLAY | MODE_REC)) == 0) {
1.51 ratchov 324: #ifdef DEBUG
325: if (debug_level >= 1) {
1.68 ratchov 326: dev_dbg(d);
1.51 ratchov 327: dbg_puts(": mode not supported by device\n");
328: }
1.39 ratchov 329: #endif
1.51 ratchov 330: return 0;
331: }
1.57 ratchov 332: d->rate = d->mode & MODE_REC ? d->ipar.rate : d->opar.rate;
1.67 ratchov 333: if (d->mode & MODE_REC) {
334: d->rec = rsio_new(f);
335: d->rec->refs++;
336: }
337: if (d->mode & MODE_PLAY) {
338: d->play = wsio_new(f);
339: d->play->refs++;
340: }
341: }
342: if (d->mode & MODE_LOOP) {
343: if (d->mode & MODE_MON) {
1.39 ratchov 344: #ifdef DEBUG
1.67 ratchov 345: if (debug_level >= 1) {
346: dbg_puts("monitoring not allowed "
347: "in loopback mode\n");
1.51 ratchov 348: }
1.67 ratchov 349: #endif
350: return 0;
351: }
352: if ((d->mode & MODE_PLAYREC) != MODE_PLAYREC) {
353: #ifdef DEBUG
354: if (debug_level >= 1) {
355: dbg_puts("both play and record streams "
356: "required in loopback mode\n");
1.51 ratchov 357: }
1.67 ratchov 358: #endif
359: return 0;
1.39 ratchov 360: }
1.67 ratchov 361: if (d->ctl_list) {
362: #ifdef DEBUG
363: if (debug_level >= 1) {
364: dbg_puts("MIDI control not allowed "
365: "in loopback mode\n");
366: }
1.39 ratchov 367: #endif
1.67 ratchov 368: return 0;
369: }
370: cmin = (d->ipar.cmin < d->opar.cmin) ?
371: d->ipar.cmin : d->opar.cmin;
372: cmax = (d->ipar.cmax > d->opar.cmax) ?
373: d->ipar.cmax : d->opar.cmax;
374: rate = (d->ipar.rate > d->opar.rate) ?
375: d->ipar.rate : d->opar.rate;
376: aparams_init(&par, cmin, cmax, rate);
377: d->ipar = par;
378: d->opar = par;
379: d->rate = rate;
1.81 ratchov 380: /*
381: * block sizes in the resampling code are limited to
382: * 2^15, so use 1/15 of the rate, since all standard
383: * sample rates are multiple of 15
384: */
385: d->round = rate / 15;
1.67 ratchov 386: d->bufsz = 2 * d->round;
387: }
388: #ifdef DEBUG
389: if (debug_level >= 2) {
1.57 ratchov 390: if (d->mode & MODE_REC) {
1.68 ratchov 391: dev_dbg(d);
1.67 ratchov 392: dbg_puts(": recording ");
393: aparams_dbg(&d->ipar);
394: dbg_puts("\n");
1.57 ratchov 395: }
396: if (d->mode & MODE_PLAY) {
1.68 ratchov 397: dev_dbg(d);
1.67 ratchov 398: dbg_puts(": playing ");
399: aparams_dbg(&d->opar);
400: dbg_puts("\n");
1.51 ratchov 401: }
1.3 ratchov 402: }
1.67 ratchov 403: #endif
1.11 ratchov 404: /*
1.51 ratchov 405: * Create the midi control end, or a simple thru box
406: * if there's no device
407: */
1.64 ratchov 408: if (d->mode & MODE_MIDIMASK) {
1.73 ratchov 409: d->midi = midi_new("midi", (d->mode & MODE_THRU) ? NULL : d);
1.64 ratchov 410: d->midi->refs++;
411: }
1.51 ratchov 412:
413: /*
414: * Create mixer, demuxer and monitor
1.1 ratchov 415: */
1.57 ratchov 416: if (d->mode & MODE_PLAY) {
1.77 ratchov 417: d->mix = mix_new("play", d->bufsz, d->round,
418: d->autovol, MIDI_TO_ADATA(d->master));
1.57 ratchov 419: d->mix->refs++;
420: }
421: if (d->mode & MODE_REC) {
422: d->sub = sub_new("rec", d->bufsz, d->round);
423: d->sub->refs++;
1.51 ratchov 424: }
1.57 ratchov 425: if (d->mode & MODE_LOOP) {
1.51 ratchov 426: /*
427: * connect mixer out to demuxer in
428: */
1.57 ratchov 429: buf = abuf_new(d->bufsz, &d->opar);
430: aproc_setout(d->mix, buf);
431: aproc_setin(d->sub, buf);
432:
433: d->mix->flags |= APROC_QUIT;
434: d->sub->flags |= APROC_QUIT;
1.51 ratchov 435: }
1.57 ratchov 436: if (d->rec) {
437: aparams_init(&par, d->ipar.cmin, d->ipar.cmax, d->rate);
1.51 ratchov 438:
1.1 ratchov 439: /*
1.51 ratchov 440: * Create device <-> demuxer buffer
1.1 ratchov 441: */
1.57 ratchov 442: buf = abuf_new(d->bufsz, &d->ipar);
443: aproc_setout(d->rec, buf);
1.1 ratchov 444:
445: /*
1.51 ratchov 446: * Insert a converter, if needed.
1.1 ratchov 447: */
1.57 ratchov 448: if (!aparams_eqenc(&d->ipar, &par)) {
449: conv = dec_new("rec", &d->ipar);
1.1 ratchov 450: aproc_setin(conv, buf);
1.57 ratchov 451: buf = abuf_new(d->round, &par);
1.1 ratchov 452: aproc_setout(conv, buf);
453: }
1.57 ratchov 454: d->ipar = par;
455: aproc_setin(d->sub, buf);
1.1 ratchov 456: }
1.57 ratchov 457: if (d->play) {
458: aparams_init(&par, d->opar.cmin, d->opar.cmax, d->rate);
1.1 ratchov 459:
460: /*
1.51 ratchov 461: * Create device <-> mixer buffer
1.1 ratchov 462: */
1.57 ratchov 463: buf = abuf_new(d->bufsz, &d->opar);
464: aproc_setin(d->play, buf);
1.25 ratchov 465:
1.1 ratchov 466: /*
1.27 ratchov 467: * Append a converter, if needed.
1.1 ratchov 468: */
1.57 ratchov 469: if (!aparams_eqenc(&par, &d->opar)) {
470: conv = enc_new("play", &d->opar);
1.1 ratchov 471: aproc_setout(conv, buf);
1.57 ratchov 472: buf = abuf_new(d->round, &par);
1.1 ratchov 473: aproc_setin(conv, buf);
474: }
1.57 ratchov 475: d->opar = par;
476: aproc_setout(d->mix, buf);
1.1 ratchov 477: }
1.57 ratchov 478: if (d->mode & MODE_MON) {
479: d->mon = mon_new("mon", d->bufsz);
480: d->mon->refs++;
481: buf = abuf_new(d->bufsz, &d->opar);
482: aproc_setout(d->mon, buf);
1.46 ratchov 483:
484: /*
485: * Append a "sub" to which clients will connect.
486: */
1.57 ratchov 487: d->submon = sub_new("mon", d->bufsz, d->round);
488: d->submon->refs++;
489: aproc_setin(d->submon, buf);
1.46 ratchov 490:
491: /*
1.51 ratchov 492: * Attach to the mixer
1.46 ratchov 493: */
1.57 ratchov 494: d->mix->u.mix.mon = d->mon;
495: d->mon->refs++;
1.46 ratchov 496: }
1.39 ratchov 497: #ifdef DEBUG
1.51 ratchov 498: if (debug_level >= 2) {
1.57 ratchov 499: if (d->mode & (MODE_PLAY | MODE_RECMASK)) {
1.68 ratchov 500: dev_dbg(d);
1.62 ratchov 501: dbg_puts(": block size is ");
1.57 ratchov 502: dbg_putu(d->round);
1.51 ratchov 503: dbg_puts(" frames, using ");
1.57 ratchov 504: dbg_putu(d->bufsz / d->round);
1.51 ratchov 505: dbg_puts(" blocks\n");
506: }
1.39 ratchov 507: }
508: #endif
1.57 ratchov 509: d->pstate = DEV_INIT;
1.66 ratchov 510: for (c = d->ctl_list; c != NULL; c = c->next) {
511: if (!devctl_open(d, c)) {
512: #ifdef DEBUG
513: if (debug_level >= 1) {
514: dbg_puts(c->path);
515: dbg_puts(": couldn't open MIDI port\n");
516: }
517: #endif
518: dev_close(d);
519: return 0;
520: }
521: }
1.26 ratchov 522: return 1;
1.1 ratchov 523: }
524:
525: /*
1.27 ratchov 526: * Cleanly stop and drain everything and close the device
527: * once both play chain and record chain are gone.
1.1 ratchov 528: */
529: void
1.57 ratchov 530: dev_close(struct dev *d)
1.1 ratchov 531: {
532: struct file *f;
533:
1.50 ratchov 534: /*
535: * if the device is starting, ensure it actually starts
536: * so buffers are drained, else clear any buffers
537: */
1.57 ratchov 538: switch (d->pstate) {
1.50 ratchov 539: case DEV_START:
540: #ifdef DEBUG
1.69 ratchov 541: if (debug_level >= 3) {
542: dev_dbg(d);
543: dbg_puts(": draining device\n");
544: }
1.50 ratchov 545: #endif
1.57 ratchov 546: dev_start(d);
1.50 ratchov 547: break;
548: case DEV_INIT:
549: #ifdef DEBUG
1.69 ratchov 550: if (debug_level >= 3) {
551: dev_dbg(d);
552: dbg_puts(": flushing device\n");
553: }
1.50 ratchov 554: #endif
1.57 ratchov 555: dev_clear(d);
1.50 ratchov 556: break;
557: }
1.39 ratchov 558: #ifdef DEBUG
1.69 ratchov 559: if (debug_level >= 2) {
560: dev_dbg(d);
561: dbg_puts(": closing device\n");
562: }
1.39 ratchov 563: #endif
1.70 ratchov 564: d->pstate = DEV_CLOSED;
1.57 ratchov 565: if (d->mix) {
1.3 ratchov 566: /*
1.32 ratchov 567: * Put the mixer in ``autoquit'' state and generate
568: * EOF on all inputs connected it. Once buffers are
569: * drained the mixer will terminate and shutdown the
570: * device.
1.3 ratchov 571: *
572: * NOTE: since file_eof() can destroy the file and
573: * reorder the file_list, we have to restart the loop
1.27 ratchov 574: * after each call to file_eof().
1.3 ratchov 575: */
1.57 ratchov 576: if (APROC_OK(d->mix))
577: mix_quit(d->mix);
1.51 ratchov 578:
579: /*
580: * XXX: handle this in mix_done()
581: */
1.57 ratchov 582: if (APROC_OK(d->mix->u.mix.mon)) {
583: d->mix->u.mix.mon->refs--;
584: aproc_del(d->mix->u.mix.mon);
585: d->mix->u.mix.mon = NULL;
1.46 ratchov 586: }
1.32 ratchov 587: restart_mix:
1.3 ratchov 588: LIST_FOREACH(f, &file_list, entry) {
1.32 ratchov 589: if (f->rproc != NULL &&
1.57 ratchov 590: aproc_depend(d->mix, f->rproc)) {
1.3 ratchov 591: file_eof(f);
1.32 ratchov 592: goto restart_mix;
1.3 ratchov 593: }
594: }
1.59 ratchov 595: } else if (d->sub) {
1.3 ratchov 596: /*
1.32 ratchov 597: * Same as above, but since there's no mixer,
598: * we generate EOF on the record-end of the
599: * device.
600: */
601: restart_sub:
602: LIST_FOREACH(f, &file_list, entry) {
603: if (f->rproc != NULL &&
1.59 ratchov 604: aproc_depend(d->sub, f->rproc)) {
1.32 ratchov 605: file_eof(f);
606: goto restart_sub;
1.59 ratchov 607: }
608: }
609: } else if (d->submon) {
610: /*
611: * Same as above
612: */
613: restart_submon:
614: LIST_FOREACH(f, &file_list, entry) {
615: if (f->rproc != NULL &&
616: aproc_depend(d->submon, f->rproc)) {
617: file_eof(f);
618: goto restart_submon;
1.23 ratchov 619: }
1.32 ratchov 620: }
621: }
1.57 ratchov 622: if (d->midi) {
623: d->midi->flags |= APROC_QUIT;
624: if (LIST_EMPTY(&d->midi->ins))
625: aproc_del(d->midi);
1.36 ratchov 626: restart_midi:
627: LIST_FOREACH(f, &file_list, entry) {
628: if (f->rproc &&
1.57 ratchov 629: aproc_depend(d->midi, f->rproc)) {
1.36 ratchov 630: file_eof(f);
631: goto restart_midi;
632: }
633: }
634: }
1.57 ratchov 635: if (d->mix) {
636: if (--d->mix->refs == 0 && (d->mix->flags & APROC_ZOMB))
637: aproc_del(d->mix);
638: d->mix = NULL;
639: }
640: if (d->play) {
641: if (--d->play->refs == 0 && (d->play->flags & APROC_ZOMB))
642: aproc_del(d->play);
643: d->play = NULL;
644: }
645: if (d->sub) {
646: if (--d->sub->refs == 0 && (d->sub->flags & APROC_ZOMB))
647: aproc_del(d->sub);
648: d->sub = NULL;
649: }
650: if (d->rec) {
651: if (--d->rec->refs == 0 && (d->rec->flags & APROC_ZOMB))
652: aproc_del(d->rec);
653: d->rec = NULL;
654: }
655: if (d->submon) {
656: if (--d->submon->refs == 0 && (d->submon->flags & APROC_ZOMB))
657: aproc_del(d->submon);
658: d->submon = NULL;
659: }
660: if (d->mon) {
661: if (--d->mon->refs == 0 && (d->mon->flags & APROC_ZOMB))
662: aproc_del(d->mon);
663: d->mon = NULL;
664: }
665: if (d->midi) {
666: if (--d->midi->refs == 0 && (d->midi->flags & APROC_ZOMB))
667: aproc_del(d->midi);
668: d->midi = NULL;
1.32 ratchov 669: }
1.51 ratchov 670: }
671:
672: /*
1.60 ratchov 673: * Unless the device is already in process of closing, request it to close
674: */
675: void
676: dev_drain(struct dev *d)
677: {
1.79 ratchov 678: unsigned int i;
1.71 ratchov 679: struct ctl_slot *s;
680:
681: for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
682: if (s->ops)
683: s->ops->quit(s->arg);
684: }
1.60 ratchov 685: if (d->pstate != DEV_CLOSED)
686: dev_close(d);
687: }
688:
689: /*
1.51 ratchov 690: * Free the device
691: */
692: void
1.57 ratchov 693: dev_del(struct dev *d)
1.51 ratchov 694: {
1.57 ratchov 695: struct dev **p;
696:
1.60 ratchov 697: dev_drain(d);
1.57 ratchov 698: for (p = &dev_list; *p != d; p = &(*p)->next) {
699: #ifdef DEBUG
700: if (*p == NULL) {
701: dbg_puts("device to delete not on the list\n");
702: dbg_panic();
703: }
704: #endif
705: }
706: *p = d->next;
707: free(d);
1.51 ratchov 708: }
709:
710: /*
711: * Attach a bi-directional MIDI stream to the MIDI device
712: */
713: void
1.57 ratchov 714: dev_midiattach(struct dev *d, struct abuf *ibuf, struct abuf *obuf)
1.51 ratchov 715: {
716: if (ibuf)
1.57 ratchov 717: aproc_setin(d->midi, ibuf);
1.51 ratchov 718: if (obuf) {
1.57 ratchov 719: aproc_setout(d->midi, obuf);
1.51 ratchov 720: if (ibuf) {
721: ibuf->duplex = obuf;
722: obuf->duplex = ibuf;
723: }
1.1 ratchov 724: }
725: }
726:
1.79 ratchov 727: unsigned int
728: dev_roundof(struct dev *d, unsigned int newrate)
1.51 ratchov 729: {
1.57 ratchov 730: return (d->round * newrate + d->rate / 2) / d->rate;
1.51 ratchov 731: }
732:
1.1 ratchov 733: /*
1.27 ratchov 734: * Start the (paused) device. By default it's paused.
1.1 ratchov 735: */
736: void
1.57 ratchov 737: dev_start(struct dev *d)
1.1 ratchov 738: {
1.22 ratchov 739: struct file *f;
740:
1.46 ratchov 741: #ifdef DEBUG
742: if (debug_level >= 2)
1.51 ratchov 743: dbg_puts("starting device\n");
1.46 ratchov 744: #endif
1.57 ratchov 745: d->pstate = DEV_RUN;
746: if (d->mode & MODE_LOOP)
1.52 ratchov 747: return;
1.57 ratchov 748: if (APROC_OK(d->mix))
749: d->mix->flags |= APROC_DROP;
750: if (APROC_OK(d->sub))
751: d->sub->flags |= APROC_DROP;
752: if (APROC_OK(d->submon))
753: d->submon->flags |= APROC_DROP;
754: if (APROC_OK(d->play) && d->play->u.io.file) {
755: f = d->play->u.io.file;
1.71 ratchov 756: f->ops->start(f, dev_onmove, d);
1.57 ratchov 757: } else if (APROC_OK(d->rec) && d->rec->u.io.file) {
758: f = d->rec->u.io.file;
1.71 ratchov 759: f->ops->start(f, dev_onmove, d);
1.22 ratchov 760: }
1.1 ratchov 761: }
762:
763: /*
1.46 ratchov 764: * Pause the device. This may trigger context switches,
765: * so it shouldn't be called from aproc methods
1.1 ratchov 766: */
767: void
1.57 ratchov 768: dev_stop(struct dev *d)
1.1 ratchov 769: {
1.22 ratchov 770: struct file *f;
771:
1.52 ratchov 772: #ifdef DEBUG
1.69 ratchov 773: if (debug_level >= 2) {
774: dev_dbg(d);
775: dbg_puts(": device stopped\n");
776: }
1.52 ratchov 777: #endif
1.57 ratchov 778: d->pstate = DEV_INIT;
779: if (d->mode & MODE_LOOP)
1.52 ratchov 780: return;
1.57 ratchov 781: if (APROC_OK(d->play) && d->play->u.io.file) {
782: f = d->play->u.io.file;
1.22 ratchov 783: f->ops->stop(f);
1.57 ratchov 784: } else if (APROC_OK(d->rec) && d->rec->u.io.file) {
785: f = d->rec->u.io.file;
1.22 ratchov 786: f->ops->stop(f);
787: }
1.57 ratchov 788: if (APROC_OK(d->mix))
789: d->mix->flags &= ~APROC_DROP;
790: if (APROC_OK(d->sub))
791: d->sub->flags &= ~APROC_DROP;
792: if (APROC_OK(d->submon))
793: d->submon->flags &= ~APROC_DROP;
1.51 ratchov 794: }
795:
796: int
1.57 ratchov 797: dev_ref(struct dev *d)
1.51 ratchov 798: {
799: #ifdef DEBUG
1.69 ratchov 800: if (debug_level >= 3) {
801: dev_dbg(d);
802: dbg_puts(": device requested\n");
803: }
1.51 ratchov 804: #endif
1.57 ratchov 805: if (d->pstate == DEV_CLOSED && !dev_open(d)) {
806: if (d->hold)
807: dev_del(d);
1.51 ratchov 808: return 0;
1.57 ratchov 809: }
810: d->refcnt++;
1.51 ratchov 811: return 1;
812: }
813:
814: void
1.57 ratchov 815: dev_unref(struct dev *d)
1.51 ratchov 816: {
817: #ifdef DEBUG
1.69 ratchov 818: if (debug_level >= 3) {
819: dev_dbg(d);
820: dbg_puts(": device released\n");
821: }
1.51 ratchov 822: #endif
1.57 ratchov 823: d->refcnt--;
824: if (d->refcnt == 0 && d->pstate == DEV_INIT && !d->hold)
825: dev_close(d);
1.51 ratchov 826: }
827:
828: /*
829: * There are actions (like start/stop/close ... ) that may trigger aproc
830: * operations, a thus cannot be started from aproc context.
831: * To avoid problems, aprocs only change the s!tate of the device,
832: * and actual operations are triggered from the main loop,
833: * outside the aproc code path.
834: *
835: * The following routine invokes pending actions, returns 0
836: * on fatal error
837: */
838: int
1.57 ratchov 839: dev_run(struct dev *d)
1.51 ratchov 840: {
1.57 ratchov 841: if (d->pstate == DEV_CLOSED)
1.51 ratchov 842: return 1;
843: /*
844: * check if device isn't gone
845: */
1.57 ratchov 846: if (((d->mode & MODE_PLAY) && !APROC_OK(d->mix)) ||
847: ((d->mode & MODE_REC) && !APROC_OK(d->sub)) ||
848: ((d->mode & MODE_MON) && !APROC_OK(d->submon))) {
1.51 ratchov 849: #ifdef DEBUG
1.74 ratchov 850: if (debug_level >= 2) {
1.69 ratchov 851: dev_dbg(d);
852: dbg_puts(": device disappeared\n");
853: }
1.51 ratchov 854: #endif
1.57 ratchov 855: if (d->hold) {
856: dev_del(d);
857: return 0;
858: }
859: dev_close(d);
860: return 1;
1.51 ratchov 861: }
1.57 ratchov 862: switch (d->pstate) {
1.51 ratchov 863: case DEV_INIT:
864: /* nothing */
865: break;
866: case DEV_START:
1.57 ratchov 867: dev_start(d);
1.51 ratchov 868: /* PASSTHROUGH */
869: case DEV_RUN:
870: /*
871: * if the device is not used, then stop it
872: */
1.57 ratchov 873: if ((!APROC_OK(d->mix) ||
874: d->mix->u.mix.idle > 2 * d->bufsz) &&
875: (!APROC_OK(d->sub) ||
876: d->sub->u.sub.idle > 2 * d->bufsz) &&
877: (!APROC_OK(d->submon) ||
878: d->submon->u.sub.idle > 2 * d->bufsz) &&
879: (!APROC_OK(d->midi) ||
1.71 ratchov 880: d->tstate != CTL_RUN)) {
1.51 ratchov 881: #ifdef DEBUG
1.69 ratchov 882: if (debug_level >= 3) {
883: dev_dbg(d);
884: dbg_puts(": device idle, suspending\n");
885: }
1.46 ratchov 886: #endif
1.57 ratchov 887: dev_stop(d);
888: if (d->refcnt == 0 && !d->hold)
889: dev_close(d);
1.58 ratchov 890: else
1.57 ratchov 891: dev_clear(d);
1.51 ratchov 892: }
893: break;
894: }
895: return 1;
896: }
897:
898: /*
1.58 ratchov 899: * If the device is paused, then resume it.
1.51 ratchov 900: * This routine can be called from aproc context.
901: */
902: void
1.57 ratchov 903: dev_wakeup(struct dev *d)
1.51 ratchov 904: {
1.57 ratchov 905: if (d->pstate == DEV_INIT)
906: d->pstate = DEV_START;
1.1 ratchov 907: }
908:
909: /*
1.27 ratchov 910: * Find the end points connected to the mix/sub.
1.14 ratchov 911: */
912: int
1.57 ratchov 913: dev_getep(struct dev *d,
1.79 ratchov 914: unsigned int mode, struct abuf **sibuf, struct abuf **sobuf)
1.14 ratchov 915: {
916: struct abuf *ibuf, *obuf;
917:
1.46 ratchov 918: if (mode & MODE_PLAY) {
1.57 ratchov 919: if (!APROC_OK(d->mix))
1.46 ratchov 920: return 0;
1.14 ratchov 921: ibuf = *sibuf;
922: for (;;) {
923: if (!ibuf || !ibuf->rproc) {
1.39 ratchov 924: #ifdef DEBUG
925: if (debug_level >= 3) {
926: abuf_dbg(*sibuf);
927: dbg_puts(": not connected to device\n");
928: }
929: #endif
1.14 ratchov 930: return 0;
931: }
1.57 ratchov 932: if (ibuf->rproc == d->mix)
1.14 ratchov 933: break;
1.49 ratchov 934: ibuf = LIST_FIRST(&ibuf->rproc->outs);
1.14 ratchov 935: }
1.21 ratchov 936: *sibuf = ibuf;
1.14 ratchov 937: }
1.46 ratchov 938: if (mode & MODE_REC) {
1.57 ratchov 939: if (!APROC_OK(d->sub))
1.46 ratchov 940: return 0;
1.14 ratchov 941: obuf = *sobuf;
942: for (;;) {
943: if (!obuf || !obuf->wproc) {
1.39 ratchov 944: #ifdef DEBUG
945: if (debug_level >= 3) {
946: abuf_dbg(*sobuf);
947: dbg_puts(": not connected to device\n");
948: }
949: #endif
1.14 ratchov 950: return 0;
951: }
1.57 ratchov 952: if (obuf->wproc == d->sub)
1.14 ratchov 953: break;
1.49 ratchov 954: obuf = LIST_FIRST(&obuf->wproc->ins);
1.14 ratchov 955: }
1.21 ratchov 956: *sobuf = obuf;
1.14 ratchov 957: }
1.46 ratchov 958: if (mode & MODE_MON) {
1.57 ratchov 959: if (!APROC_OK(d->submon))
1.46 ratchov 960: return 0;
961: obuf = *sobuf;
962: for (;;) {
963: if (!obuf || !obuf->wproc) {
964: #ifdef DEBUG
965: if (debug_level >= 3) {
966: abuf_dbg(*sobuf);
967: dbg_puts(": not connected to device\n");
968: }
969: #endif
970: return 0;
971: }
1.57 ratchov 972: if (obuf->wproc == d->submon)
1.46 ratchov 973: break;
1.49 ratchov 974: obuf = LIST_FIRST(&obuf->wproc->ins);
1.46 ratchov 975: }
976: *sobuf = obuf;
977: }
1.14 ratchov 978: return 1;
979: }
980:
981: /*
1.27 ratchov 982: * Sync play buffer to rec buffer (for instance when one of
983: * them underruns/overruns).
1.1 ratchov 984: */
985: void
1.79 ratchov 986: dev_sync(struct dev *d, unsigned int mode,
987: struct abuf *ibuf, struct abuf *obuf)
1.1 ratchov 988: {
1.53 ratchov 989: int delta, offs;
1.57 ratchov 990: struct abuf *mbuf = NULL;
1.3 ratchov 991:
1.57 ratchov 992: if (!dev_getep(d, mode, &ibuf, &obuf))
1.3 ratchov 993: return;
994: /*
1.27 ratchov 995: * Calculate delta, the number of frames the play chain is ahead
1.3 ratchov 996: * of the record chain. It's necessary to schedule silences (or
997: * drops) in order to start playback and record in sync.
998: */
1.53 ratchov 999: offs = 0;
1000: delta = 0;
1.57 ratchov 1001: if (APROC_OK(d->mix)) {
1002: mbuf = LIST_FIRST(&d->mix->outs);
1.53 ratchov 1003: offs += mbuf->w.mix.todo;
1.57 ratchov 1004: delta += d->mix->u.mix.lat;
1.53 ratchov 1005: }
1.57 ratchov 1006: if (APROC_OK(d->sub))
1007: delta += d->sub->u.sub.lat;
1.39 ratchov 1008: #ifdef DEBUG
1009: if (debug_level >= 3) {
1.69 ratchov 1010: dev_dbg(d);
1011: dbg_puts(": syncing device");
1.57 ratchov 1012: if (APROC_OK(d->mix)) {
1.51 ratchov 1013: dbg_puts(", ");
1.57 ratchov 1014: aproc_dbg(d->mix);
1.53 ratchov 1015: dbg_puts(": todo = ");
1016: dbg_putu(mbuf->w.mix.todo);
1017: dbg_puts(": lat = ");
1.57 ratchov 1018: dbg_putu(d->mix->u.mix.lat);
1.46 ratchov 1019: }
1.57 ratchov 1020: if (APROC_OK(d->sub)) {
1.51 ratchov 1021: dbg_puts(", ");
1.57 ratchov 1022: aproc_dbg(d->sub);
1.53 ratchov 1023: dbg_puts(": lat = ");
1.57 ratchov 1024: dbg_putu(d->sub->u.sub.lat);
1.46 ratchov 1025: }
1.39 ratchov 1026: dbg_puts("\n");
1027: }
1028: #endif
1.53 ratchov 1029: if (mode & MODE_PLAY)
1030: mix_drop(ibuf, -offs);
1031: if (mode & MODE_RECMASK)
1032: sub_silence(obuf, -(offs + delta));
1.36 ratchov 1033: }
1034:
1035: /*
1036: * return the current latency (in frames), ie the latency that
1037: * a stream would have if dev_attach() is called on it.
1.71 ratchov 1038: *
1.79 ratchov 1039: * XXX: return a "unsigned int", since result is always positive, isn't it?
1.36 ratchov 1040: */
1041: int
1.57 ratchov 1042: dev_getpos(struct dev *d)
1.36 ratchov 1043: {
1.53 ratchov 1044: struct abuf *mbuf = NULL;
1.36 ratchov 1045:
1.57 ratchov 1046: if (APROC_OK(d->mix)) {
1047: mbuf = LIST_FIRST(&d->mix->outs);
1048: return -(mbuf->w.mix.todo + d->mix->u.mix.lat);
1.54 ratchov 1049: } else
1050: return 0;
1.1 ratchov 1051: }
1052:
1053: /*
1.27 ratchov 1054: * Attach the given input and output buffers to the mixer and the
1.1 ratchov 1055: * multiplexer respectively. The operation is done synchronously, so
1056: * both buffers enter in sync. If buffers do not match play
1.27 ratchov 1057: * and rec.
1.1 ratchov 1058: */
1059: void
1.79 ratchov 1060: dev_attach(struct dev *d, char *name, unsigned int mode,
1061: struct abuf *ibuf, struct aparams *sipar, unsigned int inch,
1062: struct abuf *obuf, struct aparams *sopar, unsigned int onch,
1063: unsigned int xrun, int vol)
1.1 ratchov 1064: {
1.12 ratchov 1065: struct aparams ipar, opar;
1.1 ratchov 1066: struct aproc *conv;
1.79 ratchov 1067: unsigned int round, nblk, nch;
1.20 ratchov 1068:
1.46 ratchov 1069: #ifdef DEBUG
1.57 ratchov 1070: if ((!APROC_OK(d->mix) && (mode & MODE_PLAY)) ||
1071: (!APROC_OK(d->sub) && (mode & MODE_REC)) ||
1072: (!APROC_OK(d->submon) && (mode & MODE_MON))) {
1.69 ratchov 1073: dev_dbg(d);
1074: dbg_puts(": mode beyond device mode, not attaching\n");
1.46 ratchov 1075: return;
1076: }
1077: #endif
1078: if (mode & MODE_PLAY) {
1.12 ratchov 1079: ipar = *sipar;
1.57 ratchov 1080: nblk = (d->bufsz / d->round + 3) / 4;
1081: round = dev_roundof(d, ipar.rate);
1.48 ratchov 1082: nch = ipar.cmax - ipar.cmin + 1;
1.57 ratchov 1083: if (!aparams_eqenc(&ipar, &d->opar)) {
1.10 ratchov 1084: conv = dec_new(name, &ipar);
1.57 ratchov 1085: ipar.bps = d->opar.bps;
1086: ipar.bits = d->opar.bits;
1087: ipar.sig = d->opar.sig;
1088: ipar.le = d->opar.le;
1089: ipar.msb = d->opar.msb;
1.25 ratchov 1090: aproc_setin(conv, ibuf);
1.20 ratchov 1091: ibuf = abuf_new(nblk * round, &ipar);
1.9 ratchov 1092: aproc_setout(conv, ibuf);
1.8 ratchov 1093: }
1.48 ratchov 1094: if (inch > 0 && nch >= inch * 2) {
1095: conv = join_new(name);
1096: aproc_setin(conv, ibuf);
1097: ipar.cmax = ipar.cmin + inch - 1;
1098: ibuf = abuf_new(nblk * round, &ipar);
1099: aproc_setout(conv, ibuf);
1100: }
1.57 ratchov 1101: if (!aparams_eqrate(&ipar, &d->opar)) {
1102: conv = resamp_new(name, round, d->round);
1103: ipar.rate = d->opar.rate;
1104: round = d->round;
1.5 ratchov 1105: aproc_setin(conv, ibuf);
1.20 ratchov 1106: ibuf = abuf_new(nblk * round, &ipar);
1.5 ratchov 1107: aproc_setout(conv, ibuf);
1.1 ratchov 1108: }
1.48 ratchov 1109: if (inch > 0 && nch * 2 <= inch) {
1110: conv = join_new(name);
1111: aproc_setin(conv, ibuf);
1112: ipar.cmax = ipar.cmin + inch - 1;
1113: ibuf = abuf_new(nblk * round, &ipar);
1114: aproc_setout(conv, ibuf);
1115: }
1.57 ratchov 1116: aproc_setin(d->mix, ibuf);
1.46 ratchov 1117: ibuf->r.mix.xrun = xrun;
1.31 ratchov 1118: ibuf->r.mix.maxweight = vol;
1.57 ratchov 1119: mix_setmaster(d->mix);
1.1 ratchov 1120: }
1.46 ratchov 1121: if (mode & MODE_REC) {
1.12 ratchov 1122: opar = *sopar;
1.57 ratchov 1123: round = dev_roundof(d, opar.rate);
1124: nblk = (d->bufsz / d->round + 3) / 4;
1.48 ratchov 1125: nch = opar.cmax - opar.cmin + 1;
1.57 ratchov 1126: if (!aparams_eqenc(&opar, &d->ipar)) {
1.10 ratchov 1127: conv = enc_new(name, &opar);
1.57 ratchov 1128: opar.bps = d->ipar.bps;
1129: opar.bits = d->ipar.bits;
1130: opar.sig = d->ipar.sig;
1131: opar.le = d->ipar.le;
1132: opar.msb = d->ipar.msb;
1.9 ratchov 1133: aproc_setout(conv, obuf);
1.20 ratchov 1134: obuf = abuf_new(nblk * round, &opar);
1.9 ratchov 1135: aproc_setin(conv, obuf);
1.8 ratchov 1136: }
1.48 ratchov 1137: if (onch > 0 && nch >= onch * 2) {
1138: conv = join_new(name);
1139: aproc_setout(conv, obuf);
1140: opar.cmax = opar.cmin + onch - 1;
1141: obuf = abuf_new(nblk * round, &opar);
1142: aproc_setin(conv, obuf);
1143: }
1.57 ratchov 1144: if (!aparams_eqrate(&opar, &d->ipar)) {
1145: conv = resamp_new(name, d->round, round);
1146: opar.rate = d->ipar.rate;
1147: round = d->round;
1.1 ratchov 1148: aproc_setout(conv, obuf);
1.20 ratchov 1149: obuf = abuf_new(nblk * round, &opar);
1.1 ratchov 1150: aproc_setin(conv, obuf);
1151: }
1.48 ratchov 1152: if (onch > 0 && nch * 2 <= onch) {
1153: conv = join_new(name);
1154: aproc_setout(conv, obuf);
1155: opar.cmax = opar.cmin + onch - 1;
1156: obuf = abuf_new(nblk * round, &opar);
1157: aproc_setin(conv, obuf);
1158: }
1.57 ratchov 1159: aproc_setout(d->sub, obuf);
1.46 ratchov 1160: obuf->w.sub.xrun = xrun;
1161: }
1162: if (mode & MODE_MON) {
1163: opar = *sopar;
1.57 ratchov 1164: round = dev_roundof(d, opar.rate);
1165: nblk = (d->bufsz / d->round + 3) / 4;
1.48 ratchov 1166: nch = opar.cmax - opar.cmin + 1;
1.57 ratchov 1167: if (!aparams_eqenc(&opar, &d->opar)) {
1.46 ratchov 1168: conv = enc_new(name, &opar);
1.57 ratchov 1169: opar.bps = d->opar.bps;
1170: opar.bits = d->opar.bits;
1171: opar.sig = d->opar.sig;
1172: opar.le = d->opar.le;
1173: opar.msb = d->opar.msb;
1.46 ratchov 1174: aproc_setout(conv, obuf);
1175: obuf = abuf_new(nblk * round, &opar);
1176: aproc_setin(conv, obuf);
1177: }
1.48 ratchov 1178: if (onch > 0 && nch >= onch * 2) {
1179: conv = join_new(name);
1180: aproc_setout(conv, obuf);
1181: opar.cmax = opar.cmin + onch - 1;
1182: obuf = abuf_new(nblk * round, &opar);
1183: aproc_setin(conv, obuf);
1184: }
1.57 ratchov 1185: if (!aparams_eqrate(&opar, &d->opar)) {
1186: conv = resamp_new(name, d->round, round);
1187: opar.rate = d->opar.rate;
1188: round = d->round;
1.46 ratchov 1189: aproc_setout(conv, obuf);
1.48 ratchov 1190: obuf = abuf_new(nblk * round, &opar);
1191: aproc_setin(conv, obuf);
1192: }
1193: if (onch > 0 && nch * 2 <= onch) {
1194: conv = join_new(name);
1195: aproc_setout(conv, obuf);
1196: opar.cmax = opar.cmin + onch - 1;
1.46 ratchov 1197: obuf = abuf_new(nblk * round, &opar);
1198: aproc_setin(conv, obuf);
1199: }
1.57 ratchov 1200: aproc_setout(d->submon, obuf);
1.46 ratchov 1201: obuf->w.sub.xrun = xrun;
1.1 ratchov 1202: }
1203:
1204: /*
1.27 ratchov 1205: * Sync play to record.
1.1 ratchov 1206: */
1.46 ratchov 1207: if ((mode & MODE_PLAY) && (mode & MODE_RECMASK)) {
1.3 ratchov 1208: ibuf->duplex = obuf;
1209: obuf->duplex = ibuf;
1.13 ratchov 1210: }
1.57 ratchov 1211: dev_sync(d, mode, ibuf, obuf);
1.14 ratchov 1212: }
1213:
1214: /*
1.27 ratchov 1215: * Change the playback volume of the given stream.
1.14 ratchov 1216: */
1217: void
1.57 ratchov 1218: dev_setvol(struct dev *d, struct abuf *ibuf, int vol)
1.14 ratchov 1219: {
1.39 ratchov 1220: #ifdef DEBUG
1221: if (debug_level >= 3) {
1222: abuf_dbg(ibuf);
1223: dbg_puts(": setting volume to ");
1224: dbg_putu(vol);
1225: dbg_puts("\n");
1226: }
1227: #endif
1.57 ratchov 1228: if (!dev_getep(d, MODE_PLAY, &ibuf, NULL)) {
1.14 ratchov 1229: return;
1.16 ratchov 1230: }
1.31 ratchov 1231: ibuf->r.mix.vol = vol;
1.13 ratchov 1232: }
1233:
1234: /*
1.27 ratchov 1235: * Clear buffers of the play and record chains so that when the device
1236: * is started, playback and record start in sync.
1.13 ratchov 1237: */
1238: void
1.57 ratchov 1239: dev_clear(struct dev *d)
1.13 ratchov 1240: {
1241: struct abuf *buf;
1242:
1.57 ratchov 1243: if (APROC_OK(d->mix)) {
1.39 ratchov 1244: #ifdef DEBUG
1.57 ratchov 1245: if (!LIST_EMPTY(&d->mix->ins)) {
1.69 ratchov 1246: dev_dbg(d);
1247: dbg_puts(": play end not idle, can't clear device\n");
1.39 ratchov 1248: dbg_panic();
1249: }
1250: #endif
1.57 ratchov 1251: buf = LIST_FIRST(&d->mix->outs);
1.13 ratchov 1252: while (buf) {
1253: abuf_clear(buf);
1.49 ratchov 1254: buf = LIST_FIRST(&buf->rproc->outs);
1.13 ratchov 1255: }
1.57 ratchov 1256: mix_clear(d->mix);
1.13 ratchov 1257: }
1.57 ratchov 1258: if (APROC_OK(d->sub)) {
1.39 ratchov 1259: #ifdef DEBUG
1.57 ratchov 1260: if (!LIST_EMPTY(&d->sub->outs)) {
1.69 ratchov 1261: dev_dbg(d);
1262: dbg_puts(": record end not idle, can't clear device\n");
1.39 ratchov 1263: dbg_panic();
1264: }
1265: #endif
1.57 ratchov 1266: buf = LIST_FIRST(&d->sub->ins);
1.13 ratchov 1267: while (buf) {
1268: abuf_clear(buf);
1.49 ratchov 1269: buf = LIST_FIRST(&buf->wproc->ins);
1.13 ratchov 1270: }
1.57 ratchov 1271: sub_clear(d->sub);
1.40 ratchov 1272: }
1.57 ratchov 1273: if (APROC_OK(d->submon)) {
1.46 ratchov 1274: #ifdef DEBUG
1.57 ratchov 1275: if (!LIST_EMPTY(&d->submon->outs)) {
1.69 ratchov 1276: dev_dbg(d);
1277: dbg_puts(": monitoring end not idle, can't clear device\n");
1.46 ratchov 1278: dbg_panic();
1279: }
1280: #endif
1.57 ratchov 1281: buf = LIST_FIRST(&d->submon->ins);
1.46 ratchov 1282: while (buf) {
1283: abuf_clear(buf);
1.49 ratchov 1284: buf = LIST_FIRST(&buf->wproc->ins);
1.46 ratchov 1285: }
1.57 ratchov 1286: sub_clear(d->submon);
1287: mon_clear(d->mon);
1.1 ratchov 1288: }
1.71 ratchov 1289: }
1290:
1291: #ifdef DEBUG
1292: void
1293: dev_slotdbg(struct dev *d, int slot)
1294: {
1295: struct ctl_slot *s;
1296:
1297: if (slot < 0) {
1298: dbg_puts("none");
1299: } else {
1300: s = d->slot + slot;
1301: dbg_puts(s->name);
1302: dbg_putu(s->unit);
1303: dbg_puts("(");
1304: dbg_putu(s->vol);
1305: dbg_puts(")/");
1306: switch (s->tstate) {
1307: case CTL_OFF:
1308: dbg_puts("off");
1309: break;
1310: case CTL_RUN:
1311: dbg_puts("run");
1312: break;
1313: case CTL_START:
1314: dbg_puts("sta");
1315: break;
1316: case CTL_STOP:
1317: dbg_puts("stp");
1318: break;
1319: default:
1320: dbg_puts("unk");
1321: break;
1322: }
1323: }
1324: }
1325: #endif
1326:
1327: /*
1328: * find the best matching free slot index (ie midi channel).
1329: * return -1, if there are no free slots anymore
1330: */
1331: int
1332: dev_mkslot(struct dev *d, char *who)
1333: {
1334: char *s;
1335: struct ctl_slot *slot;
1336: char name[CTL_NAMEMAX];
1.79 ratchov 1337: unsigned int i, unit, umap = 0;
1338: unsigned int ser, bestser, bestidx;
1.71 ratchov 1339:
1340: /*
1341: * create a ``valid'' control name (lowcase, remove [^a-z], trucate)
1342: */
1343: for (i = 0, s = who; ; s++) {
1344: if (i == CTL_NAMEMAX - 1 || *s == '\0') {
1345: name[i] = '\0';
1346: break;
1347: } else if (*s >= 'A' && *s <= 'Z') {
1348: name[i++] = *s + 'a' - 'A';
1349: } else if (*s >= 'a' && *s <= 'z')
1350: name[i++] = *s;
1351: }
1352: if (i == 0)
1353: strlcpy(name, "noname", CTL_NAMEMAX);
1354:
1355: /*
1356: * find the instance number of the control name
1357: */
1358: for (i = 0, slot = d->slot; i < CTL_NSLOT; i++, slot++) {
1359: if (slot->ops == NULL)
1360: continue;
1361: if (strcmp(slot->name, name) == 0)
1.80 ratchov 1362: umap |= (1 << slot->unit);
1.71 ratchov 1363: }
1364: for (unit = 0; ; unit++) {
1365: if (unit == CTL_NSLOT) {
1366: #ifdef DEBUG
1367: if (debug_level >= 1) {
1368: dbg_puts(name);
1369: dbg_puts(": too many instances\n");
1370: }
1371: #endif
1372: return -1;
1373: }
1374: if ((umap & (1 << unit)) == 0)
1375: break;
1376: }
1377:
1378: /*
1379: * find a free controller slot with the same name/unit
1380: */
1381: for (i = 0, slot = d->slot; i < CTL_NSLOT; i++, slot++) {
1382: if (slot->ops == NULL &&
1383: strcmp(slot->name, name) == 0 &&
1384: slot->unit == unit) {
1385: #ifdef DEBUG
1386: if (debug_level >= 3) {
1387: dbg_puts(name);
1388: dbg_putu(unit);
1389: dbg_puts(": found slot ");
1390: dbg_putu(i);
1391: dbg_puts("\n");
1392: }
1393: #endif
1394: return i;
1395: }
1396: }
1397:
1398: /*
1399: * couldn't find a matching slot, pick oldest free slot
1400: * and set its name/unit
1401: */
1402: bestser = 0;
1403: bestidx = CTL_NSLOT;
1404: for (i = 0, slot = d->slot; i < CTL_NSLOT; i++, slot++) {
1405: if (slot->ops != NULL)
1406: continue;
1407: ser = d->serial - slot->serial;
1408: if (ser > bestser) {
1409: bestser = ser;
1410: bestidx = i;
1411: }
1412: }
1413: if (bestidx == CTL_NSLOT) {
1414: #ifdef DEBUG
1415: if (debug_level >= 1) {
1416: dbg_puts(name);
1417: dbg_putu(unit);
1418: dbg_puts(": out of mixer slots\n");
1419: }
1420: #endif
1421: return -1;
1422: }
1423: slot = d->slot + bestidx;
1424: if (slot->name[0] != '\0')
1425: slot->vol = MIDI_MAXCTL;
1426: strlcpy(slot->name, name, CTL_NAMEMAX);
1427: slot->serial = d->serial++;
1428: slot->unit = unit;
1429: #ifdef DEBUG
1430: if (debug_level >= 3) {
1431: dbg_puts(name);
1432: dbg_putu(unit);
1433: dbg_puts(": overwritten slot ");
1434: dbg_putu(bestidx);
1435: dbg_puts("\n");
1436: }
1437: #endif
1438: return bestidx;
1439: }
1440:
1441: /*
1442: * allocate a new slot and register the given call-backs
1443: */
1444: int
1445: dev_slotnew(struct dev *d, char *who, struct ctl_ops *ops, void *arg, int mmc)
1446: {
1447: int slot;
1448: struct ctl_slot *s;
1449:
1450: slot = dev_mkslot(d, who);
1451: if (slot < 0)
1452: return -1;
1453:
1454: s = d->slot + slot;
1455: s->ops = ops;
1456: s->arg = arg;
1457: s->tstate = mmc ? CTL_STOP : CTL_OFF;
1458: s->ops->vol(s->arg, s->vol);
1459:
1460: if (APROC_OK(d->midi)) {
1.73 ratchov 1461: midi_send_slot(d->midi, slot);
1462: midi_send_vol(d->midi, slot, s->vol);
1463: midi_flush(d->midi);
1.71 ratchov 1464: } else {
1465: #ifdef DEBUG
1466: if (debug_level >= 2) {
1467: dev_slotdbg(d, slot);
1468: dbg_puts(": MIDI control not available\n");
1469: }
1470: #endif
1471: }
1472: return slot;
1473: }
1474:
1475: /*
1476: * release the given slot
1477: */
1478: void
1479: dev_slotdel(struct dev *d, int slot)
1480: {
1481: struct ctl_slot *s;
1482:
1483: s = d->slot + slot;
1484: s->ops = NULL;
1485: }
1486:
1487: /*
1488: * notifty the mixer that volume changed, called by whom allocad the slot using
1489: * ctl_slotnew(). Note: it doesn't make sens to call this from within the
1490: * call-back.
1491: *
1492: * XXX: set actual volume here and use only this interface. Now, this
1493: * can work because all streams have a slot
1494: */
1495: void
1.79 ratchov 1496: dev_slotvol(struct dev *d, int slot, unsigned int vol)
1.71 ratchov 1497: {
1498: #ifdef DEBUG
1499: if (debug_level >= 3) {
1500: dev_slotdbg(d, slot);
1501: dbg_puts(": changing volume to ");
1502: dbg_putu(vol);
1503: dbg_puts("\n");
1504: }
1505: #endif
1506: d->slot[slot].vol = vol;
1.73 ratchov 1507: if (APROC_OK(d->midi)) {
1508: midi_send_vol(d->midi, slot, vol);
1509: midi_flush(d->midi);
1.71 ratchov 1510: }
1511: }
1512:
1513: /*
1514: * check that all clients controlled by MMC are ready to start,
1515: * if so, start them all but the caller
1516: */
1517: int
1518: dev_try(struct dev *d, int slot)
1519: {
1.79 ratchov 1520: unsigned int i;
1.71 ratchov 1521: struct ctl_slot *s;
1522:
1523: if (d->tstate != CTL_START) {
1524: #ifdef DEBUG
1525: if (debug_level >= 3) {
1526: dev_slotdbg(d, slot);
1.85 ! ratchov 1527: dbg_puts(": server not started, delayed\n");
1.71 ratchov 1528: }
1529: #endif
1530: return 0;
1531: }
1532: for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
1533: if (!s->ops || i == slot)
1534: continue;
1535: if (s->tstate != CTL_OFF && s->tstate != CTL_START) {
1536: #ifdef DEBUG
1537: if (debug_level >= 3) {
1538: dev_slotdbg(d, i);
1539: dbg_puts(": not ready, server delayed\n");
1540: }
1541: #endif
1542: return 0;
1543: }
1544: }
1545: for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
1546: if (!s->ops || i == slot)
1547: continue;
1548: if (s->tstate == CTL_START) {
1549: #ifdef DEBUG
1550: if (debug_level >= 3) {
1551: dev_slotdbg(d, i);
1552: dbg_puts(": started\n");
1553: }
1554: #endif
1555: s->tstate = CTL_RUN;
1556: s->ops->start(s->arg);
1557: }
1558: }
1559: if (slot >= 0)
1560: d->slot[slot].tstate = CTL_RUN;
1561: d->tstate = CTL_RUN;
1.73 ratchov 1562: if (APROC_OK(d->midi)) {
1563: midi_send_full(d->midi,
1564: d->origin, d->rate, d->round, dev_getpos(d));
1565: midi_flush(d->midi);
1566: }
1.71 ratchov 1567: dev_wakeup(d);
1568: return 1;
1569: }
1570:
1571: /*
1572: * notify the MMC layer that the stream is attempting
1573: * to start. If other streams are not ready, 0 is returned meaning
1574: * that the stream should wait. If other streams are ready, they
1575: * are started, and the caller should start immediately.
1576: */
1577: int
1578: dev_slotstart(struct dev *d, int slot)
1579: {
1580: struct ctl_slot *s = d->slot + slot;
1581:
1582: if (s->tstate == CTL_OFF || d->tstate == CTL_OFF)
1583: return 1;
1584:
1585: /*
1586: * if the server already started (the client missed the
1587: * start rendez-vous) or the server is stopped, then
1588: * tag the client as ``wanting to start''
1589: */
1590: s->tstate = CTL_START;
1591: return dev_try(d, slot);
1592: }
1593:
1594: /*
1595: * notify the MMC layer that the stream no longer is trying to
1596: * start (or that it just stopped), meaning that its ``start'' call-back
1597: * shouldn't be called anymore
1598: */
1599: void
1600: dev_slotstop(struct dev *d, int slot)
1601: {
1602: struct ctl_slot *s = d->slot + slot;
1603:
1604: /*
1605: * tag the stream as not trying to start,
1606: * unless MMC is turned off
1607: */
1608: if (s->tstate != CTL_OFF)
1609: s->tstate = CTL_STOP;
1610: }
1611:
1612: /*
1613: * start all slots simultaneously
1614: */
1615: void
1616: dev_mmcstart(struct dev *d)
1617: {
1618: if (d->tstate == CTL_STOP) {
1619: d->tstate = CTL_START;
1620: (void)dev_try(d, -1);
1621: #ifdef DEBUG
1622: } else {
1623: if (debug_level >= 3) {
1624: dev_dbg(d);
1625: dbg_puts(": ignoring mmc start\n");
1626: }
1627: #endif
1628: }
1629: }
1630:
1631: /*
1632: * stop all slots simultaneously
1633: */
1634: void
1635: dev_mmcstop(struct dev *d)
1636: {
1.79 ratchov 1637: unsigned int i;
1.71 ratchov 1638: struct ctl_slot *s;
1639:
1640: switch (d->tstate) {
1641: case CTL_START:
1642: d->tstate = CTL_STOP;
1643: return;
1644: case CTL_RUN:
1645: d->tstate = CTL_STOP;
1646: break;
1647: default:
1648: #ifdef DEBUG
1649: if (debug_level >= 3) {
1650: dev_dbg(d);
1651: dbg_puts(": ignored mmc stop\n");
1652: }
1653: #endif
1654: return;
1655: }
1656: for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
1657: if (!s->ops)
1658: continue;
1659: if (s->tstate == CTL_RUN) {
1660: #ifdef DEBUG
1661: if (debug_level >= 3) {
1662: dev_slotdbg(d, i);
1663: dbg_puts(": requested to stop\n");
1664: }
1665: #endif
1666: s->ops->stop(s->arg);
1667: }
1668: }
1669: }
1670:
1671: /*
1672: * relocate all slots simultaneously
1673: */
1674: void
1.79 ratchov 1675: dev_loc(struct dev *d, unsigned int origin)
1.71 ratchov 1676: {
1.79 ratchov 1677: unsigned int i;
1.71 ratchov 1678: struct ctl_slot *s;
1679:
1680: #ifdef DEBUG
1681: if (debug_level >= 2) {
1682: dbg_puts("server relocated to ");
1683: dbg_putu(origin);
1684: dbg_puts("\n");
1685: }
1686: #endif
1687: if (d->tstate == CTL_RUN)
1688: dev_mmcstop(d);
1689: d->origin = origin;
1690: for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
1691: if (!s->ops)
1692: continue;
1693: s->ops->loc(s->arg, d->origin);
1694: }
1695: if (d->tstate == CTL_RUN)
1696: dev_mmcstart(d);
1697: }
1698:
1699: /*
1700: * called at every clock tick by the mixer, delta is positive, unless
1701: * there's an overrun/underrun
1702: */
1703: void
1704: dev_onmove(void *arg, int delta)
1705: {
1706: struct dev *d = (struct dev *)arg;
1707:
1708: /*
1709: * don't send ticks before the start signal
1710: */
1711: if (d->tstate != CTL_RUN)
1712: return;
1.73 ratchov 1713: if (APROC_OK(d->midi)) {
1714: midi_send_qfr(d->midi, d->rate, delta);
1.77 ratchov 1715: midi_flush(d->midi);
1716: }
1717: }
1718:
1719: void
1.79 ratchov 1720: dev_master(struct dev *d, unsigned int master)
1.77 ratchov 1721: {
1722: #ifdef DEBUG
1723: if (debug_level >= 3) {
1724: dev_dbg(d);
1725: dbg_puts(": changing master volume to ");
1726: dbg_putu(master);
1727: dbg_puts("\n");
1728: }
1729: #endif
1730: d->master = master;
1731: if (APROC_OK(d->mix)) {
1732: d->mix->u.mix.master = MIDI_TO_ADATA(master);
1733: mix_setmaster(d->mix);
1.73 ratchov 1734: }
1.1 ratchov 1735: }