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