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