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