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