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