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