Annotation of src/usr.bin/sndiod/dev.c, Revision 1.37
1.37 ! ratchov 1: /* $OpenBSD: dev.c,v 1.36 2018/06/26 07:12:35 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.7 ratchov 60: int dev_open(struct dev *);
61: void dev_close(struct dev *);
62: int dev_ref(struct dev *);
63: void dev_unref(struct dev *);
64: int dev_init(struct dev *);
65: void dev_done(struct dev *);
66: struct dev *dev_bynum(int);
67: void dev_del(struct dev *);
68: unsigned int dev_roundof(struct dev *, unsigned int);
69: void dev_wakeup(struct dev *);
70: void dev_sync_attach(struct dev *);
71: void dev_mmcstart(struct dev *);
72: void dev_mmcstop(struct dev *);
73: void dev_mmcloc(struct dev *, unsigned int);
74:
75: void slot_log(struct slot *);
76: void slot_del(struct slot *);
77: void slot_setvol(struct slot *, unsigned int);
78: void slot_attach(struct slot *);
79: void slot_ready(struct slot *);
1.35 ratchov 80: void slot_allocbufs(struct slot *);
81: void slot_freebufs(struct slot *);
1.7 ratchov 82: void slot_start(struct slot *);
83: void slot_detach(struct slot *);
84: void slot_stop(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:
90: struct midiops dev_midiops = {
91: dev_midi_imsg,
92: dev_midi_omsg,
93: dev_midi_fill,
94: dev_midi_exit
95: };
96:
97: struct slotops zomb_slotops = {
98: zomb_onmove,
99: zomb_onvol,
100: zomb_fill,
101: zomb_flush,
102: zomb_eof,
103: zomb_exit
104: };
105:
106: struct dev *dev_list = NULL;
107: unsigned int dev_sndnum = 0;
108:
109: void
110: dev_log(struct dev *d)
111: {
1.3 ratchov 112: #ifdef DEBUG
113: static char *pstates[] = {
114: "cfg", "ini", "run"
115: };
116: #endif
1.1 ratchov 117: log_puts("snd");
118: log_putu(d->num);
1.3 ratchov 119: #ifdef DEBUG
120: if (log_level >= 3) {
121: log_puts(" pst=");
122: log_puts(pstates[d->pstate]);
123: }
124: #endif
1.1 ratchov 125: }
126:
127: void
128: slot_log(struct slot *s)
1.3 ratchov 129: {
1.1 ratchov 130: #ifdef DEBUG
131: static char *pstates[] = {
132: "ini", "sta", "rdy", "run", "stp", "mid"
133: };
134: static char *tstates[] = {
135: "off", "sta", "run", "stp"
136: };
137: #endif
138: log_puts(s->name);
139: log_putu(s->unit);
140: #ifdef DEBUG
141: if (log_level >= 3) {
142: log_puts(" vol=");
143: log_putu(s->vol);
144: if (s->ops) {
145: log_puts(",pst=");
146: log_puts(pstates[s->pstate]);
147: log_puts(",mmc=");
148: log_puts(tstates[s->tstate]);
149: }
150: }
151: #endif
152: }
153:
154: void
1.14 ratchov 155: zomb_onmove(void *arg)
1.1 ratchov 156: {
157: }
158:
159: void
1.25 ratchov 160: zomb_onvol(void *arg)
1.1 ratchov 161: {
162: }
163:
164: void
165: zomb_fill(void *arg)
166: {
167: }
168:
169: void
170: zomb_flush(void *arg)
171: {
172: }
173:
174: void
175: zomb_eof(void *arg)
176: {
177: struct slot *s = arg;
178:
179: #ifdef DEBUG
180: if (log_level >= 3) {
181: slot_log(s);
182: log_puts(": zomb_eof\n");
183: }
184: #endif
185: s->ops = NULL;
186: }
187:
188: void
189: zomb_exit(void *arg)
190: {
191: #ifdef DEBUG
192: struct slot *s = arg;
193:
194: if (log_level >= 3) {
195: slot_log(s);
196: log_puts(": zomb_exit\n");
197: }
198: #endif
199: }
200:
201: /*
202: * send a quarter frame MTC message
203: */
204: void
205: dev_midi_qfr(struct dev *d, int delta)
206: {
207: unsigned char buf[2];
208: unsigned int data;
209: int qfrlen;
210:
211: d->mtc.delta += delta * MTC_SEC;
212: qfrlen = d->rate * (MTC_SEC / (4 * d->mtc.fps));
213: while (d->mtc.delta >= qfrlen) {
214: switch (d->mtc.qfr) {
215: case 0:
216: data = d->mtc.fr & 0xf;
217: break;
218: case 1:
219: data = d->mtc.fr >> 4;
220: break;
221: case 2:
222: data = d->mtc.sec & 0xf;
223: break;
224: case 3:
225: data = d->mtc.sec >> 4;
226: break;
227: case 4:
228: data = d->mtc.min & 0xf;
229: break;
230: case 5:
231: data = d->mtc.min >> 4;
232: break;
233: case 6:
234: data = d->mtc.hr & 0xf;
235: break;
236: case 7:
237: data = (d->mtc.hr >> 4) | (d->mtc.fps_id << 1);
238: /*
239: * tick messages are sent 2 frames ahead
240: */
241: d->mtc.fr += 2;
242: if (d->mtc.fr < d->mtc.fps)
243: break;
244: d->mtc.fr -= d->mtc.fps;
245: d->mtc.sec++;
246: if (d->mtc.sec < 60)
247: break;
248: d->mtc.sec = 0;
249: d->mtc.min++;
250: if (d->mtc.min < 60)
251: break;
252: d->mtc.min = 0;
253: d->mtc.hr++;
254: if (d->mtc.hr < 24)
255: break;
256: d->mtc.hr = 0;
257: break;
258: default:
259: /* NOTREACHED */
260: data = 0;
261: }
262: buf[0] = 0xf1;
263: buf[1] = (d->mtc.qfr << 4) | data;
264: d->mtc.qfr++;
265: d->mtc.qfr &= 7;
266: midi_send(d->midi, buf, 2);
267: d->mtc.delta -= qfrlen;
268: }
269: }
270:
271: /*
272: * send a full frame MTC message
273: */
274: void
275: dev_midi_full(struct dev *d)
276: {
277: struct sysex x;
278: unsigned int fps;
279:
280: d->mtc.delta = MTC_SEC * dev_getpos(d);
281: if (d->rate % (30 * 4 * d->round) == 0) {
282: d->mtc.fps_id = MTC_FPS_30;
283: d->mtc.fps = 30;
284: } else if (d->rate % (25 * 4 * d->round) == 0) {
285: d->mtc.fps_id = MTC_FPS_25;
286: d->mtc.fps = 25;
287: } else {
288: d->mtc.fps_id = MTC_FPS_24;
289: d->mtc.fps = 24;
290: }
291: #ifdef DEBUG
292: if (log_level >= 3) {
293: dev_log(d);
294: log_puts(": mtc full frame at ");
295: log_puti(d->mtc.delta);
296: log_puts(", ");
297: log_puti(d->mtc.fps);
298: log_puts(" fps\n");
299: }
300: #endif
301: fps = d->mtc.fps;
302: d->mtc.hr = (d->mtc.origin / (MTC_SEC * 3600)) % 24;
303: d->mtc.min = (d->mtc.origin / (MTC_SEC * 60)) % 60;
304: d->mtc.sec = (d->mtc.origin / (MTC_SEC)) % 60;
305: d->mtc.fr = (d->mtc.origin / (MTC_SEC / fps)) % fps;
306:
307: x.start = SYSEX_START;
308: x.type = SYSEX_TYPE_RT;
1.8 ratchov 309: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 310: x.id0 = SYSEX_MTC;
311: x.id1 = SYSEX_MTC_FULL;
312: x.u.full.hr = d->mtc.hr | (d->mtc.fps_id << 5);
313: x.u.full.min = d->mtc.min;
314: x.u.full.sec = d->mtc.sec;
315: x.u.full.fr = d->mtc.fr;
316: x.u.full.end = SYSEX_END;
317: d->mtc.qfr = 0;
318: midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(full));
319: }
320:
321: /*
322: * send a volume change MIDI message
323: */
324: void
325: dev_midi_vol(struct dev *d, struct slot *s)
326: {
327: unsigned char msg[3];
328:
329: msg[0] = MIDI_CTL | (s - d->slot);
330: msg[1] = MIDI_CTL_VOL;
331: msg[2] = s->vol;
332: midi_send(d->midi, msg, 3);
333: }
334:
335: /*
336: * send a master volume MIDI message
337: */
338: void
339: dev_midi_master(struct dev *d)
340: {
341: struct sysex x;
342:
343: memset(&x, 0, sizeof(struct sysex));
344: x.start = SYSEX_START;
345: x.type = SYSEX_TYPE_RT;
1.8 ratchov 346: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 347: x.id0 = SYSEX_CONTROL;
348: x.id1 = SYSEX_MASTER;
349: x.u.master.fine = 0;
350: x.u.master.coarse = d->master;
351: x.u.master.end = SYSEX_END;
352: midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(master));
353: }
354:
355: /*
356: * send a sndiod-specific slot description MIDI message
357: */
358: void
359: dev_midi_slotdesc(struct dev *d, struct slot *s)
360: {
361: struct sysex x;
362:
363: memset(&x, 0, sizeof(struct sysex));
364: x.start = SYSEX_START;
365: x.type = SYSEX_TYPE_EDU;
1.8 ratchov 366: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 367: x.id0 = SYSEX_AUCAT;
368: x.id1 = SYSEX_AUCAT_SLOTDESC;
369: if (*s->name != '\0') {
370: snprintf((char *)x.u.slotdesc.name, SYSEX_NAMELEN,
371: "%s%u", s->name, s->unit);
372: }
373: x.u.slotdesc.chan = s - d->slot;
374: x.u.slotdesc.end = SYSEX_END;
375: midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(slotdesc));
376: }
377:
378: void
379: dev_midi_dump(struct dev *d)
380: {
381: struct sysex x;
382: struct slot *s;
383: int i;
384:
385: dev_midi_master(d);
386: for (i = 0, s = d->slot; i < DEV_NSLOT; i++, s++) {
387: dev_midi_slotdesc(d, s);
388: dev_midi_vol(d, s);
389: }
390: x.start = SYSEX_START;
391: x.type = SYSEX_TYPE_EDU;
1.8 ratchov 392: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 393: x.id0 = SYSEX_AUCAT;
394: x.id1 = SYSEX_AUCAT_DUMPEND;
395: x.u.dumpend.end = SYSEX_END;
396: midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(dumpend));
397: }
398:
399: void
400: dev_midi_imsg(void *arg, unsigned char *msg, int len)
401: {
402: #ifdef DEBUG
403: struct dev *d = arg;
404:
405: dev_log(d);
406: log_puts(": can't receive midi messages\n");
407: panic();
408: #endif
409: }
410:
411: void
412: dev_midi_omsg(void *arg, unsigned char *msg, int len)
413: {
414: struct dev *d = arg;
415: struct sysex *x;
416: unsigned int fps, chan;
417:
418: if ((msg[0] & MIDI_CMDMASK) == MIDI_CTL && msg[1] == MIDI_CTL_VOL) {
419: chan = msg[0] & MIDI_CHANMASK;
420: if (chan >= DEV_NSLOT)
421: return;
422: slot_setvol(d->slot + chan, msg[2]);
423: return;
424: }
425: x = (struct sysex *)msg;
426: if (x->start != SYSEX_START)
427: return;
428: if (len < SYSEX_SIZE(empty))
429: return;
430: switch (x->type) {
431: case SYSEX_TYPE_RT:
432: if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
433: if (len == SYSEX_SIZE(master))
434: dev_master(d, x->u.master.coarse);
435: return;
436: }
437: if (x->id0 != SYSEX_MMC)
438: return;
439: switch (x->id1) {
440: case SYSEX_MMC_STOP:
441: if (len != SYSEX_SIZE(stop))
442: return;
443: if (log_level >= 2) {
444: dev_log(d);
445: log_puts(": mmc stop\n");
446: }
447: dev_mmcstop(d);
448: break;
449: case SYSEX_MMC_START:
450: if (len != SYSEX_SIZE(start))
451: return;
452: if (log_level >= 2) {
453: dev_log(d);
454: log_puts(": mmc start\n");
455: }
456: dev_mmcstart(d);
457: break;
458: case SYSEX_MMC_LOC:
459: if (len != SYSEX_SIZE(loc) ||
460: x->u.loc.len != SYSEX_MMC_LOC_LEN ||
461: x->u.loc.cmd != SYSEX_MMC_LOC_CMD)
462: return;
463: switch (x->u.loc.hr >> 5) {
464: case MTC_FPS_24:
465: fps = 24;
466: break;
467: case MTC_FPS_25:
468: fps = 25;
469: break;
470: case MTC_FPS_30:
471: fps = 30;
472: break;
473: default:
474: dev_mmcstop(d);
475: return;
476: }
477: dev_mmcloc(d,
478: (x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
479: x->u.loc.min * 60 * MTC_SEC +
480: x->u.loc.sec * MTC_SEC +
481: x->u.loc.fr * (MTC_SEC / fps) +
482: x->u.loc.cent * (MTC_SEC / 100 / fps));
483: break;
484: }
485: break;
486: case SYSEX_TYPE_EDU:
487: if (x->id0 != SYSEX_AUCAT || x->id1 != SYSEX_AUCAT_DUMPREQ)
488: return;
489: if (len != SYSEX_SIZE(dumpreq))
490: return;
491: dev_midi_dump(d);
492: break;
493: }
494: }
495:
496: void
497: dev_midi_fill(void *arg, int count)
498: {
1.2 ratchov 499: /* nothing to do */
1.1 ratchov 500: }
501:
502: void
503: dev_midi_exit(void *arg)
504: {
505: struct dev *d = arg;
506:
507: if (log_level >= 1) {
508: dev_log(d);
509: log_puts(": midi end point died\n");
510: }
511: if (d->pstate != DEV_CFG)
512: dev_close(d);
513: }
514:
1.12 ratchov 515: int
516: slot_skip(struct slot *s)
1.1 ratchov 517: {
1.12 ratchov 518: unsigned char *data = (unsigned char *)0xdeadbeef; /* please gcc */
519: int max, count;
520:
521: max = s->skip;
522: while (s->skip > 0) {
523: if (s->pstate != SLOT_STOP && (s->mode & MODE_RECMASK)) {
524: data = abuf_wgetblk(&s->sub.buf, &count);
525: if (count < s->round * s->sub.bpf)
526: break;
527: }
528: if (s->mode & MODE_PLAY) {
529: if (s->mix.buf.used < s->round * s->mix.bpf)
530: break;
531: }
1.1 ratchov 532: #ifdef DEBUG
533: if (log_level >= 4) {
534: slot_log(s);
1.12 ratchov 535: log_puts(": skipped a cycle\n");
1.1 ratchov 536: }
537: #endif
1.12 ratchov 538: if (s->pstate != SLOT_STOP && (s->mode & MODE_RECMASK)) {
539: if (s->sub.encbuf)
540: enc_sil_do(&s->sub.enc, data, s->round);
541: else
542: memset(data, 0, s->round * s->sub.bpf);
543: abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf);
544: }
545: if (s->mode & MODE_PLAY) {
546: abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf);
1.1 ratchov 547: }
1.23 ratchov 548: s->skip--;
1.1 ratchov 549: }
1.12 ratchov 550: return max - s->skip;
1.1 ratchov 551: }
552:
1.32 ratchov 553: /*
554: * Mix the slot input block over the output block
555: */
556: void
557: dev_mix_badd(struct dev *d, struct slot *s)
1.1 ratchov 558: {
1.32 ratchov 559: adata_t *idata, *odata, *in;
560: int icount, i, offs, vol, nch;
561:
562: odata = DEV_PBUF(d);
563: idata = (adata_t *)abuf_rgetblk(&s->mix.buf, &icount);
564: #ifdef DEBUG
565: if (icount < s->round * s->mix.bpf) {
566: slot_log(s);
567: log_puts(": not enough data to mix (");
568: log_putu(icount);
569: log_puts("bytes)\n");
570: panic();
571: }
572: #endif
573:
574: /*
575: * Apply the following processing chain:
576: *
577: * dec -> resamp-> cmap
578: *
579: * where the first two are optional.
580: */
581:
582: in = idata;
583:
584: if (s->mix.decbuf) {
585: dec_do(&s->mix.dec, (void *)in, s->mix.decbuf, s->round);
586: in = s->mix.decbuf;
587: }
1.1 ratchov 588:
589: if (s->mix.resampbuf) {
1.32 ratchov 590: resamp_do(&s->mix.resamp, in, s->mix.resampbuf, s->round);
1.1 ratchov 591: in = s->mix.resampbuf;
1.32 ratchov 592: }
1.1 ratchov 593:
1.10 ratchov 594: nch = s->mix.cmap.nch;
1.1 ratchov 595: vol = ADATA_MUL(s->mix.weight, s->mix.vol) / s->mix.join;
1.32 ratchov 596: cmap_add(&s->mix.cmap, in, odata, vol, d->round);
1.1 ratchov 597:
598: offs = 0;
599: for (i = s->mix.join - 1; i > 0; i--) {
600: offs += nch;
1.32 ratchov 601: cmap_add(&s->mix.cmap, in + offs, odata, vol, d->round);
1.1 ratchov 602: }
1.32 ratchov 603:
1.1 ratchov 604: offs = 0;
605: for (i = s->mix.expand - 1; i > 0; i--) {
606: offs += nch;
1.32 ratchov 607: cmap_add(&s->mix.cmap, in, odata + offs, vol, d->round);
1.1 ratchov 608: }
609:
610: abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf);
611: }
612:
613: /*
614: * Normalize input levels.
615: */
616: void
617: dev_mix_adjvol(struct dev *d)
618: {
619: unsigned int n;
620: struct slot *i, *j;
621: int weight;
622:
623: for (i = d->slot_list; i != NULL; i = i->next) {
624: if (!(i->mode & MODE_PLAY))
625: continue;
626: weight = ADATA_UNIT;
627: if (d->autovol) {
628: /*
629: * count the number of inputs that have
630: * overlapping channel sets
631: */
632: n = 0;
633: for (j = d->slot_list; j != NULL; j = j->next) {
634: if (!(j->mode & MODE_PLAY))
635: continue;
636: if (i->mix.slot_cmin <= j->mix.slot_cmax &&
637: i->mix.slot_cmax >= j->mix.slot_cmin)
638: n++;
639: }
640: weight /= n;
641: }
642: if (weight > i->mix.maxweight)
643: weight = i->mix.maxweight;
644: i->mix.weight = ADATA_MUL(weight, MIDI_TO_ADATA(d->master));
645: #ifdef DEBUG
646: if (log_level >= 3) {
647: slot_log(i);
648: log_puts(": set weight: ");
649: log_puti(i->mix.weight);
650: log_puts("/");
651: log_puti(i->mix.maxweight);
652: log_puts("\n");
653: }
654: #endif
655: }
656: }
657:
658: /*
659: * Copy data from slot to device
660: */
661: void
662: dev_sub_bcopy(struct dev *d, struct slot *s)
663: {
1.32 ratchov 664: adata_t *idata, *enc_out, *resamp_out, *cmap_out;
665: void *odata;
1.15 ratchov 666: int ocount, moffs;
1.1 ratchov 667:
1.32 ratchov 668: int i, vol, offs, nch;
669:
670:
1.15 ratchov 671: if (s->mode & MODE_MON) {
672: moffs = d->poffs + d->round;
673: if (moffs == d->psize)
674: moffs = 0;
675: idata = d->pbuf + moffs * d->pchan;
676: } else
677: idata = d->rbuf;
1.1 ratchov 678: odata = (adata_t *)abuf_wgetblk(&s->sub.buf, &ocount);
679: #ifdef DEBUG
680: if (ocount < s->round * s->sub.bpf) {
681: log_puts("dev_sub_bcopy: not enough space\n");
682: panic();
683: }
684: #endif
1.32 ratchov 685:
686: /*
687: * Apply the following processing chain:
688: *
689: * cmap -> resamp -> enc
690: *
691: * where the last two are optional.
692: */
693:
694: enc_out = odata;
695: resamp_out = s->sub.encbuf ? s->sub.encbuf : enc_out;
696: cmap_out = s->sub.resampbuf ? s->sub.resampbuf : resamp_out;
697:
698: nch = s->sub.cmap.nch;
699: vol = ADATA_UNIT / s->sub.join;
700: cmap_copy(&s->sub.cmap, idata, cmap_out, vol, d->round);
701:
702: offs = 0;
703: for (i = s->sub.join - 1; i > 0; i--) {
704: offs += nch;
705: cmap_add(&s->sub.cmap, idata + offs, cmap_out, vol, d->round);
706: }
707:
708: offs = 0;
709: for (i = s->sub.expand - 1; i > 0; i--) {
710: offs += nch;
711: cmap_copy(&s->sub.cmap, idata, cmap_out + offs, vol, d->round);
712: }
713:
714: if (s->sub.resampbuf) {
715: resamp_do(&s->sub.resamp,
716: s->sub.resampbuf, resamp_out, d->round);
717: }
718:
719: if (s->sub.encbuf)
720: enc_do(&s->sub.enc, s->sub.encbuf, (void *)enc_out, s->round);
721:
722: abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf);
1.1 ratchov 723: }
724:
1.16 ratchov 725: /*
726: * run a one block cycle: consume one recorded block from
727: * rbuf and produce one play block in pbuf
728: */
1.1 ratchov 729: void
1.16 ratchov 730: dev_cycle(struct dev *d)
1.1 ratchov 731: {
732: struct slot *s, **ps;
1.12 ratchov 733: unsigned char *base;
734: int nsamp;
1.1 ratchov 735:
1.16 ratchov 736: /*
737: * check if the device is actually used. If it isn't,
738: * then close it
739: */
740: if (d->slot_list == NULL && d->tstate != MMC_RUN) {
741: if (log_level >= 2) {
742: dev_log(d);
743: log_puts(": device stopped\n");
744: }
745: dev_sio_stop(d);
746: d->pstate = DEV_INIT;
747: if (d->refcnt == 0)
748: dev_close(d);
749: return;
750: }
751:
752: if (d->prime > 0) {
753: #ifdef DEBUG
754: if (log_level >= 4) {
755: dev_log(d);
756: log_puts(": empty cycle, prime = ");
757: log_putu(d->prime);
758: log_puts("\n");
759: }
760: #endif
761: base = (unsigned char *)DEV_PBUF(d);
762: nsamp = d->round * d->pchan;
763: memset(base, 0, nsamp * sizeof(adata_t));
764: if (d->encbuf) {
765: enc_do(&d->enc, (unsigned char *)DEV_PBUF(d),
766: d->encbuf, d->round);
767: }
768: d->prime -= d->round;
769: return;
770: }
771:
1.12 ratchov 772: d->delta -= d->round;
1.1 ratchov 773: #ifdef DEBUG
774: if (log_level >= 4) {
775: dev_log(d);
1.16 ratchov 776: log_puts(": full cycle: delta = ");
1.12 ratchov 777: log_puti(d->delta);
778: if (d->mode & MODE_PLAY) {
779: log_puts(", poffs = ");
780: log_puti(d->poffs);
781: }
782: log_puts("\n");
1.1 ratchov 783: }
784: #endif
1.12 ratchov 785: if (d->mode & MODE_PLAY) {
786: base = (unsigned char *)DEV_PBUF(d);
787: nsamp = d->round * d->pchan;
788: memset(base, 0, nsamp * sizeof(adata_t));
789: }
1.1 ratchov 790: if ((d->mode & MODE_REC) && d->decbuf)
791: dec_do(&d->dec, d->decbuf, (unsigned char *)d->rbuf, d->round);
792: ps = &d->slot_list;
793: while ((s = *ps) != NULL) {
1.12 ratchov 794: #ifdef DEBUG
795: if (log_level >= 4) {
796: slot_log(s);
797: log_puts(": running");
798: log_puts(", skip = ");
799: log_puti(s->skip);
800: log_puts("\n");
801: }
802: #endif
803: /*
804: * skip cycles for XRUN_SYNC correction
805: */
806: slot_skip(s);
807: if (s->skip < 0) {
808: s->skip++;
1.1 ratchov 809: ps = &s->next;
810: continue;
811: }
1.12 ratchov 812:
813: #ifdef DEBUG
814: if (s->pstate == SLOT_STOP && !(s->mode & MODE_PLAY)) {
815: slot_log(s);
816: log_puts(": rec-only slots can't be drained\n");
817: panic();
818: }
819: #endif
820: /*
821: * check if stopped stream finished draining
822: */
823: if (s->pstate == SLOT_STOP &&
824: s->mix.buf.used < s->round * s->mix.bpf) {
825: /*
826: * partial blocks are zero-filled by socket
827: * layer, so s->mix.buf.used == 0 and we can
828: * destroy the buffer
829: */
1.35 ratchov 830: *ps = s->next;
1.12 ratchov 831: s->pstate = SLOT_INIT;
832: s->ops->eof(s->arg);
1.35 ratchov 833: slot_freebufs(s);
1.12 ratchov 834: dev_mix_adjvol(d);
1.35 ratchov 835: #ifdef DEBUG
836: if (log_level >= 3) {
837: slot_log(s);
838: log_puts(": drained\n");
839: }
840: #endif
1.1 ratchov 841: continue;
842: }
1.23 ratchov 843:
1.12 ratchov 844: /*
845: * check for xruns
846: */
1.23 ratchov 847: if (((s->mode & MODE_PLAY) &&
1.12 ratchov 848: s->mix.buf.used < s->round * s->mix.bpf) ||
849: ((s->mode & MODE_RECMASK) &&
850: s->sub.buf.len - s->sub.buf.used <
851: s->round * s->sub.bpf)) {
852:
853: #ifdef DEBUG
854: if (log_level >= 3) {
855: slot_log(s);
856: log_puts(": xrun, pause cycle\n");
857: }
858: #endif
1.1 ratchov 859: if (s->xrun == XRUN_IGNORE) {
860: s->delta -= s->round;
1.12 ratchov 861: ps = &s->next;
862: } else if (s->xrun == XRUN_SYNC) {
863: s->skip++;
864: ps = &s->next;
865: } else if (s->xrun == XRUN_ERROR) {
866: s->ops->exit(s->arg);
867: *ps = s->next;
868: } else {
869: #ifdef DEBUG
870: slot_log(s);
871: log_puts(": bad xrun mode\n");
872: panic();
873: #endif
874: }
875: continue;
876: }
877: if ((s->mode & MODE_RECMASK) && !(s->pstate == SLOT_STOP)) {
878: if (s->sub.prime == 0) {
879: dev_sub_bcopy(d, s);
880: s->ops->flush(s->arg);
881: } else {
1.1 ratchov 882: #ifdef DEBUG
883: if (log_level >= 3) {
884: slot_log(s);
1.12 ratchov 885: log_puts(": prime = ");
886: log_puti(s->sub.prime);
887: log_puts("\n");
1.1 ratchov 888: }
889: #endif
1.12 ratchov 890: s->sub.prime--;
1.1 ratchov 891: }
892: }
1.15 ratchov 893: if (s->mode & MODE_PLAY) {
894: dev_mix_badd(d, s);
895: if (s->pstate != SLOT_STOP)
896: s->ops->fill(s->arg);
897: }
1.1 ratchov 898: ps = &s->next;
899: }
1.12 ratchov 900: if ((d->mode & MODE_PLAY) && d->encbuf) {
901: enc_do(&d->enc, (unsigned char *)DEV_PBUF(d),
902: d->encbuf, d->round);
903: }
1.1 ratchov 904: }
905:
906: /*
907: * called at every clock tick by the device
908: */
909: void
910: dev_onmove(struct dev *d, int delta)
911: {
912: long long pos;
1.23 ratchov 913: struct slot *s, *snext;
1.12 ratchov 914:
915: d->delta += delta;
1.1 ratchov 916:
917: for (s = d->slot_list; s != NULL; s = snext) {
1.12 ratchov 918: /*
919: * s->ops->onmove() may remove the slot
920: */
1.1 ratchov 921: snext = s->next;
922: pos = (long long)delta * s->round + s->delta_rem;
923: s->delta_rem = pos % d->round;
924: s->delta += pos / (int)d->round;
925: if (s->delta >= 0)
1.14 ratchov 926: s->ops->onmove(s->arg);
1.1 ratchov 927: }
928: if (d->tstate == MMC_RUN)
929: dev_midi_qfr(d, delta);
930: }
931:
932: void
933: dev_master(struct dev *d, unsigned int master)
934: {
935: if (log_level >= 2) {
936: dev_log(d);
937: log_puts(": master volume set to ");
938: log_putu(master);
939: log_puts("\n");
940: }
941: d->master = master;
942: if (d->mode & MODE_PLAY)
943: dev_mix_adjvol(d);
944: }
945:
946: /*
947: * return the latency that a stream would have if it's attached
948: */
949: int
950: dev_getpos(struct dev *d)
951: {
952: return (d->mode & MODE_PLAY) ? -d->bufsz : 0;
953: }
954:
955: /*
956: * Create a sndio device
957: */
958: struct dev *
959: dev_new(char *path, struct aparams *par,
960: unsigned int mode, unsigned int bufsz, unsigned int round,
961: unsigned int rate, unsigned int hold, unsigned int autovol)
962: {
963: struct dev *d;
964: unsigned int i;
965:
966: if (dev_sndnum == DEV_NMAX) {
967: if (log_level >= 1)
968: log_puts("too many devices\n");
969: return NULL;
970: }
971: d = xmalloc(sizeof(struct dev));
1.21 ratchov 972: d->path = xstrdup(path);
1.1 ratchov 973: d->num = dev_sndnum++;
1.36 ratchov 974: d->opt_list = NULL;
1.1 ratchov 975:
976: /*
977: * XXX: below, we allocate a midi input buffer, since we don't
978: * receive raw midi data, so no need to allocate a input
979: * ibuf. Possibly set imsg & fill callbacks to NULL and
980: * use this to in midi_new() to check if buffers need to be
981: * allocated
982: */
983: d->midi = midi_new(&dev_midiops, d, MODE_MIDIIN | MODE_MIDIOUT);
984: midi_tag(d->midi, d->num);
985: d->reqpar = *par;
986: d->reqmode = mode;
987: d->reqpchan = d->reqrchan = 0;
988: d->reqbufsz = bufsz;
989: d->reqround = round;
990: d->reqrate = rate;
991: d->hold = hold;
992: d->autovol = autovol;
993: d->refcnt = 0;
994: d->pstate = DEV_CFG;
995: d->serial = 0;
996: for (i = 0; i < DEV_NSLOT; i++) {
997: d->slot[i].unit = i;
998: d->slot[i].ops = NULL;
999: d->slot[i].vol = MIDI_MAXCTL;
1000: d->slot[i].tstate = MMC_OFF;
1001: d->slot[i].serial = d->serial++;
1.26 ratchov 1002: strlcpy(d->slot[i].name, "prog", SLOT_NAMEMAX);
1.1 ratchov 1003: }
1004: d->slot_list = NULL;
1005: d->master = MIDI_MAXCTL;
1006: d->mtc.origin = 0;
1007: d->tstate = MMC_STOP;
1008: d->next = dev_list;
1009: dev_list = d;
1010: return d;
1011: }
1012:
1013: /*
1014: * adjust device parameters and mode
1015: */
1016: void
1017: dev_adjpar(struct dev *d, int mode,
1.25 ratchov 1018: int pmax, int rmax)
1.1 ratchov 1019: {
1020: d->reqmode |= mode & MODE_AUDIOMASK;
1021: if (mode & MODE_PLAY) {
1022: if (d->reqpchan < pmax + 1)
1023: d->reqpchan = pmax + 1;
1024: }
1025: if (mode & MODE_REC) {
1026: if (d->reqrchan < rmax + 1)
1027: d->reqrchan = rmax + 1;
1028: }
1029: }
1030:
1031: /*
1032: * Open the device with the dev_reqxxx capabilities. Setup a mixer, demuxer,
1033: * monitor, midi control, and any necessary conversions.
1034: */
1035: int
1036: dev_open(struct dev *d)
1037: {
1038: d->mode = d->reqmode;
1039: d->round = d->reqround;
1040: d->bufsz = d->reqbufsz;
1041: d->rate = d->reqrate;
1042: d->pchan = d->reqpchan;
1043: d->rchan = d->reqrchan;
1044: d->par = d->reqpar;
1045: if (d->pchan == 0)
1046: d->pchan = 2;
1047: if (d->rchan == 0)
1048: d->rchan = 2;
1049: if (!dev_sio_open(d)) {
1050: if (log_level >= 1) {
1051: dev_log(d);
1052: log_puts(": ");
1053: log_puts(d->path);
1054: log_puts(": failed to open audio device\n");
1055: }
1056: return 0;
1057: }
1058: if (d->mode & MODE_REC) {
1059: /*
1060: * Create device <-> demuxer buffer
1061: */
1062: d->rbuf = xmalloc(d->round * d->rchan * sizeof(adata_t));
1063:
1064: /*
1065: * Insert a converter, if needed.
1066: */
1067: if (!aparams_native(&d->par)) {
1068: dec_init(&d->dec, &d->par, d->rchan);
1069: d->decbuf = xmalloc(d->round * d->rchan * d->par.bps);
1070: } else
1071: d->decbuf = NULL;
1072: }
1073: if (d->mode & MODE_PLAY) {
1074: /*
1075: * Create device <-> mixer buffer
1076: */
1077: d->poffs = 0;
1.15 ratchov 1078: d->psize = d->bufsz + d->round;
1079: d->pbuf = xmalloc(d->psize * d->pchan * sizeof(adata_t));
1.1 ratchov 1080: d->mode |= MODE_MON;
1081:
1082: /*
1083: * Append a converter, if needed.
1084: */
1085: if (!aparams_native(&d->par)) {
1086: enc_init(&d->enc, &d->par, d->pchan);
1087: d->encbuf = xmalloc(d->round * d->pchan * d->par.bps);
1088: } else
1089: d->encbuf = NULL;
1090: }
1091: d->pstate = DEV_INIT;
1092: if (log_level >= 2) {
1093: dev_log(d);
1094: log_puts(": ");
1095: log_putu(d->rate);
1096: log_puts("Hz, ");
1097: aparams_log(&d->par);
1098: if (d->mode & MODE_PLAY) {
1099: log_puts(", play 0:");
1100: log_puti(d->pchan - 1);
1101: }
1102: if (d->mode & MODE_REC) {
1103: log_puts(", rec 0:");
1104: log_puti(d->rchan - 1);
1105: }
1106: log_puts(", ");
1107: log_putu(d->bufsz / d->round);
1108: log_puts(" blocks of ");
1109: log_putu(d->round);
1110: log_puts(" frames\n");
1111: }
1112: return 1;
1113: }
1114:
1115: /*
1116: * force the device to go in DEV_CFG state, the caller is supposed to
1117: * ensure buffers are drained
1118: */
1119: void
1120: dev_close(struct dev *d)
1121: {
1.3 ratchov 1122: int i;
1123: struct slot *s;
1.1 ratchov 1124:
1125: #ifdef DEBUG
1126: if (log_level >= 3) {
1127: dev_log(d);
1128: log_puts(": closing\n");
1129: }
1130: #endif
1.3 ratchov 1131: d->pstate = DEV_CFG;
1132: for (s = d->slot, i = DEV_NSLOT; i > 0; i--, s++) {
1.1 ratchov 1133: if (s->ops)
1134: s->ops->exit(s->arg);
1135: s->ops = NULL;
1136: }
1.3 ratchov 1137: d->slot_list = NULL;
1.1 ratchov 1138: dev_sio_close(d);
1139: if (d->mode & MODE_PLAY) {
1140: if (d->encbuf != NULL)
1141: xfree(d->encbuf);
1142: xfree(d->pbuf);
1143: }
1144: if (d->mode & MODE_REC) {
1145: if (d->decbuf != NULL)
1146: xfree(d->decbuf);
1147: xfree(d->rbuf);
1148: }
1149: }
1150:
1151: int
1152: dev_ref(struct dev *d)
1153: {
1154: #ifdef DEBUG
1155: if (log_level >= 3) {
1156: dev_log(d);
1157: log_puts(": device requested\n");
1158: }
1159: #endif
1160: if (d->pstate == DEV_CFG && !dev_open(d))
1161: return 0;
1162: d->refcnt++;
1163: return 1;
1164: }
1165:
1166: void
1167: dev_unref(struct dev *d)
1168: {
1169: #ifdef DEBUG
1170: if (log_level >= 3) {
1171: dev_log(d);
1172: log_puts(": device released\n");
1173: }
1174: #endif
1175: d->refcnt--;
1176: if (d->refcnt == 0 && d->pstate == DEV_INIT)
1177: dev_close(d);
1178: }
1179:
1180: /*
1181: * initialize the device with the current parameters
1182: */
1183: int
1184: dev_init(struct dev *d)
1185: {
1186: if ((d->reqmode & MODE_AUDIOMASK) == 0) {
1187: #ifdef DEBUG
1188: dev_log(d);
1189: log_puts(": has no streams\n");
1190: #endif
1191: return 0;
1192: }
1193: if (d->hold && !dev_ref(d))
1194: return 0;
1195: return 1;
1196: }
1197:
1198: /*
1199: * Unless the device is already in process of closing, request it to close
1200: */
1201: void
1202: dev_done(struct dev *d)
1203: {
1204: #ifdef DEBUG
1205: if (log_level >= 3) {
1206: dev_log(d);
1207: log_puts(": draining\n");
1208: }
1209: #endif
1.20 ratchov 1210: if (d->tstate != MMC_STOP)
1211: dev_mmcstop(d);
1.1 ratchov 1212: if (d->hold)
1213: dev_unref(d);
1214: }
1215:
1216: struct dev *
1217: dev_bynum(int num)
1218: {
1219: struct dev *d;
1220:
1221: for (d = dev_list; d != NULL; d = d->next) {
1.19 ratchov 1222: if (d->num == num)
1.1 ratchov 1223: return d;
1224: }
1225: return NULL;
1226: }
1227:
1228: /*
1229: * Free the device
1230: */
1231: void
1232: dev_del(struct dev *d)
1233: {
1234: struct dev **p;
1235:
1236: #ifdef DEBUG
1237: if (log_level >= 3) {
1238: dev_log(d);
1239: log_puts(": deleting\n");
1240: }
1241: #endif
1.36 ratchov 1242: while (d->opt_list != NULL)
1243: opt_del(d, d->opt_list);
1.1 ratchov 1244: if (d->pstate != DEV_CFG)
1245: dev_close(d);
1246: for (p = &dev_list; *p != d; p = &(*p)->next) {
1247: #ifdef DEBUG
1248: if (*p == NULL) {
1249: dev_log(d);
1250: log_puts(": device to delete not on the list\n");
1251: panic();
1252: }
1253: #endif
1254: }
1255: midi_del(d->midi);
1256: *p = d->next;
1.21 ratchov 1257: xfree(d->path);
1.1 ratchov 1258: xfree(d);
1259: }
1260:
1261: unsigned int
1262: dev_roundof(struct dev *d, unsigned int newrate)
1263: {
1264: return (d->round * newrate + d->rate / 2) / d->rate;
1265: }
1266:
1267: /*
1268: * If the device is paused, then resume it.
1269: */
1270: void
1271: dev_wakeup(struct dev *d)
1272: {
1273: if (d->pstate == DEV_INIT) {
1274: if (log_level >= 2) {
1275: dev_log(d);
1276: log_puts(": device started\n");
1277: }
1278: if (d->mode & MODE_PLAY) {
1279: d->prime = d->bufsz;
1280: } else {
1281: d->prime = 0;
1282: }
1.16 ratchov 1283: d->poffs = 0;
1.12 ratchov 1284:
1.23 ratchov 1285: /*
1.16 ratchov 1286: * empty cycles don't increment delta, so it's ok to
1287: * start at 0
1288: **/
1.23 ratchov 1289: d->delta = 0;
1.12 ratchov 1290:
1.1 ratchov 1291: d->pstate = DEV_RUN;
1292: dev_sio_start(d);
1293: }
1294: }
1295:
1296: /*
1297: * check that all clients controlled by MMC are ready to start, if so,
1298: * attach them all at the same position
1299: */
1300: void
1301: dev_sync_attach(struct dev *d)
1302: {
1303: int i;
1304: struct slot *s;
1305:
1306: if (d->tstate != MMC_START) {
1307: if (log_level >= 2) {
1308: dev_log(d);
1309: log_puts(": not started by mmc yet, waiting...\n");
1310: }
1311: return;
1312: }
1313: for (i = 0; i < DEV_NSLOT; i++) {
1314: s = d->slot + i;
1315: if (!s->ops || s->tstate == MMC_OFF)
1316: continue;
1317: if (s->tstate != MMC_START || s->pstate != SLOT_READY) {
1318: #ifdef DEBUG
1319: if (log_level >= 3) {
1320: slot_log(s);
1321: log_puts(": not ready, start delayed\n");
1322: }
1323: #endif
1324: return;
1325: }
1326: }
1327: if (!dev_ref(d))
1328: return;
1329: for (i = 0; i < DEV_NSLOT; i++) {
1330: s = d->slot + i;
1331: if (!s->ops)
1332: continue;
1333: if (s->tstate == MMC_START) {
1334: #ifdef DEBUG
1335: if (log_level >= 3) {
1336: slot_log(s);
1337: log_puts(": started\n");
1338: }
1339: #endif
1340: s->tstate = MMC_RUN;
1341: slot_attach(s);
1342: }
1343: }
1344: d->tstate = MMC_RUN;
1345: dev_midi_full(d);
1346: dev_wakeup(d);
1347: }
1348:
1349: /*
1350: * start all slots simultaneously
1351: */
1352: void
1353: dev_mmcstart(struct dev *d)
1354: {
1355: if (d->tstate == MMC_STOP) {
1356: d->tstate = MMC_START;
1357: dev_sync_attach(d);
1358: #ifdef DEBUG
1359: } else {
1360: if (log_level >= 3) {
1361: dev_log(d);
1362: log_puts(": ignoring mmc start\n");
1363: }
1364: #endif
1365: }
1366: }
1367:
1368: /*
1369: * stop all slots simultaneously
1370: */
1371: void
1372: dev_mmcstop(struct dev *d)
1373: {
1374: switch (d->tstate) {
1375: case MMC_START:
1376: d->tstate = MMC_STOP;
1377: return;
1378: case MMC_RUN:
1379: d->tstate = MMC_STOP;
1380: dev_unref(d);
1381: break;
1382: default:
1383: #ifdef DEBUG
1384: if (log_level >= 3) {
1385: dev_log(d);
1386: log_puts(": ignored mmc stop\n");
1387: }
1388: #endif
1389: return;
1390: }
1391: }
1392:
1393: /*
1394: * relocate all slots simultaneously
1395: */
1396: void
1397: dev_mmcloc(struct dev *d, unsigned int origin)
1398: {
1399: if (log_level >= 2) {
1400: dev_log(d);
1401: log_puts(": relocated to ");
1402: log_putu(origin);
1403: log_puts("\n");
1404: }
1405: if (d->tstate == MMC_RUN)
1406: dev_mmcstop(d);
1407: d->mtc.origin = origin;
1408: if (d->tstate == MMC_RUN)
1409: dev_mmcstart(d);
1410: }
1411:
1.35 ratchov 1412:
1413: /*
1414: * allocate buffers & conversion chain
1415: */
1416: void
1417: slot_allocbufs(struct slot *s)
1418: {
1419: unsigned int slot_nch, dev_nch;
1420: struct dev *d = s->dev;
1421:
1422: if (s->mode & MODE_PLAY) {
1423: s->mix.bpf = s->par.bps *
1424: (s->mix.slot_cmax - s->mix.slot_cmin + 1);
1425: abuf_init(&s->mix.buf, s->appbufsz * s->mix.bpf);
1426:
1427: slot_nch = s->mix.slot_cmax - s->mix.slot_cmin + 1;
1428: dev_nch = s->mix.dev_cmax - s->mix.dev_cmin + 1;
1429: s->mix.decbuf = NULL;
1430: s->mix.resampbuf = NULL;
1431: s->mix.join = 1;
1432: s->mix.expand = 1;
1433: if (s->dup) {
1434: if (dev_nch > slot_nch)
1435: s->mix.expand = dev_nch / slot_nch;
1436: else if (dev_nch < slot_nch)
1437: s->mix.join = slot_nch / dev_nch;
1438: }
1439: cmap_init(&s->mix.cmap,
1440: s->mix.slot_cmin, s->mix.slot_cmax,
1441: s->mix.slot_cmin, s->mix.slot_cmax,
1442: 0, d->pchan - 1,
1443: s->mix.dev_cmin, s->mix.dev_cmax);
1444: if (!aparams_native(&s->par)) {
1445: dec_init(&s->mix.dec, &s->par, slot_nch);
1446: s->mix.decbuf =
1447: xmalloc(s->round * slot_nch * sizeof(adata_t));
1448: }
1449: if (s->rate != d->rate) {
1450: resamp_init(&s->mix.resamp, s->round, d->round,
1451: slot_nch);
1452: s->mix.resampbuf =
1453: xmalloc(d->round * slot_nch * sizeof(adata_t));
1454: }
1455: }
1456:
1457: if (s->mode & MODE_RECMASK) {
1458: s->sub.bpf = s->par.bps *
1459: (s->sub.slot_cmax - s->sub.slot_cmin + 1);
1460: abuf_init(&s->sub.buf, s->appbufsz * s->sub.bpf);
1461:
1462: slot_nch = s->sub.slot_cmax - s->sub.slot_cmin + 1;
1463: dev_nch = s->sub.dev_cmax - s->sub.dev_cmin + 1;
1464: s->sub.encbuf = NULL;
1465: s->sub.resampbuf = NULL;
1466: s->sub.join = 1;
1467: s->sub.expand = 1;
1468: if (s->dup) {
1469: if (dev_nch > slot_nch)
1470: s->sub.join = dev_nch / slot_nch;
1471: else if (dev_nch < slot_nch)
1472: s->sub.expand = slot_nch / dev_nch;
1473: }
1474: cmap_init(&s->sub.cmap,
1475: 0, ((s->mode & MODE_MON) ? d->pchan : d->rchan) - 1,
1476: s->sub.dev_cmin, s->sub.dev_cmax,
1477: s->sub.slot_cmin, s->sub.slot_cmax,
1478: s->sub.slot_cmin, s->sub.slot_cmax);
1479: if (s->rate != d->rate) {
1480: resamp_init(&s->sub.resamp, d->round, s->round,
1481: slot_nch);
1482: s->sub.resampbuf =
1483: xmalloc(d->round * slot_nch * sizeof(adata_t));
1484: }
1485: if (!aparams_native(&s->par)) {
1486: enc_init(&s->sub.enc, &s->par, slot_nch);
1487: s->sub.encbuf =
1488: xmalloc(s->round * slot_nch * sizeof(adata_t));
1489: }
1490:
1491: /*
1492: * cmap_copy() doesn't write samples in all channels,
1493: * for instance when mono->stereo conversion is
1494: * disabled. So we have to prefill cmap_copy() output
1495: * with silence.
1496: */
1497: if (s->sub.resampbuf) {
1498: memset(s->sub.resampbuf, 0,
1499: d->round * slot_nch * sizeof(adata_t));
1500: } else if (s->sub.encbuf) {
1501: memset(s->sub.encbuf, 0,
1502: s->round * slot_nch * sizeof(adata_t));
1503: } else {
1504: memset(s->sub.buf.data, 0,
1505: s->appbufsz * slot_nch * sizeof(adata_t));
1506: }
1507: }
1508:
1509: #ifdef DEBUG
1510: if (log_level >= 3) {
1511: slot_log(s);
1512: log_puts(": allocated ");
1513: log_putu(s->appbufsz);
1514: log_puts("/");
1515: log_putu(SLOT_BUFSZ(s));
1516: log_puts(" fr buffers\n");
1517: }
1518: #endif
1519: }
1520:
1521: /*
1522: * free buffers & conversion chain
1523: */
1524: void
1525: slot_freebufs(struct slot *s)
1526: {
1527: if (s->mode & MODE_RECMASK) {
1528: abuf_done(&s->sub.buf);
1529: if (s->sub.encbuf)
1530: xfree(s->sub.encbuf);
1531: if (s->sub.resampbuf)
1532: xfree(s->sub.resampbuf);
1533: }
1534:
1535: if (s->mode & MODE_PLAY) {
1536: abuf_done(&s->mix.buf);
1537: if (s->mix.decbuf)
1538: xfree(s->mix.decbuf);
1539: if (s->mix.resampbuf)
1540: xfree(s->mix.resampbuf);
1541: }
1542: }
1543:
1.1 ratchov 1544: /*
1545: * allocate a new slot and register the given call-backs
1546: */
1547: struct slot *
1.37 ! ratchov 1548: slot_new(struct dev *d, struct opt *opt, char *who,
! 1549: struct slotops *ops, void *arg, int mode)
1.1 ratchov 1550: {
1551: char *p;
1552: char name[SLOT_NAMEMAX];
1553: unsigned int i, unit, umap = 0;
1554: unsigned int ser, bestser, bestidx;
1555: struct slot *s;
1556:
1557: /*
1.27 ratchov 1558: * create a ``valid'' control name (lowcase, remove [^a-z], truncate)
1.1 ratchov 1559: */
1560: for (i = 0, p = who; ; p++) {
1561: if (i == SLOT_NAMEMAX - 1 || *p == '\0') {
1562: name[i] = '\0';
1563: break;
1564: } else if (*p >= 'A' && *p <= 'Z') {
1565: name[i++] = *p + 'a' - 'A';
1566: } else if (*p >= 'a' && *p <= 'z')
1567: name[i++] = *p;
1568: }
1569: if (i == 0)
1570: strlcpy(name, "noname", SLOT_NAMEMAX);
1571:
1572: /*
1573: * find the first unused "unit" number for this name
1574: */
1575: for (i = 0, s = d->slot; i < DEV_NSLOT; i++, s++) {
1576: if (s->ops == NULL)
1577: continue;
1578: if (strcmp(s->name, name) == 0)
1579: umap |= (1 << s->unit);
1580: }
1581: for (unit = 0; ; unit++) {
1582: if ((umap & (1 << unit)) == 0)
1583: break;
1584: }
1585:
1586: /*
1.18 ratchov 1587: * find a free controller slot with the same name/unit
1.1 ratchov 1588: */
1589: for (i = 0, s = d->slot; i < DEV_NSLOT; i++, s++) {
1590: if (s->ops == NULL &&
1591: strcmp(s->name, name) == 0 &&
1592: s->unit == unit) {
1593: #ifdef DEBUG
1594: if (log_level >= 3) {
1595: log_puts(name);
1596: log_putu(unit);
1597: log_puts(": reused\n");
1598: }
1599: #endif
1600: goto found;
1601: }
1602: }
1603:
1604: /*
1.18 ratchov 1605: * couldn't find a matching slot, pick oldest free slot
1.1 ratchov 1606: * and set its name/unit
1607: */
1608: bestser = 0;
1609: bestidx = DEV_NSLOT;
1610: for (i = 0, s = d->slot; i < DEV_NSLOT; i++, s++) {
1611: if (s->ops != NULL)
1612: continue;
1613: ser = d->serial - s->serial;
1614: if (ser > bestser) {
1615: bestser = ser;
1616: bestidx = i;
1617: }
1618: }
1619: if (bestidx == DEV_NSLOT) {
1620: if (log_level >= 1) {
1621: log_puts(name);
1622: log_putu(unit);
1623: log_puts(": out of sub-device slots\n");
1624: }
1625: return NULL;
1626: }
1627: s = d->slot + bestidx;
1628: if (s->name[0] != '\0')
1629: s->vol = MIDI_MAXCTL;
1630: strlcpy(s->name, name, SLOT_NAMEMAX);
1631: s->serial = d->serial++;
1632: s->unit = unit;
1633: #ifdef DEBUG
1634: if (log_level >= 3) {
1635: log_puts(name);
1636: log_putu(unit);
1637: log_puts(": overwritten slot ");
1638: log_putu(bestidx);
1639: log_puts("\n");
1640: }
1641: #endif
1642:
1643: found:
1.37 ! ratchov 1644: if ((mode & MODE_REC) && (opt->mode & MODE_MON)) {
! 1645: mode |= MODE_MON;
! 1646: mode &= ~MODE_REC;
! 1647: }
! 1648: if ((mode & opt->mode) != mode) {
! 1649: if (log_level >= 1) {
! 1650: slot_log(s);
! 1651: log_puts(": requested mode not allowed\n");
! 1652: }
! 1653: return 0;
! 1654: }
1.1 ratchov 1655: if (!dev_ref(d))
1656: return NULL;
1.31 ratchov 1657: if ((mode & d->mode) != mode) {
1.1 ratchov 1658: if (log_level >= 1) {
1659: slot_log(s);
1660: log_puts(": requested mode not supported\n");
1661: }
1.31 ratchov 1662: dev_unref(d);
1.1 ratchov 1663: return 0;
1664: }
1.31 ratchov 1665: s->dev = d;
1.37 ! ratchov 1666: s->opt = opt;
1.31 ratchov 1667: s->ops = ops;
1668: s->arg = arg;
1669: s->pstate = SLOT_INIT;
1.1 ratchov 1670: s->mode = mode;
1.6 ratchov 1671: aparams_init(&s->par);
1.1 ratchov 1672: if (s->mode & MODE_PLAY) {
1.37 ! ratchov 1673: s->mix.slot_cmin = s->mix.dev_cmin = s->opt->pmin;
! 1674: s->mix.slot_cmax = s->mix.dev_cmax = s->opt->pmax;
1.1 ratchov 1675: }
1676: if (s->mode & MODE_RECMASK) {
1.37 ! ratchov 1677: s->sub.slot_cmin = s->sub.dev_cmin = s->opt->rmin;
! 1678: s->sub.slot_cmax = s->sub.dev_cmax = s->opt->rmax;
! 1679: }
! 1680: if (s->opt->mmc) {
! 1681: s->xrun = XRUN_SYNC;
! 1682: s->tstate = MMC_STOP;
! 1683: } else {
! 1684: s->xrun = XRUN_IGNORE;
! 1685: s->tstate = MMC_OFF;
1.1 ratchov 1686: }
1.37 ! ratchov 1687: s->mix.maxweight = s->opt->maxweight;
! 1688: s->dup = s->opt->dup;
1.1 ratchov 1689: s->appbufsz = d->bufsz;
1690: s->round = d->round;
1.5 ratchov 1691: s->rate = d->rate;
1.1 ratchov 1692: dev_midi_slotdesc(d, s);
1693: dev_midi_vol(d, s);
1694: return s;
1695: }
1696:
1697: /*
1698: * release the given slot
1699: */
1700: void
1701: slot_del(struct slot *s)
1702: {
1703: s->arg = s;
1704: s->ops = &zomb_slotops;
1705: switch (s->pstate) {
1706: case SLOT_INIT:
1707: s->ops = NULL;
1708: break;
1709: case SLOT_START:
1710: case SLOT_READY:
1711: case SLOT_RUN:
1712: slot_stop(s);
1713: /* PASSTHROUGH */
1714: case SLOT_STOP:
1715: break;
1716: }
1717: dev_unref(s->dev);
1718: s->dev = NULL;
1719: }
1720:
1721: /*
1722: * change the slot play volume; called either by the slot or by MIDI
1723: */
1724: void
1725: slot_setvol(struct slot *s, unsigned int vol)
1726: {
1727: #ifdef DEBUG
1728: if (log_level >= 3) {
1729: slot_log(s);
1730: log_puts(": setting volume ");
1731: log_putu(vol);
1732: log_puts("\n");
1733: }
1734: #endif
1735: s->vol = vol;
1736: if (s->ops == NULL)
1737: return;
1738: s->mix.vol = MIDI_TO_ADATA(s->vol);
1739: }
1740:
1741: /*
1742: * attach the slot to the device (ie start playing & recording
1743: */
1744: void
1745: slot_attach(struct slot *s)
1746: {
1747: struct dev *d = s->dev;
1.12 ratchov 1748: long long pos;
1.1 ratchov 1749: int startpos;
1750:
1751: /*
1752: * start the device if not started
1753: */
1754: dev_wakeup(d);
1.23 ratchov 1755:
1.1 ratchov 1756: /*
1757: * get the current position, the origin is when the first sample
1758: * played and/or recorded
1759: */
1760: startpos = dev_getpos(d) * (int)s->round / (int)d->round;
1.12 ratchov 1761:
1762: /*
1763: * adjust initial clock
1764: */
1765: pos = (long long)d->delta * s->round;
1766: s->delta = startpos + pos / (int)d->round;
1767: s->delta_rem = pos % d->round;
1768:
1.1 ratchov 1769: s->pstate = SLOT_RUN;
1770: #ifdef DEBUG
1.17 ratchov 1771: if (log_level >= 2) {
1.1 ratchov 1772: slot_log(s);
1773: log_puts(": attached at ");
1774: log_puti(startpos);
1.12 ratchov 1775: log_puts(", delta = ");
1776: log_puti(d->delta);
1.1 ratchov 1777: log_puts("\n");
1778: }
1779: #endif
1780:
1781: /*
1782: * We dont check whether the device is dying,
1783: * because dev_xxx() functions are supposed to
1784: * work (i.e., not to crash)
1785: */
1786: #ifdef DEBUG
1787: if ((s->mode & d->mode) != s->mode) {
1788: slot_log(s);
1.24 ratchov 1789: log_puts(": mode beyond device mode, not attaching\n");
1.1 ratchov 1790: panic();
1791: }
1792: #endif
1793: s->next = d->slot_list;
1794: d->slot_list = s;
1.12 ratchov 1795: s->skip = 0;
1.1 ratchov 1796: if (s->mode & MODE_PLAY) {
1797: s->mix.vol = MIDI_TO_ADATA(s->vol);
1798: dev_mix_adjvol(d);
1799: }
1800: if (s->mode & MODE_RECMASK) {
1801: /*
1802: * N-th recorded block is the N-th played block
1803: */
1.12 ratchov 1804: s->sub.prime = -startpos / (int)s->round;
1.1 ratchov 1805: }
1806: }
1807:
1808: /*
1809: * if MMC is enabled, and try to attach all slots synchronously, else
1810: * simply attach the slot
1811: */
1812: void
1813: slot_ready(struct slot *s)
1814: {
1.3 ratchov 1815: /*
1816: * device may be disconnected, and if so we're called from
1817: * slot->ops->exit() on a closed device
1.23 ratchov 1818: */
1.3 ratchov 1819: if (s->dev->pstate == DEV_CFG)
1820: return;
1.1 ratchov 1821: if (s->tstate == MMC_OFF)
1822: slot_attach(s);
1823: else {
1824: s->tstate = MMC_START;
1825: dev_sync_attach(s->dev);
1826: }
1827: }
1828:
1829: /*
1830: * setup buffers & conversion layers, prepare the slot to receive data
1831: * (for playback) or start (recording).
1832: */
1833: void
1834: slot_start(struct slot *s)
1835: {
1836: #ifdef DEBUG
1837: if (s->pstate != SLOT_INIT) {
1838: slot_log(s);
1839: log_puts(": slot_start: wrong state\n");
1840: panic();
1841: }
1842: if (s->mode & MODE_PLAY) {
1843: if (log_level >= 3) {
1844: slot_log(s);
1845: log_puts(": playing ");
1846: aparams_log(&s->par);
1847: log_puts(" -> ");
1.35 ratchov 1848: aparams_log(&s->dev->par);
1.1 ratchov 1849: log_puts("\n");
1850: }
1851: }
1852: if (s->mode & MODE_RECMASK) {
1853: if (log_level >= 3) {
1854: slot_log(s);
1855: log_puts(": recording ");
1856: aparams_log(&s->par);
1857: log_puts(" <- ");
1.35 ratchov 1858: aparams_log(&s->dev->par);
1.1 ratchov 1859: log_puts("\n");
1.35 ratchov 1860: }
1.1 ratchov 1861: }
1862: #endif
1.35 ratchov 1863: slot_allocbufs(s);
1.1 ratchov 1864: s->mix.weight = MIDI_TO_ADATA(MIDI_MAXCTL);
1865: if (s->mode & MODE_PLAY) {
1866: s->pstate = SLOT_START;
1867: } else {
1868: s->pstate = SLOT_READY;
1869: slot_ready(s);
1870: }
1871: }
1872:
1873: /*
1874: * stop playback and recording, and free conversion layers
1875: */
1876: void
1877: slot_detach(struct slot *s)
1878: {
1879: struct slot **ps;
1880:
1881: #ifdef DEBUG
1882: if (log_level >= 3) {
1883: slot_log(s);
1884: log_puts(": detaching\n");
1885: }
1886: #endif
1887: for (ps = &s->dev->slot_list; *ps != s; ps = &(*ps)->next) {
1888: #ifdef DEBUG
1.28 ratchov 1889: if (*ps == NULL) {
1.1 ratchov 1890: slot_log(s);
1891: log_puts(": can't detach, not on list\n");
1892: panic();
1893: }
1894: #endif
1.23 ratchov 1895: }
1.1 ratchov 1896: *ps = s->next;
1.35 ratchov 1897: if (s->mode & MODE_PLAY)
1.1 ratchov 1898: dev_mix_adjvol(s->dev);
1899: }
1900:
1901: /*
1902: * put the slot in stopping state (draining play buffers) or
1903: * stop & detach if no data to drain.
1904: */
1905: void
1906: slot_stop(struct slot *s)
1907: {
1908: #ifdef DEBUG
1909: if (log_level >= 3) {
1910: slot_log(s);
1911: log_puts(": stopping\n");
1912: }
1913: #endif
1914: if (s->pstate == SLOT_START) {
1.33 ratchov 1915: /*
1916: * If in rec-only mode, we're already in the READY or
1917: * RUN states. We're here because the play buffer was
1918: * not full enough, try to start so it's drained.
1919: */
1920: s->pstate = SLOT_READY;
1921: slot_ready(s);
1.1 ratchov 1922: }
1.34 ratchov 1923:
1924: if (s->tstate != MMC_OFF)
1925: s->tstate = MMC_STOP;
1926:
1927: if (s->pstate == SLOT_RUN) {
1928: if (s->mode & MODE_PLAY) {
1929: /*
1930: * Don't detach, dev_cycle() will do it for us
1931: * when the buffer is drained.
1932: */
1933: s->pstate = SLOT_STOP;
1934: return;
1935: }
1936: slot_detach(s);
1937: } else {
1.1 ratchov 1938: #ifdef DEBUG
1939: if (log_level >= 3) {
1940: slot_log(s);
1941: log_puts(": not drained (blocked by mmc)\n");
1942: }
1943: #endif
1944: }
1.35 ratchov 1945:
1.34 ratchov 1946: s->pstate = SLOT_INIT;
1947: s->ops->eof(s->arg);
1.35 ratchov 1948: slot_freebufs(s);
1.1 ratchov 1949: }
1950:
1.12 ratchov 1951: void
1952: slot_skip_update(struct slot *s)
1953: {
1954: int skip;
1955:
1956: skip = slot_skip(s);
1957: while (skip > 0) {
1958: #ifdef DEBUG
1959: if (log_level >= 4) {
1960: slot_log(s);
1961: log_puts(": catching skipped block\n");
1962: }
1963: #endif
1964: if (s->mode & MODE_RECMASK)
1965: s->ops->flush(s->arg);
1966: if (s->mode & MODE_PLAY)
1967: s->ops->fill(s->arg);
1968: skip--;
1969: }
1970: }
1971:
1.1 ratchov 1972: /*
1973: * notify the slot that we just wrote in the play buffer, must be called
1974: * after each write
1975: */
1976: void
1977: slot_write(struct slot *s)
1978: {
1979: if (s->pstate == SLOT_START && s->mix.buf.used == s->mix.buf.len) {
1980: #ifdef DEBUG
1981: if (log_level >= 4) {
1982: slot_log(s);
1983: log_puts(": switching to READY state\n");
1984: }
1985: #endif
1986: s->pstate = SLOT_READY;
1987: slot_ready(s);
1988: }
1.12 ratchov 1989: slot_skip_update(s);
1.1 ratchov 1990: }
1991:
1992: /*
1993: * notify the slot that we freed some space in the rec buffer
1994: */
1995: void
1996: slot_read(struct slot *s)
1997: {
1.12 ratchov 1998: slot_skip_update(s);
1.1 ratchov 1999: }