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