Annotation of src/usr.bin/sndiod/dev.c, Revision 1.102
1.102 ! ratchov 1: /* $OpenBSD: dev.c,v 1.101 2021/04/28 05:10:29 ratchov Exp $ */
1.1 ratchov 2: /*
3: * Copyright (c) 2008-2012 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: */
17: #include <stdio.h>
18: #include <string.h>
19:
20: #include "abuf.h"
21: #include "defs.h"
22: #include "dev.h"
23: #include "dsp.h"
24: #include "siofile.h"
25: #include "midi.h"
1.36 ratchov 26: #include "opt.h"
1.1 ratchov 27: #include "sysex.h"
28: #include "utils.h"
29:
1.14 ratchov 30: void zomb_onmove(void *);
1.25 ratchov 31: void zomb_onvol(void *);
1.1 ratchov 32: void zomb_fill(void *);
33: void zomb_flush(void *);
34: void zomb_eof(void *);
35: void zomb_exit(void *);
36:
1.7 ratchov 37: void dev_mix_badd(struct dev *, struct slot *);
38: void dev_mix_adjvol(struct dev *);
39: void dev_sub_bcopy(struct dev *, struct slot *);
40:
41: void dev_onmove(struct dev *, int);
42: void dev_master(struct dev *, unsigned int);
43: void dev_cycle(struct dev *);
44: struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
45: unsigned int, unsigned int, unsigned int, unsigned int);
1.25 ratchov 46: void dev_adjpar(struct dev *, int, int, int);
1.59 ratchov 47: int dev_allocbufs(struct dev *);
1.7 ratchov 48: int dev_open(struct dev *);
1.59 ratchov 49: void dev_freebufs(struct dev *);
1.7 ratchov 50: void dev_close(struct dev *);
51: int dev_ref(struct dev *);
52: void dev_unref(struct dev *);
53: int dev_init(struct dev *);
54: void dev_done(struct dev *);
55: struct dev *dev_bynum(int);
56: void dev_del(struct dev *);
1.75 ratchov 57: void dev_setalt(struct dev *, unsigned int);
1.7 ratchov 58: unsigned int dev_roundof(struct dev *, unsigned int);
59: void dev_wakeup(struct dev *);
60:
1.64 ratchov 61: void slot_ctlname(struct slot *, char *, size_t);
1.7 ratchov 62: void slot_log(struct slot *);
63: void slot_del(struct slot *);
64: void slot_setvol(struct slot *, unsigned int);
65: void slot_ready(struct slot *);
1.35 ratchov 66: void slot_allocbufs(struct slot *);
67: void slot_freebufs(struct slot *);
1.12 ratchov 68: void slot_skip_update(struct slot *);
1.7 ratchov 69: void slot_write(struct slot *);
70: void slot_read(struct slot *);
1.12 ratchov 71: int slot_skip(struct slot *);
1.1 ratchov 72:
1.64 ratchov 73: void ctl_node_log(struct ctl_node *);
74: void ctl_log(struct ctl *);
75:
1.1 ratchov 76: struct slotops zomb_slotops = {
77: zomb_onmove,
78: zomb_onvol,
79: zomb_fill,
80: zomb_flush,
81: zomb_eof,
82: zomb_exit
83: };
84:
1.92 ratchov 85: struct ctl *ctl_list = NULL;
1.1 ratchov 86: struct dev *dev_list = NULL;
87: unsigned int dev_sndnum = 0;
88:
1.85 ratchov 89: struct ctlslot ctlslot_array[DEV_NCTLSLOT];
1.84 ratchov 90: struct slot slot_array[DEV_NSLOT];
91: unsigned int slot_serial; /* for slot allocation */
92:
1.94 ratchov 93: /*
94: * we support/need a single MTC clock source only
95: */
96: struct mtc mtc_array[1] = {
97: {.dev = NULL, .tstate = MTC_STOP}
98: };
99:
1.84 ratchov 100: void
101: slot_array_init(void)
102: {
103: unsigned int i;
104:
105: for (i = 0; i < DEV_NSLOT; i++) {
106: slot_array[i].unit = i;
107: slot_array[i].ops = NULL;
108: slot_array[i].vol = MIDI_MAXCTL;
1.89 ratchov 109: slot_array[i].opt = NULL;
1.84 ratchov 110: slot_array[i].serial = slot_serial++;
111: memset(slot_array[i].name, 0, SLOT_NAMEMAX);
112: }
113: }
114:
1.1 ratchov 115: void
116: dev_log(struct dev *d)
117: {
1.3 ratchov 118: #ifdef DEBUG
119: static char *pstates[] = {
120: "cfg", "ini", "run"
121: };
122: #endif
1.1 ratchov 123: log_puts("snd");
124: log_putu(d->num);
1.3 ratchov 125: #ifdef DEBUG
126: if (log_level >= 3) {
127: log_puts(" pst=");
128: log_puts(pstates[d->pstate]);
129: }
130: #endif
1.1 ratchov 131: }
132:
133: void
1.64 ratchov 134: slot_ctlname(struct slot *s, char *name, size_t size)
135: {
136: snprintf(name, size, "%s%u", s->name, s->unit);
137: }
138:
139: void
1.1 ratchov 140: slot_log(struct slot *s)
1.3 ratchov 141: {
1.64 ratchov 142: char name[CTL_NAMEMAX];
1.1 ratchov 143: #ifdef DEBUG
144: static char *pstates[] = {
145: "ini", "sta", "rdy", "run", "stp", "mid"
146: };
147: #endif
1.64 ratchov 148: slot_ctlname(s, name, CTL_NAMEMAX);
149: log_puts(name);
1.1 ratchov 150: #ifdef DEBUG
151: if (log_level >= 3) {
152: log_puts(" vol=");
153: log_putu(s->vol);
154: if (s->ops) {
155: log_puts(",pst=");
156: log_puts(pstates[s->pstate]);
157: }
158: }
159: #endif
160: }
161:
162: void
1.14 ratchov 163: zomb_onmove(void *arg)
1.1 ratchov 164: {
165: }
166:
167: void
1.25 ratchov 168: zomb_onvol(void *arg)
1.1 ratchov 169: {
170: }
171:
172: void
173: zomb_fill(void *arg)
174: {
175: }
176:
177: void
178: zomb_flush(void *arg)
179: {
180: }
181:
182: void
183: zomb_eof(void *arg)
184: {
185: struct slot *s = arg;
186:
187: #ifdef DEBUG
188: if (log_level >= 3) {
189: slot_log(s);
190: log_puts(": zomb_eof\n");
191: }
192: #endif
193: s->ops = NULL;
194: }
195:
196: void
197: zomb_exit(void *arg)
198: {
199: #ifdef DEBUG
200: struct slot *s = arg;
201:
202: if (log_level >= 3) {
203: slot_log(s);
204: log_puts(": zomb_exit\n");
205: }
206: #endif
207: }
208:
209: /*
1.93 ratchov 210: * Broadcast MIDI data to all opts using this device
211: */
212: void
213: dev_midi_send(struct dev *d, void *msg, int msglen)
214: {
215: struct opt *o;
216:
217: for (o = opt_list; o != NULL; o = o->next) {
218: if (o->dev != d)
219: continue;
220: midi_send(o->midi, msg, msglen);
221: }
222: }
223:
224: /*
1.1 ratchov 225: * send a quarter frame MTC message
226: */
227: void
1.94 ratchov 228: mtc_midi_qfr(struct mtc *mtc, int delta)
1.1 ratchov 229: {
230: unsigned char buf[2];
231: unsigned int data;
232: int qfrlen;
233:
1.94 ratchov 234: mtc->delta += delta * MTC_SEC;
235: qfrlen = mtc->dev->rate * (MTC_SEC / (4 * mtc->fps));
236: while (mtc->delta >= qfrlen) {
237: switch (mtc->qfr) {
1.1 ratchov 238: case 0:
1.94 ratchov 239: data = mtc->fr & 0xf;
1.1 ratchov 240: break;
241: case 1:
1.94 ratchov 242: data = mtc->fr >> 4;
1.1 ratchov 243: break;
244: case 2:
1.94 ratchov 245: data = mtc->sec & 0xf;
1.1 ratchov 246: break;
247: case 3:
1.94 ratchov 248: data = mtc->sec >> 4;
1.1 ratchov 249: break;
250: case 4:
1.94 ratchov 251: data = mtc->min & 0xf;
1.1 ratchov 252: break;
253: case 5:
1.94 ratchov 254: data = mtc->min >> 4;
1.1 ratchov 255: break;
256: case 6:
1.94 ratchov 257: data = mtc->hr & 0xf;
1.1 ratchov 258: break;
259: case 7:
1.94 ratchov 260: data = (mtc->hr >> 4) | (mtc->fps_id << 1);
1.1 ratchov 261: /*
262: * tick messages are sent 2 frames ahead
263: */
1.94 ratchov 264: mtc->fr += 2;
265: if (mtc->fr < mtc->fps)
1.1 ratchov 266: break;
1.94 ratchov 267: mtc->fr -= mtc->fps;
268: mtc->sec++;
269: if (mtc->sec < 60)
1.1 ratchov 270: break;
1.94 ratchov 271: mtc->sec = 0;
272: mtc->min++;
273: if (mtc->min < 60)
1.1 ratchov 274: break;
1.94 ratchov 275: mtc->min = 0;
276: mtc->hr++;
277: if (mtc->hr < 24)
1.1 ratchov 278: break;
1.94 ratchov 279: mtc->hr = 0;
1.1 ratchov 280: break;
281: default:
282: /* NOTREACHED */
283: data = 0;
284: }
285: buf[0] = 0xf1;
1.94 ratchov 286: buf[1] = (mtc->qfr << 4) | data;
287: mtc->qfr++;
288: mtc->qfr &= 7;
289: dev_midi_send(mtc->dev, buf, 2);
290: mtc->delta -= qfrlen;
1.1 ratchov 291: }
292: }
293:
294: /*
295: * send a full frame MTC message
296: */
297: void
1.94 ratchov 298: mtc_midi_full(struct mtc *mtc)
1.1 ratchov 299: {
300: struct sysex x;
301: unsigned int fps;
302:
1.101 ratchov 303: mtc->delta = -MTC_SEC * (int)mtc->dev->bufsz;
1.94 ratchov 304: if (mtc->dev->rate % (30 * 4 * mtc->dev->round) == 0) {
305: mtc->fps_id = MTC_FPS_30;
306: mtc->fps = 30;
307: } else if (mtc->dev->rate % (25 * 4 * mtc->dev->round) == 0) {
308: mtc->fps_id = MTC_FPS_25;
309: mtc->fps = 25;
1.1 ratchov 310: } else {
1.94 ratchov 311: mtc->fps_id = MTC_FPS_24;
312: mtc->fps = 24;
1.1 ratchov 313: }
314: #ifdef DEBUG
315: if (log_level >= 3) {
1.94 ratchov 316: dev_log(mtc->dev);
1.1 ratchov 317: log_puts(": mtc full frame at ");
1.94 ratchov 318: log_puti(mtc->delta);
1.1 ratchov 319: log_puts(", ");
1.94 ratchov 320: log_puti(mtc->fps);
1.1 ratchov 321: log_puts(" fps\n");
322: }
323: #endif
1.94 ratchov 324: fps = mtc->fps;
325: mtc->hr = (mtc->origin / (MTC_SEC * 3600)) % 24;
326: mtc->min = (mtc->origin / (MTC_SEC * 60)) % 60;
327: mtc->sec = (mtc->origin / (MTC_SEC)) % 60;
328: mtc->fr = (mtc->origin / (MTC_SEC / fps)) % fps;
1.1 ratchov 329:
330: x.start = SYSEX_START;
331: x.type = SYSEX_TYPE_RT;
1.8 ratchov 332: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 333: x.id0 = SYSEX_MTC;
334: x.id1 = SYSEX_MTC_FULL;
1.94 ratchov 335: x.u.full.hr = mtc->hr | (mtc->fps_id << 5);
336: x.u.full.min = mtc->min;
337: x.u.full.sec = mtc->sec;
338: x.u.full.fr = mtc->fr;
1.1 ratchov 339: x.u.full.end = SYSEX_END;
1.94 ratchov 340: mtc->qfr = 0;
341: dev_midi_send(mtc->dev, (unsigned char *)&x, SYSEX_SIZE(full));
1.1 ratchov 342: }
343:
344: /*
345: * send a volume change MIDI message
346: */
347: void
348: dev_midi_vol(struct dev *d, struct slot *s)
349: {
350: unsigned char msg[3];
351:
1.84 ratchov 352: msg[0] = MIDI_CTL | (s - slot_array);
1.1 ratchov 353: msg[1] = MIDI_CTL_VOL;
354: msg[2] = s->vol;
1.93 ratchov 355: dev_midi_send(d, msg, 3);
1.1 ratchov 356: }
357:
358: /*
359: * send a master volume MIDI message
360: */
361: void
362: dev_midi_master(struct dev *d)
363: {
1.70 ratchov 364: struct ctl *c;
365: unsigned int master, v;
1.1 ratchov 366: struct sysex x;
367:
1.70 ratchov 368: if (d->master_enabled)
369: master = d->master;
370: else {
371: master = 0;
1.92 ratchov 372: for (c = ctl_list; c != NULL; c = c->next) {
1.70 ratchov 373: if (c->type != CTL_NUM ||
1.92 ratchov 374: strcmp(c->group, d->name) != 0 ||
1.70 ratchov 375: strcmp(c->node0.name, "output") != 0 ||
376: strcmp(c->func, "level") != 0)
377: continue;
1.92 ratchov 378: if (c->u.any.arg0 != d)
379: continue;
1.70 ratchov 380: v = (c->curval * 127 + c->maxval / 2) / c->maxval;
381: if (master < v)
382: master = v;
383: }
384: }
385:
1.1 ratchov 386: memset(&x, 0, sizeof(struct sysex));
387: x.start = SYSEX_START;
388: x.type = SYSEX_TYPE_RT;
1.8 ratchov 389: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 390: x.id0 = SYSEX_CONTROL;
391: x.id1 = SYSEX_MASTER;
392: x.u.master.fine = 0;
1.70 ratchov 393: x.u.master.coarse = master;
1.1 ratchov 394: x.u.master.end = SYSEX_END;
1.93 ratchov 395: dev_midi_send(d, (unsigned char *)&x, SYSEX_SIZE(master));
1.1 ratchov 396: }
397:
398: /*
399: * send a sndiod-specific slot description MIDI message
400: */
401: void
402: dev_midi_slotdesc(struct dev *d, struct slot *s)
403: {
404: struct sysex x;
405:
406: memset(&x, 0, sizeof(struct sysex));
407: x.start = SYSEX_START;
408: x.type = SYSEX_TYPE_EDU;
1.8 ratchov 409: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 410: x.id0 = SYSEX_AUCAT;
411: x.id1 = SYSEX_AUCAT_SLOTDESC;
1.89 ratchov 412: if (s->opt != NULL && s->opt->dev == d)
1.64 ratchov 413: slot_ctlname(s, (char *)x.u.slotdesc.name, SYSEX_NAMELEN);
1.84 ratchov 414: x.u.slotdesc.chan = (s - slot_array);
1.1 ratchov 415: x.u.slotdesc.end = SYSEX_END;
1.93 ratchov 416: dev_midi_send(d, (unsigned char *)&x, SYSEX_SIZE(slotdesc));
1.1 ratchov 417: }
418:
419: void
420: dev_midi_dump(struct dev *d)
421: {
422: struct sysex x;
423: struct slot *s;
424: int i;
425:
426: dev_midi_master(d);
1.84 ratchov 427: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.89 ratchov 428: if (s->opt != NULL && s->opt->dev != d)
1.84 ratchov 429: continue;
1.1 ratchov 430: dev_midi_slotdesc(d, s);
431: dev_midi_vol(d, s);
432: }
433: x.start = SYSEX_START;
434: x.type = SYSEX_TYPE_EDU;
1.8 ratchov 435: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 436: x.id0 = SYSEX_AUCAT;
437: x.id1 = SYSEX_AUCAT_DUMPEND;
438: x.u.dumpend.end = SYSEX_END;
1.93 ratchov 439: dev_midi_send(d, (unsigned char *)&x, SYSEX_SIZE(dumpend));
1.1 ratchov 440: }
441:
1.12 ratchov 442: int
443: slot_skip(struct slot *s)
1.1 ratchov 444: {
1.12 ratchov 445: unsigned char *data = (unsigned char *)0xdeadbeef; /* please gcc */
446: int max, count;
447:
448: max = s->skip;
449: while (s->skip > 0) {
450: if (s->pstate != SLOT_STOP && (s->mode & MODE_RECMASK)) {
451: data = abuf_wgetblk(&s->sub.buf, &count);
452: if (count < s->round * s->sub.bpf)
453: break;
454: }
455: if (s->mode & MODE_PLAY) {
456: if (s->mix.buf.used < s->round * s->mix.bpf)
457: break;
458: }
1.1 ratchov 459: #ifdef DEBUG
460: if (log_level >= 4) {
461: slot_log(s);
1.12 ratchov 462: log_puts(": skipped a cycle\n");
1.1 ratchov 463: }
464: #endif
1.12 ratchov 465: if (s->pstate != SLOT_STOP && (s->mode & MODE_RECMASK)) {
466: if (s->sub.encbuf)
467: enc_sil_do(&s->sub.enc, data, s->round);
468: else
469: memset(data, 0, s->round * s->sub.bpf);
470: abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf);
471: }
472: if (s->mode & MODE_PLAY) {
473: abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf);
1.1 ratchov 474: }
1.23 ratchov 475: s->skip--;
1.1 ratchov 476: }
1.12 ratchov 477: return max - s->skip;
1.1 ratchov 478: }
479:
1.32 ratchov 480: /*
481: * Mix the slot input block over the output block
482: */
483: void
484: dev_mix_badd(struct dev *d, struct slot *s)
1.1 ratchov 485: {
1.32 ratchov 486: adata_t *idata, *odata, *in;
487: int icount, i, offs, vol, nch;
488:
489: odata = DEV_PBUF(d);
490: idata = (adata_t *)abuf_rgetblk(&s->mix.buf, &icount);
491: #ifdef DEBUG
492: if (icount < s->round * s->mix.bpf) {
493: slot_log(s);
494: log_puts(": not enough data to mix (");
495: log_putu(icount);
496: log_puts("bytes)\n");
497: panic();
498: }
499: #endif
1.102 ! ratchov 500: if (!(s->opt->mode & MODE_PLAY)) {
! 501: /*
! 502: * playback not allowed in opt structure, produce silence
! 503: */
! 504: abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf);
! 505: return;
! 506: }
! 507:
1.32 ratchov 508:
509: /*
510: * Apply the following processing chain:
511: *
512: * dec -> resamp-> cmap
513: *
514: * where the first two are optional.
515: */
516:
517: in = idata;
518:
519: if (s->mix.decbuf) {
520: dec_do(&s->mix.dec, (void *)in, s->mix.decbuf, s->round);
521: in = s->mix.decbuf;
522: }
1.1 ratchov 523:
524: if (s->mix.resampbuf) {
1.32 ratchov 525: resamp_do(&s->mix.resamp, in, s->mix.resampbuf, s->round);
1.1 ratchov 526: in = s->mix.resampbuf;
1.32 ratchov 527: }
1.1 ratchov 528:
1.10 ratchov 529: nch = s->mix.cmap.nch;
1.1 ratchov 530: vol = ADATA_MUL(s->mix.weight, s->mix.vol) / s->mix.join;
1.32 ratchov 531: cmap_add(&s->mix.cmap, in, odata, vol, d->round);
1.1 ratchov 532:
533: offs = 0;
534: for (i = s->mix.join - 1; i > 0; i--) {
535: offs += nch;
1.32 ratchov 536: cmap_add(&s->mix.cmap, in + offs, odata, vol, d->round);
1.1 ratchov 537: }
1.32 ratchov 538:
1.1 ratchov 539: offs = 0;
540: for (i = s->mix.expand - 1; i > 0; i--) {
541: offs += nch;
1.32 ratchov 542: cmap_add(&s->mix.cmap, in, odata + offs, vol, d->round);
1.1 ratchov 543: }
544:
545: abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf);
546: }
547:
548: /*
549: * Normalize input levels.
550: */
551: void
552: dev_mix_adjvol(struct dev *d)
553: {
554: unsigned int n;
555: struct slot *i, *j;
1.42 ratchov 556: int jcmax, icmax, weight;
1.1 ratchov 557:
558: for (i = d->slot_list; i != NULL; i = i->next) {
559: if (!(i->mode & MODE_PLAY))
560: continue;
1.42 ratchov 561: icmax = i->opt->pmin + i->mix.nch - 1;
1.1 ratchov 562: weight = ADATA_UNIT;
563: if (d->autovol) {
564: /*
565: * count the number of inputs that have
566: * overlapping channel sets
567: */
568: n = 0;
569: for (j = d->slot_list; j != NULL; j = j->next) {
570: if (!(j->mode & MODE_PLAY))
571: continue;
1.42 ratchov 572: jcmax = j->opt->pmin + j->mix.nch - 1;
573: if (i->opt->pmin <= jcmax &&
574: icmax >= j->opt->pmin)
1.1 ratchov 575: n++;
576: }
577: weight /= n;
578: }
1.38 ratchov 579: if (weight > i->opt->maxweight)
580: weight = i->opt->maxweight;
1.70 ratchov 581: i->mix.weight = d->master_enabled ?
582: ADATA_MUL(weight, MIDI_TO_ADATA(d->master)) : weight;
1.1 ratchov 583: #ifdef DEBUG
584: if (log_level >= 3) {
585: slot_log(i);
586: log_puts(": set weight: ");
587: log_puti(i->mix.weight);
588: log_puts("/");
1.38 ratchov 589: log_puti(i->opt->maxweight);
1.1 ratchov 590: log_puts("\n");
591: }
592: #endif
593: }
594: }
595:
596: /*
597: * Copy data from slot to device
598: */
599: void
600: dev_sub_bcopy(struct dev *d, struct slot *s)
601: {
1.32 ratchov 602: adata_t *idata, *enc_out, *resamp_out, *cmap_out;
603: void *odata;
1.15 ratchov 604: int ocount, moffs;
1.1 ratchov 605:
1.32 ratchov 606: int i, vol, offs, nch;
607:
608:
1.1 ratchov 609: odata = (adata_t *)abuf_wgetblk(&s->sub.buf, &ocount);
610: #ifdef DEBUG
611: if (ocount < s->round * s->sub.bpf) {
612: log_puts("dev_sub_bcopy: not enough space\n");
613: panic();
614: }
615: #endif
1.102 ! ratchov 616: if (s->opt->mode & MODE_MON) {
! 617: moffs = d->poffs + d->round;
! 618: if (moffs == d->psize)
! 619: moffs = 0;
! 620: idata = d->pbuf + moffs * d->pchan;
! 621: } else if (s->opt->mode & MODE_REC) {
! 622: idata = d->rbuf;
! 623: } else {
! 624: /*
! 625: * recording not allowed in opt structure, produce silence
! 626: */
! 627: enc_sil_do(&s->sub.enc, odata, s->round);
! 628: abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf);
! 629: return;
! 630: }
1.32 ratchov 631:
632: /*
633: * Apply the following processing chain:
634: *
635: * cmap -> resamp -> enc
636: *
637: * where the last two are optional.
638: */
639:
640: enc_out = odata;
641: resamp_out = s->sub.encbuf ? s->sub.encbuf : enc_out;
642: cmap_out = s->sub.resampbuf ? s->sub.resampbuf : resamp_out;
643:
644: nch = s->sub.cmap.nch;
645: vol = ADATA_UNIT / s->sub.join;
646: cmap_copy(&s->sub.cmap, idata, cmap_out, vol, d->round);
647:
648: offs = 0;
649: for (i = s->sub.join - 1; i > 0; i--) {
650: offs += nch;
651: cmap_add(&s->sub.cmap, idata + offs, cmap_out, vol, d->round);
652: }
653:
654: offs = 0;
655: for (i = s->sub.expand - 1; i > 0; i--) {
656: offs += nch;
657: cmap_copy(&s->sub.cmap, idata, cmap_out + offs, vol, d->round);
658: }
659:
660: if (s->sub.resampbuf) {
661: resamp_do(&s->sub.resamp,
662: s->sub.resampbuf, resamp_out, d->round);
663: }
664:
665: if (s->sub.encbuf)
666: enc_do(&s->sub.enc, s->sub.encbuf, (void *)enc_out, s->round);
667:
668: abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf);
1.1 ratchov 669: }
670:
1.16 ratchov 671: /*
672: * run a one block cycle: consume one recorded block from
673: * rbuf and produce one play block in pbuf
674: */
1.1 ratchov 675: void
1.16 ratchov 676: dev_cycle(struct dev *d)
1.1 ratchov 677: {
678: struct slot *s, **ps;
1.12 ratchov 679: unsigned char *base;
680: int nsamp;
1.1 ratchov 681:
1.16 ratchov 682: /*
683: * check if the device is actually used. If it isn't,
684: * then close it
685: */
1.94 ratchov 686: if (d->slot_list == NULL && (mtc_array[0].dev != d ||
687: mtc_array[0].tstate != MTC_RUN)) {
1.16 ratchov 688: if (log_level >= 2) {
689: dev_log(d);
690: log_puts(": device stopped\n");
691: }
692: dev_sio_stop(d);
693: d->pstate = DEV_INIT;
694: if (d->refcnt == 0)
695: dev_close(d);
696: return;
697: }
698:
699: if (d->prime > 0) {
700: #ifdef DEBUG
701: if (log_level >= 4) {
702: dev_log(d);
703: log_puts(": empty cycle, prime = ");
704: log_putu(d->prime);
705: log_puts("\n");
706: }
707: #endif
708: base = (unsigned char *)DEV_PBUF(d);
709: nsamp = d->round * d->pchan;
710: memset(base, 0, nsamp * sizeof(adata_t));
711: if (d->encbuf) {
712: enc_do(&d->enc, (unsigned char *)DEV_PBUF(d),
713: d->encbuf, d->round);
714: }
715: d->prime -= d->round;
716: return;
717: }
718:
1.12 ratchov 719: d->delta -= d->round;
1.1 ratchov 720: #ifdef DEBUG
721: if (log_level >= 4) {
722: dev_log(d);
1.16 ratchov 723: log_puts(": full cycle: delta = ");
1.12 ratchov 724: log_puti(d->delta);
725: if (d->mode & MODE_PLAY) {
726: log_puts(", poffs = ");
727: log_puti(d->poffs);
728: }
729: log_puts("\n");
1.1 ratchov 730: }
731: #endif
1.12 ratchov 732: if (d->mode & MODE_PLAY) {
733: base = (unsigned char *)DEV_PBUF(d);
734: nsamp = d->round * d->pchan;
735: memset(base, 0, nsamp * sizeof(adata_t));
736: }
1.1 ratchov 737: if ((d->mode & MODE_REC) && d->decbuf)
738: dec_do(&d->dec, d->decbuf, (unsigned char *)d->rbuf, d->round);
739: ps = &d->slot_list;
740: while ((s = *ps) != NULL) {
1.12 ratchov 741: #ifdef DEBUG
742: if (log_level >= 4) {
743: slot_log(s);
744: log_puts(": running");
745: log_puts(", skip = ");
746: log_puti(s->skip);
747: log_puts("\n");
748: }
749: #endif
750: /*
751: * skip cycles for XRUN_SYNC correction
752: */
753: slot_skip(s);
754: if (s->skip < 0) {
755: s->skip++;
1.1 ratchov 756: ps = &s->next;
757: continue;
758: }
1.12 ratchov 759:
760: #ifdef DEBUG
761: if (s->pstate == SLOT_STOP && !(s->mode & MODE_PLAY)) {
762: slot_log(s);
763: log_puts(": rec-only slots can't be drained\n");
764: panic();
765: }
766: #endif
767: /*
768: * check if stopped stream finished draining
769: */
770: if (s->pstate == SLOT_STOP &&
771: s->mix.buf.used < s->round * s->mix.bpf) {
772: /*
773: * partial blocks are zero-filled by socket
774: * layer, so s->mix.buf.used == 0 and we can
775: * destroy the buffer
776: */
1.35 ratchov 777: *ps = s->next;
1.12 ratchov 778: s->pstate = SLOT_INIT;
779: s->ops->eof(s->arg);
1.35 ratchov 780: slot_freebufs(s);
1.12 ratchov 781: dev_mix_adjvol(d);
1.35 ratchov 782: #ifdef DEBUG
783: if (log_level >= 3) {
784: slot_log(s);
785: log_puts(": drained\n");
786: }
787: #endif
1.1 ratchov 788: continue;
789: }
1.23 ratchov 790:
1.12 ratchov 791: /*
792: * check for xruns
793: */
1.23 ratchov 794: if (((s->mode & MODE_PLAY) &&
1.12 ratchov 795: s->mix.buf.used < s->round * s->mix.bpf) ||
796: ((s->mode & MODE_RECMASK) &&
797: s->sub.buf.len - s->sub.buf.used <
798: s->round * s->sub.bpf)) {
799:
800: #ifdef DEBUG
801: if (log_level >= 3) {
802: slot_log(s);
803: log_puts(": xrun, pause cycle\n");
804: }
805: #endif
1.1 ratchov 806: if (s->xrun == XRUN_IGNORE) {
807: s->delta -= s->round;
1.12 ratchov 808: ps = &s->next;
809: } else if (s->xrun == XRUN_SYNC) {
810: s->skip++;
811: ps = &s->next;
812: } else if (s->xrun == XRUN_ERROR) {
813: s->ops->exit(s->arg);
814: *ps = s->next;
815: } else {
816: #ifdef DEBUG
817: slot_log(s);
818: log_puts(": bad xrun mode\n");
819: panic();
820: #endif
821: }
822: continue;
823: }
824: if ((s->mode & MODE_RECMASK) && !(s->pstate == SLOT_STOP)) {
825: if (s->sub.prime == 0) {
826: dev_sub_bcopy(d, s);
827: s->ops->flush(s->arg);
828: } else {
1.1 ratchov 829: #ifdef DEBUG
830: if (log_level >= 3) {
831: slot_log(s);
1.12 ratchov 832: log_puts(": prime = ");
833: log_puti(s->sub.prime);
834: log_puts("\n");
1.1 ratchov 835: }
836: #endif
1.12 ratchov 837: s->sub.prime--;
1.1 ratchov 838: }
839: }
1.15 ratchov 840: if (s->mode & MODE_PLAY) {
841: dev_mix_badd(d, s);
842: if (s->pstate != SLOT_STOP)
843: s->ops->fill(s->arg);
844: }
1.1 ratchov 845: ps = &s->next;
846: }
1.12 ratchov 847: if ((d->mode & MODE_PLAY) && d->encbuf) {
848: enc_do(&d->enc, (unsigned char *)DEV_PBUF(d),
849: d->encbuf, d->round);
850: }
1.1 ratchov 851: }
852:
853: /*
854: * called at every clock tick by the device
855: */
856: void
857: dev_onmove(struct dev *d, int delta)
858: {
859: long long pos;
1.23 ratchov 860: struct slot *s, *snext;
1.12 ratchov 861:
862: d->delta += delta;
1.1 ratchov 863:
864: for (s = d->slot_list; s != NULL; s = snext) {
1.12 ratchov 865: /*
866: * s->ops->onmove() may remove the slot
867: */
1.1 ratchov 868: snext = s->next;
1.80 ratchov 869: pos = s->delta_rem +
870: (long long)s->delta * d->round +
871: (long long)delta * s->round;
872: s->delta = pos / (int)d->round;
1.1 ratchov 873: s->delta_rem = pos % d->round;
1.80 ratchov 874: if (s->delta_rem < 0) {
875: s->delta_rem += d->round;
876: s->delta--;
877: }
1.1 ratchov 878: if (s->delta >= 0)
1.14 ratchov 879: s->ops->onmove(s->arg);
1.1 ratchov 880: }
1.94 ratchov 881:
882: if (mtc_array[0].dev == d && mtc_array[0].tstate == MTC_RUN)
883: mtc_midi_qfr(&mtc_array[0], delta);
1.1 ratchov 884: }
885:
886: void
887: dev_master(struct dev *d, unsigned int master)
888: {
1.70 ratchov 889: struct ctl *c;
890: unsigned int v;
891:
1.1 ratchov 892: if (log_level >= 2) {
893: dev_log(d);
894: log_puts(": master volume set to ");
895: log_putu(master);
896: log_puts("\n");
897: }
1.70 ratchov 898: if (d->master_enabled) {
899: d->master = master;
900: if (d->mode & MODE_PLAY)
901: dev_mix_adjvol(d);
902: } else {
1.92 ratchov 903: for (c = ctl_list; c != NULL; c = c->next) {
904: if (c->scope != CTL_HW || c->u.hw.dev != d)
905: continue;
1.70 ratchov 906: if (c->type != CTL_NUM ||
1.92 ratchov 907: strcmp(c->group, d->name) != 0 ||
1.70 ratchov 908: strcmp(c->node0.name, "output") != 0 ||
909: strcmp(c->func, "level") != 0)
910: continue;
911: v = (master * c->maxval + 64) / 127;
1.92 ratchov 912: ctl_setval(c, v);
1.70 ratchov 913: }
914: }
1.1 ratchov 915: }
916:
917: /*
918: * Create a sndio device
919: */
920: struct dev *
921: dev_new(char *path, struct aparams *par,
922: unsigned int mode, unsigned int bufsz, unsigned int round,
923: unsigned int rate, unsigned int hold, unsigned int autovol)
924: {
1.97 ratchov 925: struct dev *d, **pd;
1.1 ratchov 926:
927: if (dev_sndnum == DEV_NMAX) {
928: if (log_level >= 1)
929: log_puts("too many devices\n");
930: return NULL;
931: }
932: d = xmalloc(sizeof(struct dev));
1.73 ratchov 933: d->alt_list = NULL;
934: dev_addname(d,path);
1.1 ratchov 935: d->num = dev_sndnum++;
1.76 ratchov 936: d->alt_num = -1;
1.1 ratchov 937:
938: d->reqpar = *par;
939: d->reqmode = mode;
940: d->reqpchan = d->reqrchan = 0;
941: d->reqbufsz = bufsz;
942: d->reqround = round;
943: d->reqrate = rate;
944: d->hold = hold;
945: d->autovol = autovol;
946: d->refcnt = 0;
947: d->pstate = DEV_CFG;
948: d->slot_list = NULL;
949: d->master = MIDI_MAXCTL;
1.96 ratchov 950: d->master_enabled = 0;
1.92 ratchov 951: snprintf(d->name, CTL_NAMEMAX, "%u", d->num);
1.97 ratchov 952: for (pd = &dev_list; *pd != NULL; pd = &(*pd)->next)
953: ;
954: d->next = *pd;
955: *pd = d;
1.1 ratchov 956: return d;
957: }
958:
959: /*
1.73 ratchov 960: * add a alternate name
961: */
962: int
963: dev_addname(struct dev *d, char *name)
964: {
965: struct dev_alt *a;
966:
967: if (d->alt_list != NULL && d->alt_list->idx == DEV_NMAX - 1) {
968: log_puts(name);
969: log_puts(": too many alternate names\n");
970: return 0;
971: }
972: a = xmalloc(sizeof(struct dev_alt));
973: a->name = name;
974: a->idx = (d->alt_list == NULL) ? 0 : d->alt_list->idx + 1;
975: a->next = d->alt_list;
976: d->alt_list = a;
977: return 1;
978: }
979:
980: /*
1.75 ratchov 981: * set prefered alt device name
982: */
983: void
984: dev_setalt(struct dev *d, unsigned int idx)
985: {
986: struct dev_alt **pa, *a;
987:
988: /* find alt with given index */
989: for (pa = &d->alt_list; (a = *pa)->idx != idx; pa = &a->next)
990: ;
991:
992: /* detach from list */
993: *pa = a->next;
994:
995: /* attach at head */
996: a->next = d->alt_list;
997: d->alt_list = a;
998:
999: /* reopen device with the new alt */
1000: if (idx != d->alt_num)
1001: dev_reopen(d);
1002: }
1003:
1004: /*
1.1 ratchov 1005: * adjust device parameters and mode
1006: */
1007: void
1008: dev_adjpar(struct dev *d, int mode,
1.25 ratchov 1009: int pmax, int rmax)
1.1 ratchov 1010: {
1011: d->reqmode |= mode & MODE_AUDIOMASK;
1012: if (mode & MODE_PLAY) {
1013: if (d->reqpchan < pmax + 1)
1014: d->reqpchan = pmax + 1;
1015: }
1016: if (mode & MODE_REC) {
1017: if (d->reqrchan < rmax + 1)
1018: d->reqrchan = rmax + 1;
1019: }
1020: }
1021:
1022: /*
1023: * Open the device with the dev_reqxxx capabilities. Setup a mixer, demuxer,
1024: * monitor, midi control, and any necessary conversions.
1.91 edd 1025: *
1026: * Note that record and play buffers are always allocated, even if the
1027: * underlying device doesn't support both modes.
1.1 ratchov 1028: */
1029: int
1.59 ratchov 1030: dev_allocbufs(struct dev *d)
1.1 ratchov 1031: {
1.91 edd 1032: /*
1033: * Create record buffer.
1034: */
1035:
1036: /* Create device <-> demuxer buffer */
1037: d->rbuf = xmalloc(d->round * d->rchan * sizeof(adata_t));
1038:
1039: /* Insert a converter, if needed. */
1040: if (!aparams_native(&d->par)) {
1041: dec_init(&d->dec, &d->par, d->rchan);
1042: d->decbuf = xmalloc(d->round * d->rchan * d->par.bps);
1043: } else
1044: d->decbuf = NULL;
1045:
1046: /*
1047: * Create play buffer
1048: */
1049:
1050: /* Create device <-> mixer buffer */
1051: d->poffs = 0;
1052: d->psize = d->bufsz + d->round;
1053: d->pbuf = xmalloc(d->psize * d->pchan * sizeof(adata_t));
1054: d->mode |= MODE_MON;
1055:
1056: /* Append a converter, if needed. */
1057: if (!aparams_native(&d->par)) {
1058: enc_init(&d->enc, &d->par, d->pchan);
1059: d->encbuf = xmalloc(d->round * d->pchan * d->par.bps);
1060: } else
1061: d->encbuf = NULL;
1.1 ratchov 1062:
1.91 edd 1063: /*
1064: * Initially fill the record buffer with zeroed samples. This ensures
1065: * that when a client records from a play-only device the client just
1066: * gets silence.
1067: */
1068: memset(d->rbuf, 0, d->round * d->rchan * sizeof(adata_t));
1.1 ratchov 1069:
1070: if (log_level >= 2) {
1071: dev_log(d);
1072: log_puts(": ");
1073: log_putu(d->rate);
1074: log_puts("Hz, ");
1075: aparams_log(&d->par);
1076: if (d->mode & MODE_PLAY) {
1077: log_puts(", play 0:");
1078: log_puti(d->pchan - 1);
1079: }
1080: if (d->mode & MODE_REC) {
1081: log_puts(", rec 0:");
1082: log_puti(d->rchan - 1);
1083: }
1084: log_puts(", ");
1085: log_putu(d->bufsz / d->round);
1086: log_puts(" blocks of ");
1087: log_putu(d->round);
1.94 ratchov 1088: log_puts(" frames");
1089: if (d == mtc_array[0].dev)
1090: log_puts(", mtc");
1091: log_puts("\n");
1.1 ratchov 1092: }
1.57 ratchov 1093: return 1;
1094: }
1095:
1096: /*
1097: * Reset parameters and open the device.
1098: */
1099: int
1100: dev_open(struct dev *d)
1101: {
1.64 ratchov 1102: char name[CTL_NAMEMAX];
1.75 ratchov 1103: struct dev_alt *a;
1.64 ratchov 1104:
1.57 ratchov 1105: d->mode = d->reqmode;
1106: d->round = d->reqround;
1107: d->bufsz = d->reqbufsz;
1108: d->rate = d->reqrate;
1109: d->pchan = d->reqpchan;
1110: d->rchan = d->reqrchan;
1111: d->par = d->reqpar;
1112: if (d->pchan == 0)
1113: d->pchan = 2;
1114: if (d->rchan == 0)
1115: d->rchan = 2;
1.59 ratchov 1116: if (!dev_sio_open(d)) {
1117: if (log_level >= 1) {
1118: dev_log(d);
1119: log_puts(": failed to open audio device\n");
1120: }
1121: return 0;
1122: }
1123: if (!dev_allocbufs(d))
1.57 ratchov 1124: return 0;
1.64 ratchov 1125:
1.77 ratchov 1126: /* if there are multiple alt devs, add server.device knob */
1127: if (d->alt_list->next != NULL) {
1128: for (a = d->alt_list; a != NULL; a = a->next) {
1129: snprintf(name, sizeof(name), "%d", a->idx);
1.92 ratchov 1130: ctl_new(CTL_DEV_ALT, d, &a->idx,
1131: CTL_SEL, d->name, "server", -1, "device",
1.77 ratchov 1132: name, -1, 1, a->idx == d->alt_num);
1133: }
1.75 ratchov 1134: }
1135:
1.59 ratchov 1136: d->pstate = DEV_INIT;
1.1 ratchov 1137: return 1;
1138: }
1139:
1140: /*
1.72 ratchov 1141: * Force all slots to exit and close device, called after an error
1.55 ratchov 1142: */
1143: void
1.72 ratchov 1144: dev_abort(struct dev *d)
1.55 ratchov 1145: {
1146: int i;
1147: struct slot *s;
1.64 ratchov 1148: struct ctlslot *c;
1.93 ratchov 1149: struct opt *o;
1.55 ratchov 1150:
1.84 ratchov 1151: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.89 ratchov 1152: if (s->opt == NULL || s->opt->dev != d)
1.84 ratchov 1153: continue;
1.89 ratchov 1154: if (s->ops) {
1.55 ratchov 1155: s->ops->exit(s->arg);
1.89 ratchov 1156: s->ops = NULL;
1157: }
1.55 ratchov 1158: }
1159: d->slot_list = NULL;
1.64 ratchov 1160:
1.95 ratchov 1161: for (c = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, c++) {
1.90 ratchov 1162: if (c->ops == NULL)
1163: continue;
1.88 ratchov 1164: if (c->opt->dev != d)
1.85 ratchov 1165: continue;
1.90 ratchov 1166: c->ops->exit(c->arg);
1167: c->ops = NULL;
1.64 ratchov 1168: }
1.83 ratchov 1169:
1.93 ratchov 1170: for (o = opt_list; o != NULL; o = o->next) {
1171: if (o->dev != d)
1172: continue;
1173: midi_abort(o->midi);
1174: }
1.72 ratchov 1175:
1176: if (d->pstate != DEV_CFG)
1177: dev_close(d);
1.55 ratchov 1178: }
1179:
1180: /*
1.1 ratchov 1181: * force the device to go in DEV_CFG state, the caller is supposed to
1182: * ensure buffers are drained
1183: */
1184: void
1.59 ratchov 1185: dev_freebufs(struct dev *d)
1.1 ratchov 1186: {
1187: #ifdef DEBUG
1188: if (log_level >= 3) {
1189: dev_log(d);
1190: log_puts(": closing\n");
1191: }
1192: #endif
1193: if (d->mode & MODE_PLAY) {
1194: if (d->encbuf != NULL)
1195: xfree(d->encbuf);
1196: xfree(d->pbuf);
1197: }
1198: if (d->mode & MODE_REC) {
1199: if (d->decbuf != NULL)
1200: xfree(d->decbuf);
1201: xfree(d->rbuf);
1202: }
1.58 ratchov 1203: }
1204:
1205: /*
1206: * Close the device and exit all slots
1207: */
1208: void
1209: dev_close(struct dev *d)
1210: {
1.92 ratchov 1211: struct dev_alt *a;
1212: unsigned int idx;
1.64 ratchov 1213:
1.59 ratchov 1214: d->pstate = DEV_CFG;
1215: dev_sio_close(d);
1216: dev_freebufs(d);
1.64 ratchov 1217:
1.92 ratchov 1218: if (d->master_enabled) {
1219: d->master_enabled = 0;
1220: ctl_del(CTL_DEV_MASTER, d, NULL);
1.64 ratchov 1221: }
1.92 ratchov 1222: for (idx = 0, a = d->alt_list; a != NULL; idx++, a = a->next)
1223: ctl_del(CTL_DEV_ALT, d, &idx);
1.1 ratchov 1224: }
1225:
1.62 ratchov 1226: /*
1227: * Close the device, but attempt to migrate everything to a new sndio
1228: * device.
1229: */
1230: int
1231: dev_reopen(struct dev *d)
1232: {
1.94 ratchov 1233: struct mtc *mtc;
1.62 ratchov 1234: struct slot *s;
1235: long long pos;
1236: unsigned int pstate;
1237: int delta;
1238:
1239: /* not opened */
1240: if (d->pstate == DEV_CFG)
1241: return 1;
1242:
1243: /* save state */
1244: delta = d->delta;
1245: pstate = d->pstate;
1246:
1247: if (!dev_sio_reopen(d))
1248: return 0;
1249:
1250: /* reopen returns a stopped device */
1251: d->pstate = DEV_INIT;
1252:
1253: /* reallocate new buffers, with new parameters */
1254: dev_freebufs(d);
1255: dev_allocbufs(d);
1256:
1257: /*
1258: * adjust time positions, make anything go back delta ticks, so
1259: * that the new device can start at zero
1260: */
1261: for (s = d->slot_list; s != NULL; s = s->next) {
1262: pos = (long long)s->delta * d->round + s->delta_rem;
1263: pos -= (long long)delta * s->round;
1264: s->delta_rem = pos % (int)d->round;
1265: s->delta = pos / (int)d->round;
1266: if (log_level >= 3) {
1267: slot_log(s);
1268: log_puts(": adjusted: delta -> ");
1269: log_puti(s->delta);
1270: log_puts(", delta_rem -> ");
1271: log_puti(s->delta_rem);
1272: log_puts("\n");
1273: }
1274:
1275: /* reinitilize the format conversion chain */
1276: slot_initconv(s);
1277: }
1.94 ratchov 1278: mtc = &mtc_array[0];
1279: if (mtc->dev == d && mtc->tstate == MTC_RUN) {
1280: mtc->delta -= delta * MTC_SEC;
1.62 ratchov 1281: if (log_level >= 2) {
1.94 ratchov 1282: dev_log(mtc->dev);
1.62 ratchov 1283: log_puts(": adjusted mtc: delta ->");
1.94 ratchov 1284: log_puti(mtc->delta);
1.62 ratchov 1285: log_puts("\n");
1286: }
1287: }
1288:
1.71 ratchov 1289: /* remove old controls and add new ones */
1290: dev_sioctl_close(d);
1.64 ratchov 1291: dev_sioctl_open(d);
1292:
1.62 ratchov 1293: /* start the device if needed */
1294: if (pstate == DEV_RUN)
1295: dev_wakeup(d);
1296:
1297: return 1;
1298: }
1299:
1.1 ratchov 1300: int
1301: dev_ref(struct dev *d)
1302: {
1303: #ifdef DEBUG
1304: if (log_level >= 3) {
1305: dev_log(d);
1306: log_puts(": device requested\n");
1307: }
1308: #endif
1309: if (d->pstate == DEV_CFG && !dev_open(d))
1310: return 0;
1311: d->refcnt++;
1312: return 1;
1313: }
1314:
1315: void
1316: dev_unref(struct dev *d)
1317: {
1318: #ifdef DEBUG
1319: if (log_level >= 3) {
1320: dev_log(d);
1321: log_puts(": device released\n");
1322: }
1323: #endif
1324: d->refcnt--;
1325: if (d->refcnt == 0 && d->pstate == DEV_INIT)
1326: dev_close(d);
1327: }
1328:
1329: /*
1330: * initialize the device with the current parameters
1331: */
1332: int
1333: dev_init(struct dev *d)
1334: {
1335: if ((d->reqmode & MODE_AUDIOMASK) == 0) {
1336: #ifdef DEBUG
1337: dev_log(d);
1338: log_puts(": has no streams\n");
1339: #endif
1340: return 0;
1341: }
1342: if (d->hold && !dev_ref(d))
1343: return 0;
1344: return 1;
1345: }
1346:
1347: /*
1348: * Unless the device is already in process of closing, request it to close
1349: */
1350: void
1351: dev_done(struct dev *d)
1352: {
1353: #ifdef DEBUG
1354: if (log_level >= 3) {
1355: dev_log(d);
1356: log_puts(": draining\n");
1357: }
1358: #endif
1.94 ratchov 1359: if (mtc_array[0].dev == d && mtc_array[0].tstate != MTC_STOP)
1360: mtc_stop(&mtc_array[0]);
1.1 ratchov 1361: if (d->hold)
1362: dev_unref(d);
1363: }
1364:
1365: struct dev *
1366: dev_bynum(int num)
1367: {
1368: struct dev *d;
1369:
1370: for (d = dev_list; d != NULL; d = d->next) {
1.19 ratchov 1371: if (d->num == num)
1.1 ratchov 1372: return d;
1373: }
1374: return NULL;
1375: }
1376:
1377: /*
1378: * Free the device
1379: */
1380: void
1381: dev_del(struct dev *d)
1382: {
1383: struct dev **p;
1.73 ratchov 1384: struct dev_alt *a;
1.1 ratchov 1385:
1386: #ifdef DEBUG
1387: if (log_level >= 3) {
1388: dev_log(d);
1389: log_puts(": deleting\n");
1390: }
1391: #endif
1392: if (d->pstate != DEV_CFG)
1393: dev_close(d);
1394: for (p = &dev_list; *p != d; p = &(*p)->next) {
1395: #ifdef DEBUG
1396: if (*p == NULL) {
1397: dev_log(d);
1398: log_puts(": device to delete not on the list\n");
1399: panic();
1400: }
1401: #endif
1402: }
1403: *p = d->next;
1.73 ratchov 1404: while ((a = d->alt_list) != NULL) {
1405: d->alt_list = a->next;
1406: xfree(a);
1407: }
1.1 ratchov 1408: xfree(d);
1409: }
1410:
1411: unsigned int
1412: dev_roundof(struct dev *d, unsigned int newrate)
1413: {
1414: return (d->round * newrate + d->rate / 2) / d->rate;
1415: }
1416:
1417: /*
1418: * If the device is paused, then resume it.
1419: */
1420: void
1421: dev_wakeup(struct dev *d)
1422: {
1423: if (d->pstate == DEV_INIT) {
1424: if (log_level >= 2) {
1425: dev_log(d);
1426: log_puts(": device started\n");
1427: }
1428: if (d->mode & MODE_PLAY) {
1429: d->prime = d->bufsz;
1430: } else {
1431: d->prime = 0;
1432: }
1.16 ratchov 1433: d->poffs = 0;
1.12 ratchov 1434:
1.23 ratchov 1435: /*
1.16 ratchov 1436: * empty cycles don't increment delta, so it's ok to
1437: * start at 0
1438: **/
1.23 ratchov 1439: d->delta = 0;
1.12 ratchov 1440:
1.1 ratchov 1441: d->pstate = DEV_RUN;
1442: dev_sio_start(d);
1443: }
1444: }
1445:
1446: /*
1447: * check that all clients controlled by MMC are ready to start, if so,
1448: * attach them all at the same position
1449: */
1450: void
1.94 ratchov 1451: mtc_trigger(struct mtc *mtc)
1.1 ratchov 1452: {
1453: int i;
1454: struct slot *s;
1455:
1.94 ratchov 1456: if (mtc->tstate != MTC_START) {
1.1 ratchov 1457: if (log_level >= 2) {
1.94 ratchov 1458: dev_log(mtc->dev);
1.1 ratchov 1459: log_puts(": not started by mmc yet, waiting...\n");
1460: }
1461: return;
1462: }
1.84 ratchov 1463:
1464: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.94 ratchov 1465: if (s->opt == NULL || s->opt->mtc != mtc)
1.1 ratchov 1466: continue;
1.46 ratchov 1467: if (s->pstate != SLOT_READY) {
1.1 ratchov 1468: #ifdef DEBUG
1469: if (log_level >= 3) {
1470: slot_log(s);
1471: log_puts(": not ready, start delayed\n");
1472: }
1473: #endif
1474: return;
1475: }
1476: }
1.94 ratchov 1477: if (!dev_ref(mtc->dev))
1.1 ratchov 1478: return;
1.84 ratchov 1479:
1480: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.94 ratchov 1481: if (s->opt == NULL || s->opt->mtc != mtc)
1.1 ratchov 1482: continue;
1.46 ratchov 1483: slot_attach(s);
1.79 ratchov 1484: s->pstate = SLOT_RUN;
1.1 ratchov 1485: }
1.94 ratchov 1486: mtc->tstate = MTC_RUN;
1487: mtc_midi_full(mtc);
1488: dev_wakeup(mtc->dev);
1.1 ratchov 1489: }
1490:
1491: /*
1492: * start all slots simultaneously
1493: */
1494: void
1.94 ratchov 1495: mtc_start(struct mtc *mtc)
1.1 ratchov 1496: {
1.94 ratchov 1497: if (mtc->tstate == MTC_STOP) {
1498: mtc->tstate = MTC_START;
1499: mtc_trigger(mtc);
1.1 ratchov 1500: #ifdef DEBUG
1501: } else {
1502: if (log_level >= 3) {
1.94 ratchov 1503: dev_log(mtc->dev);
1.1 ratchov 1504: log_puts(": ignoring mmc start\n");
1505: }
1506: #endif
1507: }
1508: }
1509:
1510: /*
1511: * stop all slots simultaneously
1512: */
1513: void
1.94 ratchov 1514: mtc_stop(struct mtc *mtc)
1.1 ratchov 1515: {
1.94 ratchov 1516: switch (mtc->tstate) {
1517: case MTC_START:
1518: mtc->tstate = MTC_STOP;
1.1 ratchov 1519: return;
1.94 ratchov 1520: case MTC_RUN:
1521: mtc->tstate = MTC_STOP;
1522: dev_unref(mtc->dev);
1.1 ratchov 1523: break;
1524: default:
1525: #ifdef DEBUG
1526: if (log_level >= 3) {
1.94 ratchov 1527: dev_log(mtc->dev);
1.1 ratchov 1528: log_puts(": ignored mmc stop\n");
1529: }
1530: #endif
1531: return;
1532: }
1533: }
1534:
1535: /*
1536: * relocate all slots simultaneously
1537: */
1538: void
1.94 ratchov 1539: mtc_loc(struct mtc *mtc, unsigned int origin)
1.1 ratchov 1540: {
1541: if (log_level >= 2) {
1.94 ratchov 1542: dev_log(mtc->dev);
1.1 ratchov 1543: log_puts(": relocated to ");
1544: log_putu(origin);
1545: log_puts("\n");
1546: }
1.94 ratchov 1547: if (mtc->tstate == MTC_RUN)
1548: mtc_stop(mtc);
1549: mtc->origin = origin;
1550: if (mtc->tstate == MTC_RUN)
1551: mtc_start(mtc);
1.1 ratchov 1552: }
1553:
1.35 ratchov 1554: /*
1555: * allocate buffers & conversion chain
1556: */
1557: void
1.60 ratchov 1558: slot_initconv(struct slot *s)
1.35 ratchov 1559: {
1.63 ratchov 1560: unsigned int dev_nch;
1.89 ratchov 1561: struct dev *d = s->opt->dev;
1.35 ratchov 1562:
1563: if (s->mode & MODE_PLAY) {
1564: cmap_init(&s->mix.cmap,
1.42 ratchov 1565: s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1566: s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1.35 ratchov 1567: 0, d->pchan - 1,
1.40 ratchov 1568: s->opt->pmin, s->opt->pmax);
1.100 ratchov 1569: s->mix.decbuf = NULL;
1570: s->mix.resampbuf = NULL;
1.35 ratchov 1571: if (!aparams_native(&s->par)) {
1.42 ratchov 1572: dec_init(&s->mix.dec, &s->par, s->mix.nch);
1.100 ratchov 1573: s->mix.decbuf =
1574: xmalloc(s->round * s->mix.nch * sizeof(adata_t));
1.35 ratchov 1575: }
1576: if (s->rate != d->rate) {
1577: resamp_init(&s->mix.resamp, s->round, d->round,
1.42 ratchov 1578: s->mix.nch);
1.100 ratchov 1579: s->mix.resampbuf =
1580: xmalloc(d->round * s->mix.nch * sizeof(adata_t));
1.35 ratchov 1581: }
1.61 ratchov 1582: s->mix.join = 1;
1583: s->mix.expand = 1;
1.63 ratchov 1584: if (s->opt->dup && s->mix.cmap.nch > 0) {
1585: dev_nch = d->pchan < (s->opt->pmax + 1) ?
1586: d->pchan - s->opt->pmin :
1587: s->opt->pmax - s->opt->pmin + 1;
1588: if (dev_nch > s->mix.nch)
1589: s->mix.expand = dev_nch / s->mix.nch;
1590: else if (s->mix.nch > dev_nch)
1591: s->mix.join = s->mix.nch / dev_nch;
1.61 ratchov 1592: }
1.35 ratchov 1593: }
1594:
1595: if (s->mode & MODE_RECMASK) {
1.102 ! ratchov 1596: unsigned int outchan = (s->opt->mode & MODE_MON) ?
1.63 ratchov 1597: d->pchan : d->rchan;
1598:
1.100 ratchov 1599: s->sub.encbuf = NULL;
1600: s->sub.resampbuf = NULL;
1.35 ratchov 1601: cmap_init(&s->sub.cmap,
1.63 ratchov 1602: 0, outchan - 1,
1.40 ratchov 1603: s->opt->rmin, s->opt->rmax,
1.42 ratchov 1604: s->opt->rmin, s->opt->rmin + s->sub.nch - 1,
1605: s->opt->rmin, s->opt->rmin + s->sub.nch - 1);
1.35 ratchov 1606: if (s->rate != d->rate) {
1607: resamp_init(&s->sub.resamp, d->round, s->round,
1.42 ratchov 1608: s->sub.nch);
1.100 ratchov 1609: s->sub.resampbuf =
1610: xmalloc(d->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1611: }
1612: if (!aparams_native(&s->par)) {
1.42 ratchov 1613: enc_init(&s->sub.enc, &s->par, s->sub.nch);
1.100 ratchov 1614: s->sub.encbuf =
1615: xmalloc(s->round * s->sub.nch * sizeof(adata_t));
1.61 ratchov 1616: }
1617: s->sub.join = 1;
1618: s->sub.expand = 1;
1.63 ratchov 1619: if (s->opt->dup && s->sub.cmap.nch > 0) {
1620: dev_nch = outchan < (s->opt->rmax + 1) ?
1621: outchan - s->opt->rmin :
1622: s->opt->rmax - s->opt->rmin + 1;
1623: if (dev_nch > s->sub.nch)
1624: s->sub.join = dev_nch / s->sub.nch;
1625: else if (s->sub.nch > dev_nch)
1626: s->sub.expand = s->sub.nch / dev_nch;
1.35 ratchov 1627: }
1628:
1629: /*
1630: * cmap_copy() doesn't write samples in all channels,
1631: * for instance when mono->stereo conversion is
1632: * disabled. So we have to prefill cmap_copy() output
1633: * with silence.
1634: */
1635: if (s->sub.resampbuf) {
1636: memset(s->sub.resampbuf, 0,
1.42 ratchov 1637: d->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1638: } else if (s->sub.encbuf) {
1639: memset(s->sub.encbuf, 0,
1.42 ratchov 1640: s->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1641: } else {
1642: memset(s->sub.buf.data, 0,
1.42 ratchov 1643: s->appbufsz * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1644: }
1645: }
1.60 ratchov 1646: }
1647:
1648: /*
1649: * allocate buffers & conversion chain
1650: */
1651: void
1652: slot_allocbufs(struct slot *s)
1653: {
1654: if (s->mode & MODE_PLAY) {
1655: s->mix.bpf = s->par.bps * s->mix.nch;
1656: abuf_init(&s->mix.buf, s->appbufsz * s->mix.bpf);
1657: }
1658:
1659: if (s->mode & MODE_RECMASK) {
1660: s->sub.bpf = s->par.bps * s->sub.nch;
1661: abuf_init(&s->sub.buf, s->appbufsz * s->sub.bpf);
1662: }
1663:
1.35 ratchov 1664: #ifdef DEBUG
1665: if (log_level >= 3) {
1666: slot_log(s);
1667: log_puts(": allocated ");
1668: log_putu(s->appbufsz);
1669: log_puts("/");
1670: log_putu(SLOT_BUFSZ(s));
1671: log_puts(" fr buffers\n");
1672: }
1673: #endif
1674: }
1675:
1676: /*
1677: * free buffers & conversion chain
1678: */
1679: void
1680: slot_freebufs(struct slot *s)
1681: {
1682: if (s->mode & MODE_RECMASK) {
1683: abuf_done(&s->sub.buf);
1684: }
1685:
1686: if (s->mode & MODE_PLAY) {
1687: abuf_done(&s->mix.buf);
1688: }
1689: }
1690:
1.1 ratchov 1691: /*
1692: * allocate a new slot and register the given call-backs
1693: */
1694: struct slot *
1.89 ratchov 1695: slot_new(struct opt *opt, unsigned int id, char *who,
1.37 ratchov 1696: struct slotops *ops, void *arg, int mode)
1.1 ratchov 1697: {
1698: char *p;
1699: char name[SLOT_NAMEMAX];
1.99 ratchov 1700: char ctl_name[CTL_NAMEMAX];
1.52 ratchov 1701: unsigned int i, ser, bestser, bestidx;
1702: struct slot *unit[DEV_NSLOT];
1.1 ratchov 1703: struct slot *s;
1704:
1705: /*
1.27 ratchov 1706: * create a ``valid'' control name (lowcase, remove [^a-z], truncate)
1.1 ratchov 1707: */
1708: for (i = 0, p = who; ; p++) {
1709: if (i == SLOT_NAMEMAX - 1 || *p == '\0') {
1710: name[i] = '\0';
1711: break;
1712: } else if (*p >= 'A' && *p <= 'Z') {
1713: name[i++] = *p + 'a' - 'A';
1714: } else if (*p >= 'a' && *p <= 'z')
1715: name[i++] = *p;
1716: }
1717: if (i == 0)
1718: strlcpy(name, "noname", SLOT_NAMEMAX);
1719:
1720: /*
1.52 ratchov 1721: * build a unit-to-slot map for this name
1.1 ratchov 1722: */
1.52 ratchov 1723: for (i = 0; i < DEV_NSLOT; i++)
1724: unit[i] = NULL;
1.84 ratchov 1725: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.1 ratchov 1726: if (strcmp(s->name, name) == 0)
1.52 ratchov 1727: unit[s->unit] = s;
1.1 ratchov 1728: }
1729:
1730: /*
1.54 ratchov 1731: * find the free slot with the least unit number and same id
1732: */
1733: for (i = 0; i < DEV_NSLOT; i++) {
1734: s = unit[i];
1735: if (s != NULL && s->ops == NULL && s->id == id)
1736: goto found;
1737: }
1738:
1739: /*
1.52 ratchov 1740: * find the free slot with the least unit number
1.1 ratchov 1741: */
1.52 ratchov 1742: for (i = 0; i < DEV_NSLOT; i++) {
1743: s = unit[i];
1.54 ratchov 1744: if (s != NULL && s->ops == NULL) {
1745: s->id = id;
1.1 ratchov 1746: goto found;
1.54 ratchov 1747: }
1.1 ratchov 1748: }
1749:
1750: /*
1.18 ratchov 1751: * couldn't find a matching slot, pick oldest free slot
1.1 ratchov 1752: * and set its name/unit
1753: */
1754: bestser = 0;
1755: bestidx = DEV_NSLOT;
1.84 ratchov 1756: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.1 ratchov 1757: if (s->ops != NULL)
1758: continue;
1.84 ratchov 1759: ser = slot_serial - s->serial;
1.1 ratchov 1760: if (ser > bestser) {
1761: bestser = ser;
1762: bestidx = i;
1763: }
1764: }
1.98 ratchov 1765:
1766: if (bestidx == DEV_NSLOT) {
1767: if (log_level >= 1) {
1768: log_puts(name);
1769: log_puts(": out of sub-device slots\n");
1770: }
1771: return NULL;
1.1 ratchov 1772: }
1.53 ratchov 1773:
1.98 ratchov 1774: s = slot_array + bestidx;
1.99 ratchov 1775: ctl_del(CTL_SLOT_LEVEL, s, NULL);
1.98 ratchov 1776: s->vol = MIDI_MAXCTL;
1777: strlcpy(s->name, name, SLOT_NAMEMAX);
1778: s->serial = slot_serial++;
1779: for (i = 0; unit[i] != NULL; i++)
1780: ; /* nothing */
1781: s->unit = i;
1782: s->id = id;
1.99 ratchov 1783: s->opt = opt;
1784: slot_ctlname(s, ctl_name, CTL_NAMEMAX);
1785: ctl_new(CTL_SLOT_LEVEL, s, NULL,
1786: CTL_NUM, "app", ctl_name, -1, "level",
1787: NULL, -1, 127, s->vol);
1.1 ratchov 1788:
1789: found:
1.89 ratchov 1790: if (!dev_ref(opt->dev))
1.1 ratchov 1791: return NULL;
1.37 ratchov 1792: s->opt = opt;
1.31 ratchov 1793: s->ops = ops;
1794: s->arg = arg;
1795: s->pstate = SLOT_INIT;
1.1 ratchov 1796: s->mode = mode;
1.6 ratchov 1797: aparams_init(&s->par);
1.41 ratchov 1798: if (s->mode & MODE_PLAY)
1.42 ratchov 1799: s->mix.nch = s->opt->pmax - s->opt->pmin + 1;
1.41 ratchov 1800: if (s->mode & MODE_RECMASK)
1.42 ratchov 1801: s->sub.nch = s->opt->rmax - s->opt->rmin + 1;
1.94 ratchov 1802: s->xrun = s->opt->mtc != NULL ? XRUN_SYNC : XRUN_IGNORE;
1.89 ratchov 1803: s->appbufsz = s->opt->dev->bufsz;
1804: s->round = s->opt->dev->round;
1805: s->rate = s->opt->dev->rate;
1806: dev_midi_slotdesc(s->opt->dev, s);
1807: dev_midi_vol(s->opt->dev, s);
1.43 ratchov 1808: #ifdef DEBUG
1809: if (log_level >= 3) {
1810: slot_log(s);
1811: log_puts(": using ");
1.89 ratchov 1812: dev_log(s->opt->dev);
1.43 ratchov 1813: log_puts(".");
1.89 ratchov 1814: log_puts(s->opt->name);
1.43 ratchov 1815: log_puts(", mode = ");
1816: log_putx(mode);
1817: log_puts("\n");
1818: }
1819: #endif
1.1 ratchov 1820: return s;
1821: }
1822:
1823: /*
1824: * release the given slot
1825: */
1826: void
1827: slot_del(struct slot *s)
1828: {
1829: s->arg = s;
1830: s->ops = &zomb_slotops;
1831: switch (s->pstate) {
1832: case SLOT_INIT:
1833: s->ops = NULL;
1834: break;
1835: case SLOT_START:
1836: case SLOT_READY:
1837: case SLOT_RUN:
1838: case SLOT_STOP:
1.82 ratchov 1839: slot_stop(s, 0);
1.1 ratchov 1840: break;
1841: }
1.89 ratchov 1842: dev_unref(s->opt->dev);
1.1 ratchov 1843: }
1844:
1845: /*
1846: * change the slot play volume; called either by the slot or by MIDI
1847: */
1848: void
1849: slot_setvol(struct slot *s, unsigned int vol)
1850: {
1851: #ifdef DEBUG
1852: if (log_level >= 3) {
1853: slot_log(s);
1854: log_puts(": setting volume ");
1855: log_putu(vol);
1856: log_puts("\n");
1857: }
1858: #endif
1859: s->vol = vol;
1860: s->mix.vol = MIDI_TO_ADATA(s->vol);
1861: }
1862:
1863: /*
1864: * attach the slot to the device (ie start playing & recording
1865: */
1866: void
1867: slot_attach(struct slot *s)
1868: {
1.89 ratchov 1869: struct dev *d = s->opt->dev;
1.12 ratchov 1870: long long pos;
1.102 ! ratchov 1871:
! 1872: if (((s->mode & MODE_PLAY) && !(s->opt->mode & MODE_PLAY)) ||
! 1873: ((s->mode & MODE_RECMASK) && !(s->opt->mode & MODE_RECMASK))) {
! 1874: if (log_level >= 1) {
! 1875: slot_log(s);
! 1876: log_puts(" at ");
! 1877: log_puts(s->opt->name);
! 1878: log_puts(": mode not allowed on this sub-device\n");
! 1879: }
! 1880: }
1.1 ratchov 1881:
1882: /*
1.100 ratchov 1883: * setup converions layer
1884: */
1885: slot_initconv(s);
1886:
1887: /*
1.1 ratchov 1888: * start the device if not started
1889: */
1890: dev_wakeup(d);
1.23 ratchov 1891:
1.1 ratchov 1892: /*
1.12 ratchov 1893: * adjust initial clock
1894: */
1.79 ratchov 1895: pos = s->delta_rem +
1896: (long long)s->delta * d->round +
1897: (long long)d->delta * s->round;
1898: s->delta = pos / (int)d->round;
1.12 ratchov 1899: s->delta_rem = pos % d->round;
1.79 ratchov 1900: if (s->delta_rem < 0) {
1901: s->delta_rem += d->round;
1902: s->delta--;
1903: }
1.12 ratchov 1904:
1.1 ratchov 1905: #ifdef DEBUG
1.17 ratchov 1906: if (log_level >= 2) {
1.1 ratchov 1907: slot_log(s);
1908: log_puts(": attached at ");
1.79 ratchov 1909: log_puti(s->delta);
1910: log_puts(" + ");
1911: log_puti(s->delta_rem);
1912: log_puts("/");
1913: log_puti(s->round);
1.1 ratchov 1914: log_puts("\n");
1915: }
1916: #endif
1917:
1918: /*
1919: * We dont check whether the device is dying,
1920: * because dev_xxx() functions are supposed to
1921: * work (i.e., not to crash)
1922: */
1.91 edd 1923:
1.1 ratchov 1924: s->next = d->slot_list;
1925: d->slot_list = s;
1926: if (s->mode & MODE_PLAY) {
1927: s->mix.vol = MIDI_TO_ADATA(s->vol);
1928: dev_mix_adjvol(d);
1929: }
1930: }
1931:
1932: /*
1933: * if MMC is enabled, and try to attach all slots synchronously, else
1934: * simply attach the slot
1935: */
1936: void
1937: slot_ready(struct slot *s)
1938: {
1.3 ratchov 1939: /*
1940: * device may be disconnected, and if so we're called from
1941: * slot->ops->exit() on a closed device
1.23 ratchov 1942: */
1.89 ratchov 1943: if (s->opt->dev->pstate == DEV_CFG)
1.3 ratchov 1944: return;
1.94 ratchov 1945: if (s->opt->mtc == NULL) {
1.1 ratchov 1946: slot_attach(s);
1.79 ratchov 1947: s->pstate = SLOT_RUN;
1948: } else
1.94 ratchov 1949: mtc_trigger(s->opt->mtc);
1.1 ratchov 1950: }
1951:
1952: /*
1953: * setup buffers & conversion layers, prepare the slot to receive data
1954: * (for playback) or start (recording).
1955: */
1956: void
1957: slot_start(struct slot *s)
1958: {
1.89 ratchov 1959: struct dev *d = s->opt->dev;
1.1 ratchov 1960: #ifdef DEBUG
1961: if (s->pstate != SLOT_INIT) {
1962: slot_log(s);
1963: log_puts(": slot_start: wrong state\n");
1964: panic();
1965: }
1966: if (s->mode & MODE_PLAY) {
1967: if (log_level >= 3) {
1968: slot_log(s);
1969: log_puts(": playing ");
1970: aparams_log(&s->par);
1971: log_puts(" -> ");
1.81 ratchov 1972: aparams_log(&d->par);
1.1 ratchov 1973: log_puts("\n");
1974: }
1975: }
1976: if (s->mode & MODE_RECMASK) {
1977: if (log_level >= 3) {
1978: slot_log(s);
1979: log_puts(": recording ");
1980: aparams_log(&s->par);
1981: log_puts(" <- ");
1.81 ratchov 1982: aparams_log(&d->par);
1.1 ratchov 1983: log_puts("\n");
1.35 ratchov 1984: }
1.1 ratchov 1985: }
1986: #endif
1.35 ratchov 1987: slot_allocbufs(s);
1.47 ratchov 1988:
1989: if (s->mode & MODE_RECMASK) {
1990: /*
1991: * N-th recorded block is the N-th played block
1992: */
1.101 ratchov 1993: s->sub.prime = d->bufsz / d->round;
1.47 ratchov 1994: }
1995: s->skip = 0;
1996:
1.79 ratchov 1997: /*
1998: * get the current position, the origin is when the first sample
1999: * played and/or recorded
2000: */
1.101 ratchov 2001: s->delta = -(long long)d->bufsz * s->round / d->round;
1.79 ratchov 2002: s->delta_rem = 0;
2003:
1.1 ratchov 2004: if (s->mode & MODE_PLAY) {
2005: s->pstate = SLOT_START;
2006: } else {
2007: s->pstate = SLOT_READY;
2008: slot_ready(s);
2009: }
2010: }
2011:
2012: /*
2013: * stop playback and recording, and free conversion layers
2014: */
2015: void
2016: slot_detach(struct slot *s)
2017: {
2018: struct slot **ps;
1.89 ratchov 2019: struct dev *d = s->opt->dev;
1.79 ratchov 2020: long long pos;
1.1 ratchov 2021:
1.81 ratchov 2022: for (ps = &d->slot_list; *ps != s; ps = &(*ps)->next) {
1.1 ratchov 2023: #ifdef DEBUG
1.28 ratchov 2024: if (*ps == NULL) {
1.1 ratchov 2025: slot_log(s);
2026: log_puts(": can't detach, not on list\n");
2027: panic();
2028: }
2029: #endif
1.23 ratchov 2030: }
1.1 ratchov 2031: *ps = s->next;
1.79 ratchov 2032:
2033: /*
2034: * adjust clock, go back d->delta ticks so that slot_attach()
2035: * could be called with the resulting state
2036: */
2037: pos = s->delta_rem +
2038: (long long)s->delta * d->round -
2039: (long long)d->delta * s->round;
2040: s->delta = pos / (int)d->round;
2041: s->delta_rem = pos % d->round;
2042: if (s->delta_rem < 0) {
2043: s->delta_rem += d->round;
2044: s->delta--;
2045: }
2046:
2047: #ifdef DEBUG
2048: if (log_level >= 2) {
2049: slot_log(s);
2050: log_puts(": detached at ");
2051: log_puti(s->delta);
2052: log_puts(" + ");
2053: log_puti(s->delta_rem);
2054: log_puts("/");
2055: log_puti(d->round);
2056: log_puts("\n");
2057: }
2058: #endif
1.35 ratchov 2059: if (s->mode & MODE_PLAY)
1.81 ratchov 2060: dev_mix_adjvol(d);
1.100 ratchov 2061:
2062: if (s->mode & MODE_RECMASK) {
2063: if (s->sub.encbuf) {
2064: xfree(s->sub.encbuf);
2065: s->sub.encbuf = NULL;
2066: }
2067: if (s->sub.resampbuf) {
2068: xfree(s->sub.resampbuf);
2069: s->sub.resampbuf = NULL;
2070: }
2071: }
2072:
2073: if (s->mode & MODE_PLAY) {
2074: if (s->mix.decbuf) {
2075: xfree(s->mix.decbuf);
2076: s->mix.decbuf = NULL;
2077: }
2078: if (s->mix.resampbuf) {
2079: xfree(s->mix.resampbuf);
2080: s->mix.resampbuf = NULL;
2081: }
2082: }
1.1 ratchov 2083: }
2084:
2085: /*
2086: * put the slot in stopping state (draining play buffers) or
2087: * stop & detach if no data to drain.
2088: */
2089: void
1.82 ratchov 2090: slot_stop(struct slot *s, int drain)
1.1 ratchov 2091: {
2092: #ifdef DEBUG
2093: if (log_level >= 3) {
2094: slot_log(s);
2095: log_puts(": stopping\n");
2096: }
2097: #endif
2098: if (s->pstate == SLOT_START) {
1.33 ratchov 2099: /*
2100: * If in rec-only mode, we're already in the READY or
2101: * RUN states. We're here because the play buffer was
2102: * not full enough, try to start so it's drained.
2103: */
2104: s->pstate = SLOT_READY;
2105: slot_ready(s);
1.1 ratchov 2106: }
1.34 ratchov 2107:
2108: if (s->pstate == SLOT_RUN) {
1.82 ratchov 2109: if ((s->mode & MODE_PLAY) && drain) {
1.34 ratchov 2110: /*
2111: * Don't detach, dev_cycle() will do it for us
2112: * when the buffer is drained.
2113: */
2114: s->pstate = SLOT_STOP;
2115: return;
2116: }
1.82 ratchov 2117: slot_detach(s);
2118: } else if (s->pstate == SLOT_STOP) {
1.34 ratchov 2119: slot_detach(s);
2120: } else {
1.1 ratchov 2121: #ifdef DEBUG
2122: if (log_level >= 3) {
2123: slot_log(s);
2124: log_puts(": not drained (blocked by mmc)\n");
2125: }
2126: #endif
2127: }
1.35 ratchov 2128:
1.34 ratchov 2129: s->pstate = SLOT_INIT;
2130: s->ops->eof(s->arg);
1.35 ratchov 2131: slot_freebufs(s);
1.1 ratchov 2132: }
2133:
1.12 ratchov 2134: void
2135: slot_skip_update(struct slot *s)
2136: {
2137: int skip;
2138:
2139: skip = slot_skip(s);
2140: while (skip > 0) {
2141: #ifdef DEBUG
2142: if (log_level >= 4) {
2143: slot_log(s);
2144: log_puts(": catching skipped block\n");
2145: }
2146: #endif
2147: if (s->mode & MODE_RECMASK)
2148: s->ops->flush(s->arg);
2149: if (s->mode & MODE_PLAY)
2150: s->ops->fill(s->arg);
2151: skip--;
2152: }
2153: }
2154:
1.1 ratchov 2155: /*
2156: * notify the slot that we just wrote in the play buffer, must be called
2157: * after each write
2158: */
2159: void
2160: slot_write(struct slot *s)
2161: {
2162: if (s->pstate == SLOT_START && s->mix.buf.used == s->mix.buf.len) {
2163: #ifdef DEBUG
2164: if (log_level >= 4) {
2165: slot_log(s);
2166: log_puts(": switching to READY state\n");
2167: }
2168: #endif
2169: s->pstate = SLOT_READY;
2170: slot_ready(s);
2171: }
1.12 ratchov 2172: slot_skip_update(s);
1.1 ratchov 2173: }
2174:
2175: /*
2176: * notify the slot that we freed some space in the rec buffer
2177: */
2178: void
2179: slot_read(struct slot *s)
2180: {
1.12 ratchov 2181: slot_skip_update(s);
1.64 ratchov 2182: }
2183:
2184: /*
2185: * allocate at control slot
2186: */
2187: struct ctlslot *
1.88 ratchov 2188: ctlslot_new(struct opt *o, struct ctlops *ops, void *arg)
1.64 ratchov 2189: {
2190: struct ctlslot *s;
2191: struct ctl *c;
2192: int i;
2193:
2194: i = 0;
2195: for (;;) {
2196: if (i == DEV_NCTLSLOT)
2197: return NULL;
1.85 ratchov 2198: s = ctlslot_array + i;
1.64 ratchov 2199: if (s->ops == NULL)
2200: break;
2201: i++;
2202: }
1.88 ratchov 2203: s->opt = o;
1.87 ratchov 2204: s->self = 1 << i;
1.88 ratchov 2205: if (!dev_ref(o->dev))
1.64 ratchov 2206: return NULL;
2207: s->ops = ops;
2208: s->arg = arg;
1.92 ratchov 2209: for (c = ctl_list; c != NULL; c = c->next) {
2210: if (!ctlslot_visible(s, c))
2211: continue;
1.87 ratchov 2212: c->refs_mask |= s->self;
1.92 ratchov 2213: }
1.64 ratchov 2214: return s;
2215: }
2216:
2217: /*
2218: * free control slot
2219: */
2220: void
2221: ctlslot_del(struct ctlslot *s)
2222: {
2223: struct ctl *c, **pc;
2224:
1.92 ratchov 2225: pc = &ctl_list;
1.64 ratchov 2226: while ((c = *pc) != NULL) {
1.87 ratchov 2227: c->refs_mask &= ~s->self;
1.64 ratchov 2228: if (c->refs_mask == 0) {
2229: *pc = c->next;
2230: xfree(c);
2231: } else
2232: pc = &c->next;
2233: }
2234: s->ops = NULL;
1.88 ratchov 2235: dev_unref(s->opt->dev);
1.64 ratchov 2236: }
2237:
1.92 ratchov 2238: int
2239: ctlslot_visible(struct ctlslot *s, struct ctl *c)
2240: {
2241: if (s->opt == NULL)
2242: return 1;
2243: switch (c->scope) {
2244: case CTL_HW:
2245: case CTL_DEV_MASTER:
2246: case CTL_DEV_ALT:
2247: return (s->opt->dev == c->u.any.arg0);
2248: case CTL_SLOT_LEVEL:
2249: return (s->opt->dev == c->u.slot_level.slot->opt->dev);
2250: default:
2251: return 0;
2252: }
2253: }
2254:
2255: struct ctl *
2256: ctlslot_lookup(struct ctlslot *s, int addr)
2257: {
2258: struct ctl *c;
2259:
2260: c = ctl_list;
2261: while (1) {
2262: if (c == NULL)
2263: return NULL;
2264: if (c->type != CTL_NONE && c->addr == addr)
2265: break;
2266: c = c->next;
2267: }
2268: if (!ctlslot_visible(s, c))
2269: return NULL;
2270: return c;
2271: }
2272:
1.64 ratchov 2273: void
2274: ctl_node_log(struct ctl_node *c)
2275: {
2276: log_puts(c->name);
2277: if (c->unit >= 0)
2278: log_putu(c->unit);
2279: }
2280:
2281: void
2282: ctl_log(struct ctl *c)
2283: {
2284: if (c->group[0] != 0) {
2285: log_puts(c->group);
2286: log_puts("/");
2287: }
2288: ctl_node_log(&c->node0);
2289: log_puts(".");
2290: log_puts(c->func);
2291: log_puts("=");
2292: switch (c->type) {
1.67 ratchov 2293: case CTL_NONE:
2294: log_puts("none");
2295: break;
1.64 ratchov 2296: case CTL_NUM:
2297: case CTL_SW:
2298: log_putu(c->curval);
2299: break;
2300: case CTL_VEC:
2301: case CTL_LIST:
1.74 ratchov 2302: case CTL_SEL:
1.64 ratchov 2303: ctl_node_log(&c->node1);
2304: log_puts(":");
2305: log_putu(c->curval);
2306: }
2307: log_puts(" at ");
2308: log_putu(c->addr);
1.92 ratchov 2309: log_puts(" -> ");
2310: switch (c->scope) {
2311: case CTL_HW:
2312: log_puts("hw:");
2313: log_puts(c->u.hw.dev->name);
2314: log_puts("/");
2315: log_putu(c->u.hw.addr);
2316: break;
2317: case CTL_DEV_MASTER:
2318: log_puts("dev_master:");
2319: log_puts(c->u.dev_master.dev->name);
2320: break;
2321: case CTL_DEV_ALT:
2322: log_puts("dev_alt:");
2323: log_puts(c->u.dev_alt.dev->name);
2324: log_putu(c->u.dev_alt.idx);
2325: break;
2326: case CTL_SLOT_LEVEL:
2327: log_puts("slot_level:");
2328: log_puts(c->u.slot_level.slot->name);
2329: log_putu(c->u.slot_level.slot->unit);
2330: break;
2331: default:
2332: log_puts("unknown");
2333: }
2334: }
2335:
2336: int
2337: ctl_setval(struct ctl *c, int val)
2338: {
2339: if (c->curval == val) {
2340: if (log_level >= 3) {
2341: ctl_log(c);
2342: log_puts(": already set\n");
2343: }
2344: return 1;
2345: }
2346: if (val < 0 || val > c->maxval) {
2347: if (log_level >= 3) {
2348: log_putu(val);
2349: log_puts(": ctl val out of bounds\n");
2350: }
2351: return 0;
2352: }
2353:
2354: switch (c->scope) {
2355: case CTL_HW:
2356: if (log_level >= 3) {
2357: ctl_log(c);
2358: log_puts(": marked as dirty\n");
2359: }
2360: c->curval = val;
2361: c->dirty = 1;
2362: return dev_ref(c->u.hw.dev);
2363: case CTL_DEV_MASTER:
2364: if (!c->u.dev_master.dev->master_enabled)
2365: return 1;
2366: dev_master(c->u.dev_master.dev, val);
2367: dev_midi_master(c->u.dev_master.dev);
2368: c->val_mask = ~0U;
2369: c->curval = val;
2370: return 1;
2371: case CTL_DEV_ALT:
2372: dev_setalt (c->u.dev_alt.dev, c->u.dev_alt.idx);
2373: return 1;
2374: case CTL_SLOT_LEVEL:
2375: slot_setvol(c->u.slot_level.slot, val);
2376: // XXX change dev_midi_vol() into slot_midi_vol()
2377: dev_midi_vol(c->u.slot_level.slot->opt->dev, c->u.slot_level.slot);
2378: c->val_mask = ~0U;
2379: c->curval = val;
2380: return 1;
2381: default:
2382: if (log_level >= 2) {
2383: ctl_log(c);
2384: log_puts(": not writable\n");
2385: }
2386: return 1;
2387: }
1.64 ratchov 2388: }
2389:
2390: /*
2391: * add a ctl
2392: */
2393: struct ctl *
1.92 ratchov 2394: ctl_new(int scope, void *arg0, void *arg1,
2395: int type, char *gstr,
2396: char *str0, int unit0, char *func,
2397: char *str1, int unit1, int maxval, int val)
1.64 ratchov 2398: {
2399: struct ctl *c, **pc;
1.92 ratchov 2400: struct ctlslot *s;
2401: int addr;
1.64 ratchov 2402: int i;
2403:
1.92 ratchov 2404: /*
2405: * find the smallest unused addr number and
2406: * the last position in the list
2407: */
2408: addr = 0;
2409: for (pc = &ctl_list; (c = *pc) != NULL; pc = &c->next) {
2410: if (c->addr > addr)
2411: addr = c->addr;
2412: }
2413: addr++;
2414:
1.64 ratchov 2415: c = xmalloc(sizeof(struct ctl));
2416: c->type = type;
2417: strlcpy(c->func, func, CTL_NAMEMAX);
2418: strlcpy(c->group, gstr, CTL_NAMEMAX);
2419: strlcpy(c->node0.name, str0, CTL_NAMEMAX);
2420: c->node0.unit = unit0;
1.74 ratchov 2421: if (c->type == CTL_VEC || c->type == CTL_LIST || c->type == CTL_SEL) {
1.64 ratchov 2422: strlcpy(c->node1.name, str1, CTL_NAMEMAX);
2423: c->node1.unit = unit1;
2424: } else
2425: memset(&c->node1, 0, sizeof(struct ctl_node));
1.92 ratchov 2426: c->scope = scope;
2427: c->u.any.arg0 = arg0;
2428: switch (scope) {
2429: case CTL_HW:
2430: c->u.hw.addr = *(unsigned int *)arg1;
2431: break;
2432: case CTL_DEV_ALT:
2433: c->u.dev_alt.idx = *(unsigned int *)arg1;
2434: break;
2435: default:
2436: c->u.any.arg1 = NULL;
2437: }
1.64 ratchov 2438: c->addr = addr;
2439: c->maxval = maxval;
2440: c->val_mask = ~0;
2441: c->desc_mask = ~0;
2442: c->curval = val;
2443: c->dirty = 0;
1.92 ratchov 2444: c->refs_mask = CTL_DEVMASK;
2445: for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) {
2446: if (s->ops == NULL)
2447: continue;
2448: if (ctlslot_visible(s, c))
1.64 ratchov 2449: c->refs_mask |= 1 << i;
2450: }
1.92 ratchov 2451: c->next = *pc;
1.64 ratchov 2452: *pc = c;
2453: #ifdef DEBUG
1.92 ratchov 2454: if (log_level >= 2) {
1.64 ratchov 2455: ctl_log(c);
1.92 ratchov 2456: log_puts(": added\n");
1.64 ratchov 2457: }
2458: #endif
2459: return c;
2460: }
2461:
2462: void
1.92 ratchov 2463: ctl_update(struct ctl *c)
2464: {
2465: struct ctlslot *s;
2466: unsigned int refs_mask;
2467: int i;
2468:
2469: for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) {
2470: if (s->ops == NULL)
2471: continue;
2472: refs_mask = ctlslot_visible(s, c) ? s->self : 0;
2473:
2474: /* nothing to do if no visibility change */
2475: if (((c->refs_mask & s->self) ^ refs_mask) == 0)
2476: continue;
2477: /* if control becomes visble */
2478: if (refs_mask)
2479: c->refs_mask |= s->self;
2480: /* if control is hidden */
2481: c->desc_mask |= s->self;
2482: }
2483: }
2484:
2485: int
2486: ctl_match(struct ctl *c, int scope, void *arg0, void *arg1)
2487: {
2488: if (c->type == CTL_NONE || c->scope != scope || c->u.any.arg0 != arg0)
2489: return 0;
2490: if (arg0 != NULL && c->u.any.arg0 != arg0)
2491: return 0;
2492: switch (scope) {
2493: case CTL_HW:
2494: if (arg1 != NULL && c->u.hw.addr != *(unsigned int *)arg1)
2495: return 0;
2496: break;
2497: case CTL_DEV_ALT:
2498: if (arg1 != NULL && c->u.dev_alt.idx != *(unsigned int *)arg1)
2499: return 0;
2500: break;
2501: }
2502: return 1;
2503: }
2504:
2505: struct ctl *
2506: ctl_find(int scope, void *arg0, void *arg1)
2507: {
2508: struct ctl *c;
2509:
2510: for (c = ctl_list; c != NULL; c = c->next) {
2511: if (ctl_match(c, scope, arg0, arg1))
2512: return c;
2513: }
2514: return NULL;
2515: }
2516:
2517: int
2518: ctl_onval(int scope, void *arg0, void *arg1, int val)
2519: {
2520: struct ctl *c;
2521:
2522: c = ctl_find(scope, arg0, arg1);
2523: if (c == NULL)
2524: return 0;
2525: c->curval = val;
2526: c->val_mask = ~0U;
2527: return 1;
2528: }
2529:
2530: void
2531: ctl_del(int scope, void *arg0, void *arg1)
1.64 ratchov 2532: {
2533: struct ctl *c, **pc;
2534:
1.92 ratchov 2535: pc = &ctl_list;
1.64 ratchov 2536: for (;;) {
2537: c = *pc;
2538: if (c == NULL)
2539: return;
1.92 ratchov 2540: if (ctl_match(c, scope, arg0, arg1)) {
1.64 ratchov 2541: #ifdef DEBUG
1.92 ratchov 2542: if (log_level >= 2) {
2543: ctl_log(c);
2544: log_puts(": removed\n");
2545: }
1.64 ratchov 2546: #endif
1.92 ratchov 2547: c->refs_mask &= ~CTL_DEVMASK;
2548: if (c->refs_mask == 0) {
2549: *pc = c->next;
2550: xfree(c);
2551: continue;
2552: }
2553: c->type = CTL_NONE;
2554: c->desc_mask = ~0;
2555: }
2556: pc = &c->next;
1.68 ratchov 2557: }
1.65 ratchov 2558: }
2559:
2560: void
2561: dev_ctlsync(struct dev *d)
2562: {
1.70 ratchov 2563: struct ctl *c;
1.65 ratchov 2564: struct ctlslot *s;
1.70 ratchov 2565: int found, i;
2566:
2567: found = 0;
1.92 ratchov 2568: for (c = ctl_list; c != NULL; c = c->next) {
2569: if (c->scope == CTL_HW &&
2570: c->u.hw.dev == d &&
1.70 ratchov 2571: c->type == CTL_NUM &&
1.92 ratchov 2572: strcmp(c->group, d->name) == 0 &&
1.70 ratchov 2573: strcmp(c->node0.name, "output") == 0 &&
2574: strcmp(c->func, "level") == 0)
2575: found = 1;
2576: }
2577:
2578: if (d->master_enabled && found) {
2579: if (log_level >= 2) {
2580: dev_log(d);
2581: log_puts(": software master level control disabled\n");
2582: }
2583: d->master_enabled = 0;
1.92 ratchov 2584: ctl_del(CTL_DEV_MASTER, d, NULL);
1.70 ratchov 2585: } else if (!d->master_enabled && !found) {
2586: if (log_level >= 2) {
2587: dev_log(d);
2588: log_puts(": software master level control enabled\n");
2589: }
2590: d->master_enabled = 1;
1.92 ratchov 2591: ctl_new(CTL_DEV_MASTER, d, NULL,
2592: CTL_NUM, d->name, "output", -1, "level",
2593: NULL, -1, 127, d->master);
1.70 ratchov 2594: }
1.65 ratchov 2595:
1.95 ratchov 2596: for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) {
2597: if (s->ops == NULL)
2598: continue;
2599: if (s->opt->dev == d)
1.65 ratchov 2600: s->ops->sync(s->arg);
2601: }
1.64 ratchov 2602: }
2603: