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