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