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