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