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