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