Annotation of src/usr.bin/sndiod/dev.c, Revision 1.55
1.55 ! ratchov 1: /* $OpenBSD: dev.c,v 1.54 2019/07/12 06:30:55 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: /*
1.55 ! ratchov 1111: * Force all slots to exit
! 1112: */
! 1113: void
! 1114: dev_exitall(struct dev *d)
! 1115: {
! 1116: int i;
! 1117: struct slot *s;
! 1118:
! 1119: for (s = d->slot, i = DEV_NSLOT; i > 0; i--, s++) {
! 1120: if (s->ops)
! 1121: s->ops->exit(s->arg);
! 1122: s->ops = NULL;
! 1123: }
! 1124: d->slot_list = NULL;
! 1125: }
! 1126:
! 1127: /*
1.1 ratchov 1128: * force the device to go in DEV_CFG state, the caller is supposed to
1129: * ensure buffers are drained
1130: */
1131: void
1132: dev_close(struct dev *d)
1133: {
1134: #ifdef DEBUG
1135: if (log_level >= 3) {
1136: dev_log(d);
1137: log_puts(": closing\n");
1138: }
1139: #endif
1.3 ratchov 1140: d->pstate = DEV_CFG;
1.55 ! ratchov 1141: dev_exitall(d);
1.1 ratchov 1142: dev_sio_close(d);
1143: if (d->mode & MODE_PLAY) {
1144: if (d->encbuf != NULL)
1145: xfree(d->encbuf);
1146: xfree(d->pbuf);
1147: }
1148: if (d->mode & MODE_REC) {
1149: if (d->decbuf != NULL)
1150: xfree(d->decbuf);
1151: xfree(d->rbuf);
1152: }
1153: }
1154:
1155: int
1156: dev_ref(struct dev *d)
1157: {
1158: #ifdef DEBUG
1159: if (log_level >= 3) {
1160: dev_log(d);
1161: log_puts(": device requested\n");
1162: }
1163: #endif
1164: if (d->pstate == DEV_CFG && !dev_open(d))
1165: return 0;
1166: d->refcnt++;
1167: return 1;
1168: }
1169:
1170: void
1171: dev_unref(struct dev *d)
1172: {
1173: #ifdef DEBUG
1174: if (log_level >= 3) {
1175: dev_log(d);
1176: log_puts(": device released\n");
1177: }
1178: #endif
1179: d->refcnt--;
1180: if (d->refcnt == 0 && d->pstate == DEV_INIT)
1181: dev_close(d);
1182: }
1183:
1184: /*
1185: * initialize the device with the current parameters
1186: */
1187: int
1188: dev_init(struct dev *d)
1189: {
1190: if ((d->reqmode & MODE_AUDIOMASK) == 0) {
1191: #ifdef DEBUG
1192: dev_log(d);
1193: log_puts(": has no streams\n");
1194: #endif
1195: return 0;
1196: }
1197: if (d->hold && !dev_ref(d))
1198: return 0;
1199: return 1;
1200: }
1201:
1202: /*
1203: * Unless the device is already in process of closing, request it to close
1204: */
1205: void
1206: dev_done(struct dev *d)
1207: {
1208: #ifdef DEBUG
1209: if (log_level >= 3) {
1210: dev_log(d);
1211: log_puts(": draining\n");
1212: }
1213: #endif
1.20 ratchov 1214: if (d->tstate != MMC_STOP)
1215: dev_mmcstop(d);
1.1 ratchov 1216: if (d->hold)
1217: dev_unref(d);
1218: }
1219:
1220: struct dev *
1221: dev_bynum(int num)
1222: {
1223: struct dev *d;
1224:
1225: for (d = dev_list; d != NULL; d = d->next) {
1.19 ratchov 1226: if (d->num == num)
1.1 ratchov 1227: return d;
1228: }
1229: return NULL;
1230: }
1231:
1232: /*
1233: * Free the device
1234: */
1235: void
1236: dev_del(struct dev *d)
1237: {
1238: struct dev **p;
1239:
1240: #ifdef DEBUG
1241: if (log_level >= 3) {
1242: dev_log(d);
1243: log_puts(": deleting\n");
1244: }
1245: #endif
1.36 ratchov 1246: while (d->opt_list != NULL)
1247: opt_del(d, d->opt_list);
1.1 ratchov 1248: if (d->pstate != DEV_CFG)
1249: dev_close(d);
1250: for (p = &dev_list; *p != d; p = &(*p)->next) {
1251: #ifdef DEBUG
1252: if (*p == NULL) {
1253: dev_log(d);
1254: log_puts(": device to delete not on the list\n");
1255: panic();
1256: }
1257: #endif
1258: }
1259: midi_del(d->midi);
1260: *p = d->next;
1.21 ratchov 1261: xfree(d->path);
1.1 ratchov 1262: xfree(d);
1263: }
1264:
1265: unsigned int
1266: dev_roundof(struct dev *d, unsigned int newrate)
1267: {
1268: return (d->round * newrate + d->rate / 2) / d->rate;
1269: }
1270:
1271: /*
1272: * If the device is paused, then resume it.
1273: */
1274: void
1275: dev_wakeup(struct dev *d)
1276: {
1277: if (d->pstate == DEV_INIT) {
1278: if (log_level >= 2) {
1279: dev_log(d);
1280: log_puts(": device started\n");
1281: }
1282: if (d->mode & MODE_PLAY) {
1283: d->prime = d->bufsz;
1284: } else {
1285: d->prime = 0;
1286: }
1.16 ratchov 1287: d->poffs = 0;
1.12 ratchov 1288:
1.23 ratchov 1289: /*
1.16 ratchov 1290: * empty cycles don't increment delta, so it's ok to
1291: * start at 0
1292: **/
1.23 ratchov 1293: d->delta = 0;
1.12 ratchov 1294:
1.1 ratchov 1295: d->pstate = DEV_RUN;
1296: dev_sio_start(d);
1297: }
1298: }
1299:
1300: /*
1301: * check that all clients controlled by MMC are ready to start, if so,
1302: * attach them all at the same position
1303: */
1304: void
1305: dev_sync_attach(struct dev *d)
1306: {
1307: int i;
1308: struct slot *s;
1309:
1310: if (d->tstate != MMC_START) {
1311: if (log_level >= 2) {
1312: dev_log(d);
1313: log_puts(": not started by mmc yet, waiting...\n");
1314: }
1315: return;
1316: }
1317: for (i = 0; i < DEV_NSLOT; i++) {
1318: s = d->slot + i;
1.46 ratchov 1319: if (!s->ops || !s->opt->mmc)
1.1 ratchov 1320: continue;
1.46 ratchov 1321: if (s->pstate != SLOT_READY) {
1.1 ratchov 1322: #ifdef DEBUG
1323: if (log_level >= 3) {
1324: slot_log(s);
1325: log_puts(": not ready, start delayed\n");
1326: }
1327: #endif
1328: return;
1329: }
1330: }
1331: if (!dev_ref(d))
1332: return;
1333: for (i = 0; i < DEV_NSLOT; i++) {
1334: s = d->slot + i;
1.46 ratchov 1335: if (!s->ops || !s->opt->mmc)
1.1 ratchov 1336: continue;
1.46 ratchov 1337: slot_attach(s);
1.1 ratchov 1338: }
1339: d->tstate = MMC_RUN;
1340: dev_midi_full(d);
1341: dev_wakeup(d);
1342: }
1343:
1344: /*
1345: * start all slots simultaneously
1346: */
1347: void
1348: dev_mmcstart(struct dev *d)
1349: {
1350: if (d->tstate == MMC_STOP) {
1351: d->tstate = MMC_START;
1352: dev_sync_attach(d);
1353: #ifdef DEBUG
1354: } else {
1355: if (log_level >= 3) {
1356: dev_log(d);
1357: log_puts(": ignoring mmc start\n");
1358: }
1359: #endif
1360: }
1361: }
1362:
1363: /*
1364: * stop all slots simultaneously
1365: */
1366: void
1367: dev_mmcstop(struct dev *d)
1368: {
1369: switch (d->tstate) {
1370: case MMC_START:
1371: d->tstate = MMC_STOP;
1372: return;
1373: case MMC_RUN:
1374: d->tstate = MMC_STOP;
1375: dev_unref(d);
1376: break;
1377: default:
1378: #ifdef DEBUG
1379: if (log_level >= 3) {
1380: dev_log(d);
1381: log_puts(": ignored mmc stop\n");
1382: }
1383: #endif
1384: return;
1385: }
1386: }
1387:
1388: /*
1389: * relocate all slots simultaneously
1390: */
1391: void
1392: dev_mmcloc(struct dev *d, unsigned int origin)
1393: {
1394: if (log_level >= 2) {
1395: dev_log(d);
1396: log_puts(": relocated to ");
1397: log_putu(origin);
1398: log_puts("\n");
1399: }
1400: if (d->tstate == MMC_RUN)
1401: dev_mmcstop(d);
1402: d->mtc.origin = origin;
1403: if (d->tstate == MMC_RUN)
1404: dev_mmcstart(d);
1405: }
1406:
1.35 ratchov 1407:
1408: /*
1409: * allocate buffers & conversion chain
1410: */
1411: void
1412: slot_allocbufs(struct slot *s)
1413: {
1.42 ratchov 1414: unsigned int dev_nch;
1.35 ratchov 1415: struct dev *d = s->dev;
1416:
1417: if (s->mode & MODE_PLAY) {
1.42 ratchov 1418: s->mix.bpf = s->par.bps * s->mix.nch;
1.35 ratchov 1419: abuf_init(&s->mix.buf, s->appbufsz * s->mix.bpf);
1420:
1.40 ratchov 1421: dev_nch = s->opt->pmax - s->opt->pmin + 1;
1.35 ratchov 1422: s->mix.decbuf = NULL;
1423: s->mix.resampbuf = NULL;
1424: s->mix.join = 1;
1425: s->mix.expand = 1;
1.39 ratchov 1426: if (s->opt->dup) {
1.42 ratchov 1427: if (dev_nch > s->mix.nch)
1428: s->mix.expand = dev_nch / s->mix.nch;
1429: else if (dev_nch < s->mix.nch)
1430: s->mix.join = s->mix.nch / dev_nch;
1.35 ratchov 1431: }
1432: cmap_init(&s->mix.cmap,
1.42 ratchov 1433: s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1434: s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1.35 ratchov 1435: 0, d->pchan - 1,
1.40 ratchov 1436: s->opt->pmin, s->opt->pmax);
1.35 ratchov 1437: if (!aparams_native(&s->par)) {
1.42 ratchov 1438: dec_init(&s->mix.dec, &s->par, s->mix.nch);
1.35 ratchov 1439: s->mix.decbuf =
1.42 ratchov 1440: xmalloc(s->round * s->mix.nch * sizeof(adata_t));
1.35 ratchov 1441: }
1442: if (s->rate != d->rate) {
1443: resamp_init(&s->mix.resamp, s->round, d->round,
1.42 ratchov 1444: s->mix.nch);
1.35 ratchov 1445: s->mix.resampbuf =
1.42 ratchov 1446: xmalloc(d->round * s->mix.nch * sizeof(adata_t));
1.35 ratchov 1447: }
1448: }
1449:
1450: if (s->mode & MODE_RECMASK) {
1.42 ratchov 1451: s->sub.bpf = s->par.bps * s->sub.nch;
1.35 ratchov 1452: abuf_init(&s->sub.buf, s->appbufsz * s->sub.bpf);
1453:
1.40 ratchov 1454: dev_nch = s->opt->rmax - s->opt->rmin + 1;
1.35 ratchov 1455: s->sub.encbuf = NULL;
1456: s->sub.resampbuf = NULL;
1457: s->sub.join = 1;
1458: s->sub.expand = 1;
1.39 ratchov 1459: if (s->opt->dup) {
1.42 ratchov 1460: if (dev_nch > s->sub.nch)
1461: s->sub.join = dev_nch / s->sub.nch;
1462: else if (dev_nch < s->sub.nch)
1463: s->sub.expand = s->sub.nch / dev_nch;
1.35 ratchov 1464: }
1465: cmap_init(&s->sub.cmap,
1466: 0, ((s->mode & MODE_MON) ? d->pchan : d->rchan) - 1,
1.40 ratchov 1467: s->opt->rmin, s->opt->rmax,
1.42 ratchov 1468: s->opt->rmin, s->opt->rmin + s->sub.nch - 1,
1469: s->opt->rmin, s->opt->rmin + s->sub.nch - 1);
1.35 ratchov 1470: if (s->rate != d->rate) {
1471: resamp_init(&s->sub.resamp, d->round, s->round,
1.42 ratchov 1472: s->sub.nch);
1.35 ratchov 1473: s->sub.resampbuf =
1.42 ratchov 1474: xmalloc(d->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1475: }
1476: if (!aparams_native(&s->par)) {
1.42 ratchov 1477: enc_init(&s->sub.enc, &s->par, s->sub.nch);
1.35 ratchov 1478: s->sub.encbuf =
1.42 ratchov 1479: xmalloc(s->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1480: }
1481:
1482: /*
1483: * cmap_copy() doesn't write samples in all channels,
1484: * for instance when mono->stereo conversion is
1485: * disabled. So we have to prefill cmap_copy() output
1486: * with silence.
1487: */
1488: if (s->sub.resampbuf) {
1489: memset(s->sub.resampbuf, 0,
1.42 ratchov 1490: d->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1491: } else if (s->sub.encbuf) {
1492: memset(s->sub.encbuf, 0,
1.42 ratchov 1493: s->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1494: } else {
1495: memset(s->sub.buf.data, 0,
1.42 ratchov 1496: s->appbufsz * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1497: }
1498: }
1499:
1500: #ifdef DEBUG
1501: if (log_level >= 3) {
1502: slot_log(s);
1503: log_puts(": allocated ");
1504: log_putu(s->appbufsz);
1505: log_puts("/");
1506: log_putu(SLOT_BUFSZ(s));
1507: log_puts(" fr buffers\n");
1508: }
1509: #endif
1510: }
1511:
1512: /*
1513: * free buffers & conversion chain
1514: */
1515: void
1516: slot_freebufs(struct slot *s)
1517: {
1518: if (s->mode & MODE_RECMASK) {
1519: abuf_done(&s->sub.buf);
1520: if (s->sub.encbuf)
1521: xfree(s->sub.encbuf);
1522: if (s->sub.resampbuf)
1523: xfree(s->sub.resampbuf);
1524: }
1525:
1526: if (s->mode & MODE_PLAY) {
1527: abuf_done(&s->mix.buf);
1528: if (s->mix.decbuf)
1529: xfree(s->mix.decbuf);
1530: if (s->mix.resampbuf)
1531: xfree(s->mix.resampbuf);
1532: }
1533: }
1534:
1.1 ratchov 1535: /*
1536: * allocate a new slot and register the given call-backs
1537: */
1538: struct slot *
1.54 ratchov 1539: slot_new(struct dev *d, struct opt *opt, unsigned int id, char *who,
1.37 ratchov 1540: struct slotops *ops, void *arg, int mode)
1.1 ratchov 1541: {
1542: char *p;
1543: char name[SLOT_NAMEMAX];
1.52 ratchov 1544: unsigned int i, ser, bestser, bestidx;
1545: struct slot *unit[DEV_NSLOT];
1.1 ratchov 1546: struct slot *s;
1547:
1548: /*
1.27 ratchov 1549: * create a ``valid'' control name (lowcase, remove [^a-z], truncate)
1.1 ratchov 1550: */
1551: for (i = 0, p = who; ; p++) {
1552: if (i == SLOT_NAMEMAX - 1 || *p == '\0') {
1553: name[i] = '\0';
1554: break;
1555: } else if (*p >= 'A' && *p <= 'Z') {
1556: name[i++] = *p + 'a' - 'A';
1557: } else if (*p >= 'a' && *p <= 'z')
1558: name[i++] = *p;
1559: }
1560: if (i == 0)
1561: strlcpy(name, "noname", SLOT_NAMEMAX);
1562:
1563: /*
1.52 ratchov 1564: * build a unit-to-slot map for this name
1.1 ratchov 1565: */
1.52 ratchov 1566: for (i = 0; i < DEV_NSLOT; i++)
1567: unit[i] = NULL;
1568: for (i = 0; i < DEV_NSLOT; i++) {
1569: s = d->slot + i;
1.1 ratchov 1570: if (strcmp(s->name, name) == 0)
1.52 ratchov 1571: unit[s->unit] = s;
1.1 ratchov 1572: }
1573:
1574: /*
1.54 ratchov 1575: * find the free slot with the least unit number and same id
1576: */
1577: for (i = 0; i < DEV_NSLOT; i++) {
1578: s = unit[i];
1579: if (s != NULL && s->ops == NULL && s->id == id)
1580: goto found;
1581: }
1582:
1583: /*
1.52 ratchov 1584: * find the free slot with the least unit number
1.1 ratchov 1585: */
1.52 ratchov 1586: for (i = 0; i < DEV_NSLOT; i++) {
1587: s = unit[i];
1.54 ratchov 1588: if (s != NULL && s->ops == NULL) {
1589: s->id = id;
1.1 ratchov 1590: goto found;
1.54 ratchov 1591: }
1.1 ratchov 1592: }
1593:
1594: /*
1.18 ratchov 1595: * couldn't find a matching slot, pick oldest free slot
1.1 ratchov 1596: * and set its name/unit
1597: */
1598: bestser = 0;
1599: bestidx = DEV_NSLOT;
1600: for (i = 0, s = d->slot; i < DEV_NSLOT; i++, s++) {
1601: if (s->ops != NULL)
1602: continue;
1603: ser = d->serial - s->serial;
1604: if (ser > bestser) {
1605: bestser = ser;
1606: bestidx = i;
1607: }
1608: }
1.51 ratchov 1609: if (bestidx != DEV_NSLOT) {
1610: s = d->slot + bestidx;
1611: s->vol = MIDI_MAXCTL;
1612: strlcpy(s->name, name, SLOT_NAMEMAX);
1613: s->serial = d->serial++;
1.52 ratchov 1614: for (i = 0; unit[i] != NULL; i++)
1615: ; /* nothing */
1616: s->unit = i;
1.54 ratchov 1617: s->id = id;
1.51 ratchov 1618: goto found;
1.1 ratchov 1619: }
1.53 ratchov 1620:
1.51 ratchov 1621: if (log_level >= 1) {
1.1 ratchov 1622: log_puts(name);
1.51 ratchov 1623: log_puts(": out of sub-device slots\n");
1.1 ratchov 1624: }
1.51 ratchov 1625: return NULL;
1.1 ratchov 1626:
1627: found:
1.37 ratchov 1628: if ((mode & MODE_REC) && (opt->mode & MODE_MON)) {
1629: mode |= MODE_MON;
1630: mode &= ~MODE_REC;
1631: }
1632: if ((mode & opt->mode) != mode) {
1633: if (log_level >= 1) {
1634: slot_log(s);
1635: log_puts(": requested mode not allowed\n");
1636: }
1637: return 0;
1638: }
1.1 ratchov 1639: if (!dev_ref(d))
1640: return NULL;
1.31 ratchov 1641: if ((mode & d->mode) != mode) {
1.1 ratchov 1642: if (log_level >= 1) {
1643: slot_log(s);
1644: log_puts(": requested mode not supported\n");
1645: }
1.31 ratchov 1646: dev_unref(d);
1.49 ratchov 1647: return NULL;
1.1 ratchov 1648: }
1.31 ratchov 1649: s->dev = d;
1.37 ratchov 1650: s->opt = opt;
1.31 ratchov 1651: s->ops = ops;
1652: s->arg = arg;
1653: s->pstate = SLOT_INIT;
1.1 ratchov 1654: s->mode = mode;
1.6 ratchov 1655: aparams_init(&s->par);
1.41 ratchov 1656: if (s->mode & MODE_PLAY)
1.42 ratchov 1657: s->mix.nch = s->opt->pmax - s->opt->pmin + 1;
1.41 ratchov 1658: if (s->mode & MODE_RECMASK)
1.42 ratchov 1659: s->sub.nch = s->opt->rmax - s->opt->rmin + 1;
1.46 ratchov 1660: s->xrun = s->opt->mmc ? XRUN_SYNC : XRUN_IGNORE;
1.1 ratchov 1661: s->appbufsz = d->bufsz;
1662: s->round = d->round;
1.5 ratchov 1663: s->rate = d->rate;
1.1 ratchov 1664: dev_midi_slotdesc(d, s);
1665: dev_midi_vol(d, s);
1.43 ratchov 1666: #ifdef DEBUG
1667: if (log_level >= 3) {
1668: slot_log(s);
1669: log_puts(": using ");
1670: dev_log(d);
1671: log_puts(".");
1672: log_puts(opt->name);
1673: log_puts(", mode = ");
1674: log_putx(mode);
1675: log_puts("\n");
1676: }
1677: #endif
1.1 ratchov 1678: return s;
1679: }
1680:
1681: /*
1682: * release the given slot
1683: */
1684: void
1685: slot_del(struct slot *s)
1686: {
1687: s->arg = s;
1688: s->ops = &zomb_slotops;
1689: switch (s->pstate) {
1690: case SLOT_INIT:
1691: s->ops = NULL;
1692: break;
1693: case SLOT_START:
1694: case SLOT_READY:
1695: case SLOT_RUN:
1696: slot_stop(s);
1697: /* PASSTHROUGH */
1698: case SLOT_STOP:
1699: break;
1700: }
1701: dev_unref(s->dev);
1702: s->dev = NULL;
1703: }
1704:
1705: /*
1706: * change the slot play volume; called either by the slot or by MIDI
1707: */
1708: void
1709: slot_setvol(struct slot *s, unsigned int vol)
1710: {
1711: #ifdef DEBUG
1712: if (log_level >= 3) {
1713: slot_log(s);
1714: log_puts(": setting volume ");
1715: log_putu(vol);
1716: log_puts("\n");
1717: }
1718: #endif
1719: s->vol = vol;
1720: s->mix.vol = MIDI_TO_ADATA(s->vol);
1721: }
1722:
1723: /*
1724: * attach the slot to the device (ie start playing & recording
1725: */
1726: void
1727: slot_attach(struct slot *s)
1728: {
1729: struct dev *d = s->dev;
1.12 ratchov 1730: long long pos;
1.1 ratchov 1731: int startpos;
1732:
1733: /*
1734: * start the device if not started
1735: */
1736: dev_wakeup(d);
1.23 ratchov 1737:
1.1 ratchov 1738: /*
1739: * get the current position, the origin is when the first sample
1740: * played and/or recorded
1741: */
1742: startpos = dev_getpos(d) * (int)s->round / (int)d->round;
1.12 ratchov 1743:
1744: /*
1745: * adjust initial clock
1746: */
1747: pos = (long long)d->delta * s->round;
1748: s->delta = startpos + pos / (int)d->round;
1749: s->delta_rem = pos % d->round;
1750:
1.1 ratchov 1751: s->pstate = SLOT_RUN;
1752: #ifdef DEBUG
1.17 ratchov 1753: if (log_level >= 2) {
1.1 ratchov 1754: slot_log(s);
1755: log_puts(": attached at ");
1756: log_puti(startpos);
1.12 ratchov 1757: log_puts(", delta = ");
1758: log_puti(d->delta);
1.1 ratchov 1759: log_puts("\n");
1760: }
1761: #endif
1762:
1763: /*
1764: * We dont check whether the device is dying,
1765: * because dev_xxx() functions are supposed to
1766: * work (i.e., not to crash)
1767: */
1768: #ifdef DEBUG
1769: if ((s->mode & d->mode) != s->mode) {
1770: slot_log(s);
1.24 ratchov 1771: log_puts(": mode beyond device mode, not attaching\n");
1.1 ratchov 1772: panic();
1773: }
1774: #endif
1775: s->next = d->slot_list;
1776: d->slot_list = s;
1777: if (s->mode & MODE_PLAY) {
1778: s->mix.vol = MIDI_TO_ADATA(s->vol);
1779: dev_mix_adjvol(d);
1780: }
1781: }
1782:
1783: /*
1784: * if MMC is enabled, and try to attach all slots synchronously, else
1785: * simply attach the slot
1786: */
1787: void
1788: slot_ready(struct slot *s)
1789: {
1.3 ratchov 1790: /*
1791: * device may be disconnected, and if so we're called from
1792: * slot->ops->exit() on a closed device
1.23 ratchov 1793: */
1.3 ratchov 1794: if (s->dev->pstate == DEV_CFG)
1795: return;
1.46 ratchov 1796: if (!s->opt->mmc)
1.1 ratchov 1797: slot_attach(s);
1.46 ratchov 1798: else
1.1 ratchov 1799: dev_sync_attach(s->dev);
1800: }
1801:
1802: /*
1803: * setup buffers & conversion layers, prepare the slot to receive data
1804: * (for playback) or start (recording).
1805: */
1806: void
1807: slot_start(struct slot *s)
1808: {
1809: #ifdef DEBUG
1810: if (s->pstate != SLOT_INIT) {
1811: slot_log(s);
1812: log_puts(": slot_start: wrong state\n");
1813: panic();
1814: }
1815: if (s->mode & MODE_PLAY) {
1816: if (log_level >= 3) {
1817: slot_log(s);
1818: log_puts(": playing ");
1819: aparams_log(&s->par);
1820: log_puts(" -> ");
1.35 ratchov 1821: aparams_log(&s->dev->par);
1.1 ratchov 1822: log_puts("\n");
1823: }
1824: }
1825: if (s->mode & MODE_RECMASK) {
1826: if (log_level >= 3) {
1827: slot_log(s);
1828: log_puts(": recording ");
1829: aparams_log(&s->par);
1830: log_puts(" <- ");
1.35 ratchov 1831: aparams_log(&s->dev->par);
1.1 ratchov 1832: log_puts("\n");
1.35 ratchov 1833: }
1.1 ratchov 1834: }
1835: #endif
1.35 ratchov 1836: slot_allocbufs(s);
1.47 ratchov 1837:
1838: if (s->mode & MODE_RECMASK) {
1839: /*
1840: * N-th recorded block is the N-th played block
1841: */
1842: s->sub.prime = -dev_getpos(s->dev) / s->dev->round;
1843: }
1844: s->skip = 0;
1845:
1.1 ratchov 1846: if (s->mode & MODE_PLAY) {
1847: s->pstate = SLOT_START;
1848: } else {
1849: s->pstate = SLOT_READY;
1850: slot_ready(s);
1851: }
1852: }
1853:
1854: /*
1855: * stop playback and recording, and free conversion layers
1856: */
1857: void
1858: slot_detach(struct slot *s)
1859: {
1860: struct slot **ps;
1861:
1862: #ifdef DEBUG
1863: if (log_level >= 3) {
1864: slot_log(s);
1865: log_puts(": detaching\n");
1866: }
1867: #endif
1868: for (ps = &s->dev->slot_list; *ps != s; ps = &(*ps)->next) {
1869: #ifdef DEBUG
1.28 ratchov 1870: if (*ps == NULL) {
1.1 ratchov 1871: slot_log(s);
1872: log_puts(": can't detach, not on list\n");
1873: panic();
1874: }
1875: #endif
1.23 ratchov 1876: }
1.1 ratchov 1877: *ps = s->next;
1.35 ratchov 1878: if (s->mode & MODE_PLAY)
1.1 ratchov 1879: dev_mix_adjvol(s->dev);
1880: }
1881:
1882: /*
1883: * put the slot in stopping state (draining play buffers) or
1884: * stop & detach if no data to drain.
1885: */
1886: void
1887: slot_stop(struct slot *s)
1888: {
1889: #ifdef DEBUG
1890: if (log_level >= 3) {
1891: slot_log(s);
1892: log_puts(": stopping\n");
1893: }
1894: #endif
1895: if (s->pstate == SLOT_START) {
1.33 ratchov 1896: /*
1897: * If in rec-only mode, we're already in the READY or
1898: * RUN states. We're here because the play buffer was
1899: * not full enough, try to start so it's drained.
1900: */
1901: s->pstate = SLOT_READY;
1902: slot_ready(s);
1.1 ratchov 1903: }
1.34 ratchov 1904:
1905: if (s->pstate == SLOT_RUN) {
1906: if (s->mode & MODE_PLAY) {
1907: /*
1908: * Don't detach, dev_cycle() will do it for us
1909: * when the buffer is drained.
1910: */
1911: s->pstate = SLOT_STOP;
1912: return;
1913: }
1914: slot_detach(s);
1915: } else {
1.1 ratchov 1916: #ifdef DEBUG
1917: if (log_level >= 3) {
1918: slot_log(s);
1919: log_puts(": not drained (blocked by mmc)\n");
1920: }
1921: #endif
1922: }
1.35 ratchov 1923:
1.34 ratchov 1924: s->pstate = SLOT_INIT;
1925: s->ops->eof(s->arg);
1.35 ratchov 1926: slot_freebufs(s);
1.1 ratchov 1927: }
1928:
1.12 ratchov 1929: void
1930: slot_skip_update(struct slot *s)
1931: {
1932: int skip;
1933:
1934: skip = slot_skip(s);
1935: while (skip > 0) {
1936: #ifdef DEBUG
1937: if (log_level >= 4) {
1938: slot_log(s);
1939: log_puts(": catching skipped block\n");
1940: }
1941: #endif
1942: if (s->mode & MODE_RECMASK)
1943: s->ops->flush(s->arg);
1944: if (s->mode & MODE_PLAY)
1945: s->ops->fill(s->arg);
1946: skip--;
1947: }
1948: }
1949:
1.1 ratchov 1950: /*
1951: * notify the slot that we just wrote in the play buffer, must be called
1952: * after each write
1953: */
1954: void
1955: slot_write(struct slot *s)
1956: {
1957: if (s->pstate == SLOT_START && s->mix.buf.used == s->mix.buf.len) {
1958: #ifdef DEBUG
1959: if (log_level >= 4) {
1960: slot_log(s);
1961: log_puts(": switching to READY state\n");
1962: }
1963: #endif
1964: s->pstate = SLOT_READY;
1965: slot_ready(s);
1966: }
1.12 ratchov 1967: slot_skip_update(s);
1.1 ratchov 1968: }
1969:
1970: /*
1971: * notify the slot that we freed some space in the rec buffer
1972: */
1973: void
1974: slot_read(struct slot *s)
1975: {
1.12 ratchov 1976: slot_skip_update(s);
1.1 ratchov 1977: }