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