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