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