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