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