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