Annotation of src/usr.bin/sndiod/dev.c, Revision 1.91
1.91 ! edd 1: /* $OpenBSD: dev.c,v 1.90 2021/02/02 11:18:57 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.59 ratchov 62: void dev_freebufs(struct dev *);
1.7 ratchov 63: void dev_close(struct dev *);
64: int dev_ref(struct dev *);
65: void dev_unref(struct dev *);
66: int dev_init(struct dev *);
67: void dev_done(struct dev *);
68: struct dev *dev_bynum(int);
69: void dev_del(struct dev *);
1.75 ratchov 70: void dev_setalt(struct dev *, unsigned int);
1.7 ratchov 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:
1.64 ratchov 78: void slot_ctlname(struct slot *, char *, size_t);
1.7 ratchov 79: void slot_log(struct slot *);
80: void slot_del(struct slot *);
81: void slot_setvol(struct slot *, unsigned int);
82: void slot_ready(struct slot *);
1.35 ratchov 83: void slot_allocbufs(struct slot *);
84: void slot_freebufs(struct slot *);
1.12 ratchov 85: void slot_skip_update(struct slot *);
1.7 ratchov 86: void slot_write(struct slot *);
87: void slot_read(struct slot *);
1.12 ratchov 88: int slot_skip(struct slot *);
1.1 ratchov 89:
1.64 ratchov 90: void ctl_node_log(struct ctl_node *);
91: void ctl_log(struct ctl *);
92:
1.1 ratchov 93: struct midiops dev_midiops = {
94: dev_midi_imsg,
95: dev_midi_omsg,
96: dev_midi_fill,
97: dev_midi_exit
98: };
99:
100: struct slotops zomb_slotops = {
101: zomb_onmove,
102: zomb_onvol,
103: zomb_fill,
104: zomb_flush,
105: zomb_eof,
106: zomb_exit
107: };
108:
109: struct dev *dev_list = NULL;
110: unsigned int dev_sndnum = 0;
111:
1.85 ratchov 112: struct ctlslot ctlslot_array[DEV_NCTLSLOT];
1.84 ratchov 113: struct slot slot_array[DEV_NSLOT];
114: unsigned int slot_serial; /* for slot allocation */
115:
116: void
117: slot_array_init(void)
118: {
119: unsigned int i;
120:
121: for (i = 0; i < DEV_NSLOT; i++) {
122: slot_array[i].unit = i;
123: slot_array[i].ops = NULL;
124: slot_array[i].vol = MIDI_MAXCTL;
1.89 ratchov 125: slot_array[i].opt = NULL;
1.84 ratchov 126: slot_array[i].serial = slot_serial++;
127: memset(slot_array[i].name, 0, SLOT_NAMEMAX);
128: }
129: }
130:
1.1 ratchov 131: void
132: dev_log(struct dev *d)
133: {
1.3 ratchov 134: #ifdef DEBUG
135: static char *pstates[] = {
136: "cfg", "ini", "run"
137: };
138: #endif
1.1 ratchov 139: log_puts("snd");
140: log_putu(d->num);
1.3 ratchov 141: #ifdef DEBUG
142: if (log_level >= 3) {
143: log_puts(" pst=");
144: log_puts(pstates[d->pstate]);
145: }
146: #endif
1.1 ratchov 147: }
148:
149: void
1.64 ratchov 150: slot_ctlname(struct slot *s, char *name, size_t size)
151: {
152: snprintf(name, size, "%s%u", s->name, s->unit);
153: }
154:
155: void
1.1 ratchov 156: slot_log(struct slot *s)
1.3 ratchov 157: {
1.64 ratchov 158: char name[CTL_NAMEMAX];
1.1 ratchov 159: #ifdef DEBUG
160: static char *pstates[] = {
161: "ini", "sta", "rdy", "run", "stp", "mid"
162: };
163: #endif
1.64 ratchov 164: slot_ctlname(s, name, CTL_NAMEMAX);
165: log_puts(name);
1.1 ratchov 166: #ifdef DEBUG
167: if (log_level >= 3) {
168: log_puts(" vol=");
169: log_putu(s->vol);
170: if (s->ops) {
171: log_puts(",pst=");
172: log_puts(pstates[s->pstate]);
173: }
174: }
175: #endif
176: }
177:
178: void
1.14 ratchov 179: zomb_onmove(void *arg)
1.1 ratchov 180: {
181: }
182:
183: void
1.25 ratchov 184: zomb_onvol(void *arg)
1.1 ratchov 185: {
186: }
187:
188: void
189: zomb_fill(void *arg)
190: {
191: }
192:
193: void
194: zomb_flush(void *arg)
195: {
196: }
197:
198: void
199: zomb_eof(void *arg)
200: {
201: struct slot *s = arg;
202:
203: #ifdef DEBUG
204: if (log_level >= 3) {
205: slot_log(s);
206: log_puts(": zomb_eof\n");
207: }
208: #endif
209: s->ops = NULL;
210: }
211:
212: void
213: zomb_exit(void *arg)
214: {
215: #ifdef DEBUG
216: struct slot *s = arg;
217:
218: if (log_level >= 3) {
219: slot_log(s);
220: log_puts(": zomb_exit\n");
221: }
222: #endif
223: }
224:
225: /*
226: * send a quarter frame MTC message
227: */
228: void
229: dev_midi_qfr(struct dev *d, int delta)
230: {
231: unsigned char buf[2];
232: unsigned int data;
233: int qfrlen;
234:
235: d->mtc.delta += delta * MTC_SEC;
236: qfrlen = d->rate * (MTC_SEC / (4 * d->mtc.fps));
237: while (d->mtc.delta >= qfrlen) {
238: switch (d->mtc.qfr) {
239: case 0:
240: data = d->mtc.fr & 0xf;
241: break;
242: case 1:
243: data = d->mtc.fr >> 4;
244: break;
245: case 2:
246: data = d->mtc.sec & 0xf;
247: break;
248: case 3:
249: data = d->mtc.sec >> 4;
250: break;
251: case 4:
252: data = d->mtc.min & 0xf;
253: break;
254: case 5:
255: data = d->mtc.min >> 4;
256: break;
257: case 6:
258: data = d->mtc.hr & 0xf;
259: break;
260: case 7:
261: data = (d->mtc.hr >> 4) | (d->mtc.fps_id << 1);
262: /*
263: * tick messages are sent 2 frames ahead
264: */
265: d->mtc.fr += 2;
266: if (d->mtc.fr < d->mtc.fps)
267: break;
268: d->mtc.fr -= d->mtc.fps;
269: d->mtc.sec++;
270: if (d->mtc.sec < 60)
271: break;
272: d->mtc.sec = 0;
273: d->mtc.min++;
274: if (d->mtc.min < 60)
275: break;
276: d->mtc.min = 0;
277: d->mtc.hr++;
278: if (d->mtc.hr < 24)
279: break;
280: d->mtc.hr = 0;
281: break;
282: default:
283: /* NOTREACHED */
284: data = 0;
285: }
286: buf[0] = 0xf1;
287: buf[1] = (d->mtc.qfr << 4) | data;
288: d->mtc.qfr++;
289: d->mtc.qfr &= 7;
290: midi_send(d->midi, buf, 2);
291: d->mtc.delta -= qfrlen;
292: }
293: }
294:
295: /*
296: * send a full frame MTC message
297: */
298: void
299: dev_midi_full(struct dev *d)
300: {
301: struct sysex x;
302: unsigned int fps;
303:
304: d->mtc.delta = MTC_SEC * dev_getpos(d);
305: if (d->rate % (30 * 4 * d->round) == 0) {
306: d->mtc.fps_id = MTC_FPS_30;
307: d->mtc.fps = 30;
308: } else if (d->rate % (25 * 4 * d->round) == 0) {
309: d->mtc.fps_id = MTC_FPS_25;
310: d->mtc.fps = 25;
311: } else {
312: d->mtc.fps_id = MTC_FPS_24;
313: d->mtc.fps = 24;
314: }
315: #ifdef DEBUG
316: if (log_level >= 3) {
317: dev_log(d);
318: log_puts(": mtc full frame at ");
319: log_puti(d->mtc.delta);
320: log_puts(", ");
321: log_puti(d->mtc.fps);
322: log_puts(" fps\n");
323: }
324: #endif
325: fps = d->mtc.fps;
326: d->mtc.hr = (d->mtc.origin / (MTC_SEC * 3600)) % 24;
327: d->mtc.min = (d->mtc.origin / (MTC_SEC * 60)) % 60;
328: d->mtc.sec = (d->mtc.origin / (MTC_SEC)) % 60;
329: d->mtc.fr = (d->mtc.origin / (MTC_SEC / fps)) % fps;
330:
331: x.start = SYSEX_START;
332: x.type = SYSEX_TYPE_RT;
1.8 ratchov 333: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 334: x.id0 = SYSEX_MTC;
335: x.id1 = SYSEX_MTC_FULL;
336: x.u.full.hr = d->mtc.hr | (d->mtc.fps_id << 5);
337: x.u.full.min = d->mtc.min;
338: x.u.full.sec = d->mtc.sec;
339: x.u.full.fr = d->mtc.fr;
340: x.u.full.end = SYSEX_END;
341: d->mtc.qfr = 0;
342: midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(full));
343: }
344:
345: /*
346: * send a volume change MIDI message
347: */
348: void
349: dev_midi_vol(struct dev *d, struct slot *s)
350: {
351: unsigned char msg[3];
352:
1.84 ratchov 353: msg[0] = MIDI_CTL | (s - slot_array);
1.1 ratchov 354: msg[1] = MIDI_CTL_VOL;
355: msg[2] = s->vol;
356: midi_send(d->midi, msg, 3);
357: }
358:
359: /*
360: * send a master volume MIDI message
361: */
362: void
363: dev_midi_master(struct dev *d)
364: {
1.70 ratchov 365: struct ctl *c;
366: unsigned int master, v;
1.1 ratchov 367: struct sysex x;
368:
1.70 ratchov 369: if (d->master_enabled)
370: master = d->master;
371: else {
372: master = 0;
373: for (c = d->ctl_list; c != NULL; c = c->next) {
374: if (c->type != CTL_NUM ||
375: strcmp(c->group, "") != 0 ||
376: strcmp(c->node0.name, "output") != 0 ||
377: strcmp(c->func, "level") != 0)
378: continue;
379: v = (c->curval * 127 + c->maxval / 2) / c->maxval;
380: if (master < v)
381: master = v;
382: }
383: }
384:
1.1 ratchov 385: memset(&x, 0, sizeof(struct sysex));
386: x.start = SYSEX_START;
387: x.type = SYSEX_TYPE_RT;
1.8 ratchov 388: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 389: x.id0 = SYSEX_CONTROL;
390: x.id1 = SYSEX_MASTER;
391: x.u.master.fine = 0;
1.70 ratchov 392: x.u.master.coarse = master;
1.1 ratchov 393: x.u.master.end = SYSEX_END;
394: midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(master));
395: }
396:
397: /*
398: * send a sndiod-specific slot description MIDI message
399: */
400: void
401: dev_midi_slotdesc(struct dev *d, struct slot *s)
402: {
403: struct sysex x;
404:
405: memset(&x, 0, sizeof(struct sysex));
406: x.start = SYSEX_START;
407: x.type = SYSEX_TYPE_EDU;
1.8 ratchov 408: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 409: x.id0 = SYSEX_AUCAT;
410: x.id1 = SYSEX_AUCAT_SLOTDESC;
1.89 ratchov 411: if (s->opt != NULL && s->opt->dev == d)
1.64 ratchov 412: slot_ctlname(s, (char *)x.u.slotdesc.name, SYSEX_NAMELEN);
1.84 ratchov 413: x.u.slotdesc.chan = (s - slot_array);
1.1 ratchov 414: x.u.slotdesc.end = SYSEX_END;
415: midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(slotdesc));
416: }
417:
418: void
419: dev_midi_dump(struct dev *d)
420: {
421: struct sysex x;
422: struct slot *s;
423: int i;
424:
425: dev_midi_master(d);
1.84 ratchov 426: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.89 ratchov 427: if (s->opt != NULL && s->opt->dev != d)
1.84 ratchov 428: continue;
1.1 ratchov 429: dev_midi_slotdesc(d, s);
430: dev_midi_vol(d, s);
431: }
432: x.start = SYSEX_START;
433: x.type = SYSEX_TYPE_EDU;
1.8 ratchov 434: x.dev = SYSEX_DEV_ANY;
1.1 ratchov 435: x.id0 = SYSEX_AUCAT;
436: x.id1 = SYSEX_AUCAT_DUMPEND;
437: x.u.dumpend.end = SYSEX_END;
438: midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(dumpend));
439: }
440:
441: void
442: dev_midi_imsg(void *arg, unsigned char *msg, int len)
443: {
444: #ifdef DEBUG
445: struct dev *d = arg;
446:
447: dev_log(d);
448: log_puts(": can't receive midi messages\n");
449: panic();
450: #endif
451: }
452:
453: void
454: dev_midi_omsg(void *arg, unsigned char *msg, int len)
455: {
456: struct dev *d = arg;
457: struct sysex *x;
458: unsigned int fps, chan;
459:
460: if ((msg[0] & MIDI_CMDMASK) == MIDI_CTL && msg[1] == MIDI_CTL_VOL) {
461: chan = msg[0] & MIDI_CHANMASK;
462: if (chan >= DEV_NSLOT)
463: return;
1.89 ratchov 464: if (slot_array[chan].opt == NULL ||
465: slot_array[chan].opt->dev != d)
1.84 ratchov 466: return;
467: slot_setvol(slot_array + chan, msg[2]);
1.64 ratchov 468: dev_onval(d, CTLADDR_SLOT_LEVEL(chan), msg[2]);
1.1 ratchov 469: return;
470: }
471: x = (struct sysex *)msg;
472: if (x->start != SYSEX_START)
473: return;
474: if (len < SYSEX_SIZE(empty))
475: return;
476: switch (x->type) {
477: case SYSEX_TYPE_RT:
478: if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
1.64 ratchov 479: if (len == SYSEX_SIZE(master)) {
1.1 ratchov 480: dev_master(d, x->u.master.coarse);
1.70 ratchov 481: if (d->master_enabled) {
482: dev_onval(d, CTLADDR_MASTER,
483: x->u.master.coarse);
484: }
1.64 ratchov 485: }
1.1 ratchov 486: return;
487: }
488: if (x->id0 != SYSEX_MMC)
489: return;
490: switch (x->id1) {
491: case SYSEX_MMC_STOP:
492: if (len != SYSEX_SIZE(stop))
493: return;
494: if (log_level >= 2) {
495: dev_log(d);
496: log_puts(": mmc stop\n");
497: }
498: dev_mmcstop(d);
499: break;
500: case SYSEX_MMC_START:
501: if (len != SYSEX_SIZE(start))
502: return;
503: if (log_level >= 2) {
504: dev_log(d);
505: log_puts(": mmc start\n");
506: }
507: dev_mmcstart(d);
508: break;
509: case SYSEX_MMC_LOC:
510: if (len != SYSEX_SIZE(loc) ||
511: x->u.loc.len != SYSEX_MMC_LOC_LEN ||
512: x->u.loc.cmd != SYSEX_MMC_LOC_CMD)
513: return;
514: switch (x->u.loc.hr >> 5) {
515: case MTC_FPS_24:
516: fps = 24;
517: break;
518: case MTC_FPS_25:
519: fps = 25;
520: break;
521: case MTC_FPS_30:
522: fps = 30;
523: break;
524: default:
525: dev_mmcstop(d);
526: return;
527: }
528: dev_mmcloc(d,
529: (x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
530: x->u.loc.min * 60 * MTC_SEC +
531: x->u.loc.sec * MTC_SEC +
1.48 ratchov 532: x->u.loc.fr * (MTC_SEC / fps));
1.1 ratchov 533: break;
534: }
535: break;
536: case SYSEX_TYPE_EDU:
537: if (x->id0 != SYSEX_AUCAT || x->id1 != SYSEX_AUCAT_DUMPREQ)
538: return;
539: if (len != SYSEX_SIZE(dumpreq))
540: return;
541: dev_midi_dump(d);
542: break;
543: }
544: }
545:
546: void
547: dev_midi_fill(void *arg, int count)
548: {
1.2 ratchov 549: /* nothing to do */
1.1 ratchov 550: }
551:
552: void
553: dev_midi_exit(void *arg)
554: {
555: struct dev *d = arg;
556:
557: if (log_level >= 1) {
558: dev_log(d);
559: log_puts(": midi end point died\n");
560: }
561: if (d->pstate != DEV_CFG)
562: dev_close(d);
563: }
564:
1.12 ratchov 565: int
566: slot_skip(struct slot *s)
1.1 ratchov 567: {
1.12 ratchov 568: unsigned char *data = (unsigned char *)0xdeadbeef; /* please gcc */
569: int max, count;
570:
571: max = s->skip;
572: while (s->skip > 0) {
573: if (s->pstate != SLOT_STOP && (s->mode & MODE_RECMASK)) {
574: data = abuf_wgetblk(&s->sub.buf, &count);
575: if (count < s->round * s->sub.bpf)
576: break;
577: }
578: if (s->mode & MODE_PLAY) {
579: if (s->mix.buf.used < s->round * s->mix.bpf)
580: break;
581: }
1.1 ratchov 582: #ifdef DEBUG
583: if (log_level >= 4) {
584: slot_log(s);
1.12 ratchov 585: log_puts(": skipped a cycle\n");
1.1 ratchov 586: }
587: #endif
1.12 ratchov 588: if (s->pstate != SLOT_STOP && (s->mode & MODE_RECMASK)) {
589: if (s->sub.encbuf)
590: enc_sil_do(&s->sub.enc, data, s->round);
591: else
592: memset(data, 0, s->round * s->sub.bpf);
593: abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf);
594: }
595: if (s->mode & MODE_PLAY) {
596: abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf);
1.1 ratchov 597: }
1.23 ratchov 598: s->skip--;
1.1 ratchov 599: }
1.12 ratchov 600: return max - s->skip;
1.1 ratchov 601: }
602:
1.32 ratchov 603: /*
604: * Mix the slot input block over the output block
605: */
606: void
607: dev_mix_badd(struct dev *d, struct slot *s)
1.1 ratchov 608: {
1.32 ratchov 609: adata_t *idata, *odata, *in;
610: int icount, i, offs, vol, nch;
611:
612: odata = DEV_PBUF(d);
613: idata = (adata_t *)abuf_rgetblk(&s->mix.buf, &icount);
614: #ifdef DEBUG
615: if (icount < s->round * s->mix.bpf) {
616: slot_log(s);
617: log_puts(": not enough data to mix (");
618: log_putu(icount);
619: log_puts("bytes)\n");
620: panic();
621: }
622: #endif
623:
624: /*
625: * Apply the following processing chain:
626: *
627: * dec -> resamp-> cmap
628: *
629: * where the first two are optional.
630: */
631:
632: in = idata;
633:
634: if (s->mix.decbuf) {
635: dec_do(&s->mix.dec, (void *)in, s->mix.decbuf, s->round);
636: in = s->mix.decbuf;
637: }
1.1 ratchov 638:
639: if (s->mix.resampbuf) {
1.32 ratchov 640: resamp_do(&s->mix.resamp, in, s->mix.resampbuf, s->round);
1.1 ratchov 641: in = s->mix.resampbuf;
1.32 ratchov 642: }
1.1 ratchov 643:
1.10 ratchov 644: nch = s->mix.cmap.nch;
1.1 ratchov 645: vol = ADATA_MUL(s->mix.weight, s->mix.vol) / s->mix.join;
1.32 ratchov 646: cmap_add(&s->mix.cmap, in, odata, vol, d->round);
1.1 ratchov 647:
648: offs = 0;
649: for (i = s->mix.join - 1; i > 0; i--) {
650: offs += nch;
1.32 ratchov 651: cmap_add(&s->mix.cmap, in + offs, odata, vol, d->round);
1.1 ratchov 652: }
1.32 ratchov 653:
1.1 ratchov 654: offs = 0;
655: for (i = s->mix.expand - 1; i > 0; i--) {
656: offs += nch;
1.32 ratchov 657: cmap_add(&s->mix.cmap, in, odata + offs, vol, d->round);
1.1 ratchov 658: }
659:
660: abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf);
661: }
662:
663: /*
664: * Normalize input levels.
665: */
666: void
667: dev_mix_adjvol(struct dev *d)
668: {
669: unsigned int n;
670: struct slot *i, *j;
1.42 ratchov 671: int jcmax, icmax, weight;
1.1 ratchov 672:
673: for (i = d->slot_list; i != NULL; i = i->next) {
674: if (!(i->mode & MODE_PLAY))
675: continue;
1.42 ratchov 676: icmax = i->opt->pmin + i->mix.nch - 1;
1.1 ratchov 677: weight = ADATA_UNIT;
678: if (d->autovol) {
679: /*
680: * count the number of inputs that have
681: * overlapping channel sets
682: */
683: n = 0;
684: for (j = d->slot_list; j != NULL; j = j->next) {
685: if (!(j->mode & MODE_PLAY))
686: continue;
1.42 ratchov 687: jcmax = j->opt->pmin + j->mix.nch - 1;
688: if (i->opt->pmin <= jcmax &&
689: icmax >= j->opt->pmin)
1.1 ratchov 690: n++;
691: }
692: weight /= n;
693: }
1.38 ratchov 694: if (weight > i->opt->maxweight)
695: weight = i->opt->maxweight;
1.70 ratchov 696: i->mix.weight = d->master_enabled ?
697: ADATA_MUL(weight, MIDI_TO_ADATA(d->master)) : weight;
1.1 ratchov 698: #ifdef DEBUG
699: if (log_level >= 3) {
700: slot_log(i);
701: log_puts(": set weight: ");
702: log_puti(i->mix.weight);
703: log_puts("/");
1.38 ratchov 704: log_puti(i->opt->maxweight);
1.1 ratchov 705: log_puts("\n");
706: }
707: #endif
708: }
709: }
710:
711: /*
712: * Copy data from slot to device
713: */
714: void
715: dev_sub_bcopy(struct dev *d, struct slot *s)
716: {
1.32 ratchov 717: adata_t *idata, *enc_out, *resamp_out, *cmap_out;
718: void *odata;
1.15 ratchov 719: int ocount, moffs;
1.1 ratchov 720:
1.32 ratchov 721: int i, vol, offs, nch;
722:
723:
1.15 ratchov 724: if (s->mode & MODE_MON) {
725: moffs = d->poffs + d->round;
726: if (moffs == d->psize)
727: moffs = 0;
728: idata = d->pbuf + moffs * d->pchan;
729: } else
730: idata = d->rbuf;
1.1 ratchov 731: odata = (adata_t *)abuf_wgetblk(&s->sub.buf, &ocount);
732: #ifdef DEBUG
733: if (ocount < s->round * s->sub.bpf) {
734: log_puts("dev_sub_bcopy: not enough space\n");
735: panic();
736: }
737: #endif
1.32 ratchov 738:
739: /*
740: * Apply the following processing chain:
741: *
742: * cmap -> resamp -> enc
743: *
744: * where the last two are optional.
745: */
746:
747: enc_out = odata;
748: resamp_out = s->sub.encbuf ? s->sub.encbuf : enc_out;
749: cmap_out = s->sub.resampbuf ? s->sub.resampbuf : resamp_out;
750:
751: nch = s->sub.cmap.nch;
752: vol = ADATA_UNIT / s->sub.join;
753: cmap_copy(&s->sub.cmap, idata, cmap_out, vol, d->round);
754:
755: offs = 0;
756: for (i = s->sub.join - 1; i > 0; i--) {
757: offs += nch;
758: cmap_add(&s->sub.cmap, idata + offs, cmap_out, vol, d->round);
759: }
760:
761: offs = 0;
762: for (i = s->sub.expand - 1; i > 0; i--) {
763: offs += nch;
764: cmap_copy(&s->sub.cmap, idata, cmap_out + offs, vol, d->round);
765: }
766:
767: if (s->sub.resampbuf) {
768: resamp_do(&s->sub.resamp,
769: s->sub.resampbuf, resamp_out, d->round);
770: }
771:
772: if (s->sub.encbuf)
773: enc_do(&s->sub.enc, s->sub.encbuf, (void *)enc_out, s->round);
774:
775: abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf);
1.1 ratchov 776: }
777:
1.16 ratchov 778: /*
779: * run a one block cycle: consume one recorded block from
780: * rbuf and produce one play block in pbuf
781: */
1.1 ratchov 782: void
1.16 ratchov 783: dev_cycle(struct dev *d)
1.1 ratchov 784: {
785: struct slot *s, **ps;
1.12 ratchov 786: unsigned char *base;
787: int nsamp;
1.1 ratchov 788:
1.16 ratchov 789: /*
790: * check if the device is actually used. If it isn't,
791: * then close it
792: */
793: if (d->slot_list == NULL && d->tstate != MMC_RUN) {
794: if (log_level >= 2) {
795: dev_log(d);
796: log_puts(": device stopped\n");
797: }
798: dev_sio_stop(d);
799: d->pstate = DEV_INIT;
800: if (d->refcnt == 0)
801: dev_close(d);
802: return;
803: }
804:
805: if (d->prime > 0) {
806: #ifdef DEBUG
807: if (log_level >= 4) {
808: dev_log(d);
809: log_puts(": empty cycle, prime = ");
810: log_putu(d->prime);
811: log_puts("\n");
812: }
813: #endif
814: base = (unsigned char *)DEV_PBUF(d);
815: nsamp = d->round * d->pchan;
816: memset(base, 0, nsamp * sizeof(adata_t));
817: if (d->encbuf) {
818: enc_do(&d->enc, (unsigned char *)DEV_PBUF(d),
819: d->encbuf, d->round);
820: }
821: d->prime -= d->round;
822: return;
823: }
824:
1.12 ratchov 825: d->delta -= d->round;
1.1 ratchov 826: #ifdef DEBUG
827: if (log_level >= 4) {
828: dev_log(d);
1.16 ratchov 829: log_puts(": full cycle: delta = ");
1.12 ratchov 830: log_puti(d->delta);
831: if (d->mode & MODE_PLAY) {
832: log_puts(", poffs = ");
833: log_puti(d->poffs);
834: }
835: log_puts("\n");
1.1 ratchov 836: }
837: #endif
1.12 ratchov 838: if (d->mode & MODE_PLAY) {
839: base = (unsigned char *)DEV_PBUF(d);
840: nsamp = d->round * d->pchan;
841: memset(base, 0, nsamp * sizeof(adata_t));
842: }
1.1 ratchov 843: if ((d->mode & MODE_REC) && d->decbuf)
844: dec_do(&d->dec, d->decbuf, (unsigned char *)d->rbuf, d->round);
845: ps = &d->slot_list;
846: while ((s = *ps) != NULL) {
1.12 ratchov 847: #ifdef DEBUG
848: if (log_level >= 4) {
849: slot_log(s);
850: log_puts(": running");
851: log_puts(", skip = ");
852: log_puti(s->skip);
853: log_puts("\n");
854: }
855: #endif
856: /*
857: * skip cycles for XRUN_SYNC correction
858: */
859: slot_skip(s);
860: if (s->skip < 0) {
861: s->skip++;
1.1 ratchov 862: ps = &s->next;
863: continue;
864: }
1.12 ratchov 865:
866: #ifdef DEBUG
867: if (s->pstate == SLOT_STOP && !(s->mode & MODE_PLAY)) {
868: slot_log(s);
869: log_puts(": rec-only slots can't be drained\n");
870: panic();
871: }
872: #endif
873: /*
874: * check if stopped stream finished draining
875: */
876: if (s->pstate == SLOT_STOP &&
877: s->mix.buf.used < s->round * s->mix.bpf) {
878: /*
879: * partial blocks are zero-filled by socket
880: * layer, so s->mix.buf.used == 0 and we can
881: * destroy the buffer
882: */
1.35 ratchov 883: *ps = s->next;
1.12 ratchov 884: s->pstate = SLOT_INIT;
885: s->ops->eof(s->arg);
1.35 ratchov 886: slot_freebufs(s);
1.12 ratchov 887: dev_mix_adjvol(d);
1.35 ratchov 888: #ifdef DEBUG
889: if (log_level >= 3) {
890: slot_log(s);
891: log_puts(": drained\n");
892: }
893: #endif
1.1 ratchov 894: continue;
895: }
1.23 ratchov 896:
1.12 ratchov 897: /*
898: * check for xruns
899: */
1.23 ratchov 900: if (((s->mode & MODE_PLAY) &&
1.12 ratchov 901: s->mix.buf.used < s->round * s->mix.bpf) ||
902: ((s->mode & MODE_RECMASK) &&
903: s->sub.buf.len - s->sub.buf.used <
904: s->round * s->sub.bpf)) {
905:
906: #ifdef DEBUG
907: if (log_level >= 3) {
908: slot_log(s);
909: log_puts(": xrun, pause cycle\n");
910: }
911: #endif
1.1 ratchov 912: if (s->xrun == XRUN_IGNORE) {
913: s->delta -= s->round;
1.12 ratchov 914: ps = &s->next;
915: } else if (s->xrun == XRUN_SYNC) {
916: s->skip++;
917: ps = &s->next;
918: } else if (s->xrun == XRUN_ERROR) {
919: s->ops->exit(s->arg);
920: *ps = s->next;
921: } else {
922: #ifdef DEBUG
923: slot_log(s);
924: log_puts(": bad xrun mode\n");
925: panic();
926: #endif
927: }
928: continue;
929: }
930: if ((s->mode & MODE_RECMASK) && !(s->pstate == SLOT_STOP)) {
931: if (s->sub.prime == 0) {
932: dev_sub_bcopy(d, s);
933: s->ops->flush(s->arg);
934: } else {
1.1 ratchov 935: #ifdef DEBUG
936: if (log_level >= 3) {
937: slot_log(s);
1.12 ratchov 938: log_puts(": prime = ");
939: log_puti(s->sub.prime);
940: log_puts("\n");
1.1 ratchov 941: }
942: #endif
1.12 ratchov 943: s->sub.prime--;
1.1 ratchov 944: }
945: }
1.15 ratchov 946: if (s->mode & MODE_PLAY) {
947: dev_mix_badd(d, s);
948: if (s->pstate != SLOT_STOP)
949: s->ops->fill(s->arg);
950: }
1.1 ratchov 951: ps = &s->next;
952: }
1.12 ratchov 953: if ((d->mode & MODE_PLAY) && d->encbuf) {
954: enc_do(&d->enc, (unsigned char *)DEV_PBUF(d),
955: d->encbuf, d->round);
956: }
1.1 ratchov 957: }
958:
959: /*
960: * called at every clock tick by the device
961: */
962: void
963: dev_onmove(struct dev *d, int delta)
964: {
965: long long pos;
1.23 ratchov 966: struct slot *s, *snext;
1.12 ratchov 967:
968: d->delta += delta;
1.1 ratchov 969:
970: for (s = d->slot_list; s != NULL; s = snext) {
1.12 ratchov 971: /*
972: * s->ops->onmove() may remove the slot
973: */
1.1 ratchov 974: snext = s->next;
1.80 ratchov 975: pos = s->delta_rem +
976: (long long)s->delta * d->round +
977: (long long)delta * s->round;
978: s->delta = pos / (int)d->round;
1.1 ratchov 979: s->delta_rem = pos % d->round;
1.80 ratchov 980: if (s->delta_rem < 0) {
981: s->delta_rem += d->round;
982: s->delta--;
983: }
1.1 ratchov 984: if (s->delta >= 0)
1.14 ratchov 985: s->ops->onmove(s->arg);
1.1 ratchov 986: }
987: if (d->tstate == MMC_RUN)
988: dev_midi_qfr(d, delta);
989: }
990:
991: void
992: dev_master(struct dev *d, unsigned int master)
993: {
1.70 ratchov 994: struct ctl *c;
995: unsigned int v;
996:
1.1 ratchov 997: if (log_level >= 2) {
998: dev_log(d);
999: log_puts(": master volume set to ");
1000: log_putu(master);
1001: log_puts("\n");
1002: }
1.70 ratchov 1003: if (d->master_enabled) {
1004: d->master = master;
1005: if (d->mode & MODE_PLAY)
1006: dev_mix_adjvol(d);
1007: } else {
1008: for (c = d->ctl_list; c != NULL; c = c->next) {
1009: if (c->type != CTL_NUM ||
1010: strcmp(c->group, "") != 0 ||
1011: strcmp(c->node0.name, "output") != 0 ||
1012: strcmp(c->func, "level") != 0)
1013: continue;
1014: v = (master * c->maxval + 64) / 127;
1015: dev_setctl(d, c->addr, v);
1016: }
1017: }
1.1 ratchov 1018: }
1019:
1020: /*
1021: * return the latency that a stream would have if it's attached
1022: */
1023: int
1024: dev_getpos(struct dev *d)
1025: {
1026: return (d->mode & MODE_PLAY) ? -d->bufsz : 0;
1027: }
1028:
1029: /*
1030: * Create a sndio device
1031: */
1032: struct dev *
1033: dev_new(char *path, struct aparams *par,
1034: unsigned int mode, unsigned int bufsz, unsigned int round,
1035: unsigned int rate, unsigned int hold, unsigned int autovol)
1036: {
1037: struct dev *d;
1038:
1039: if (dev_sndnum == DEV_NMAX) {
1040: if (log_level >= 1)
1041: log_puts("too many devices\n");
1042: return NULL;
1043: }
1044: d = xmalloc(sizeof(struct dev));
1.73 ratchov 1045: d->alt_list = NULL;
1046: dev_addname(d,path);
1.1 ratchov 1047: d->num = dev_sndnum++;
1.76 ratchov 1048: d->alt_num = -1;
1.1 ratchov 1049:
1050: /*
1051: * XXX: below, we allocate a midi input buffer, since we don't
1052: * receive raw midi data, so no need to allocate a input
1053: * ibuf. Possibly set imsg & fill callbacks to NULL and
1054: * use this to in midi_new() to check if buffers need to be
1055: * allocated
1056: */
1057: d->midi = midi_new(&dev_midiops, d, MODE_MIDIIN | MODE_MIDIOUT);
1058: midi_tag(d->midi, d->num);
1059: d->reqpar = *par;
1060: d->reqmode = mode;
1061: d->reqpchan = d->reqrchan = 0;
1062: d->reqbufsz = bufsz;
1063: d->reqround = round;
1064: d->reqrate = rate;
1065: d->hold = hold;
1066: d->autovol = autovol;
1067: d->refcnt = 0;
1068: d->pstate = DEV_CFG;
1069: d->slot_list = NULL;
1070: d->master = MIDI_MAXCTL;
1071: d->mtc.origin = 0;
1072: d->tstate = MMC_STOP;
1.64 ratchov 1073: d->ctl_list = NULL;
1.1 ratchov 1074: d->next = dev_list;
1075: dev_list = d;
1076: return d;
1077: }
1078:
1079: /*
1.73 ratchov 1080: * add a alternate name
1081: */
1082: int
1083: dev_addname(struct dev *d, char *name)
1084: {
1085: struct dev_alt *a;
1086:
1087: if (d->alt_list != NULL && d->alt_list->idx == DEV_NMAX - 1) {
1088: log_puts(name);
1089: log_puts(": too many alternate names\n");
1090: return 0;
1091: }
1092: a = xmalloc(sizeof(struct dev_alt));
1093: a->name = name;
1094: a->idx = (d->alt_list == NULL) ? 0 : d->alt_list->idx + 1;
1095: a->next = d->alt_list;
1096: d->alt_list = a;
1097: return 1;
1098: }
1099:
1100: /*
1.75 ratchov 1101: * set prefered alt device name
1102: */
1103: void
1104: dev_setalt(struct dev *d, unsigned int idx)
1105: {
1106: struct dev_alt **pa, *a;
1107:
1108: /* find alt with given index */
1109: for (pa = &d->alt_list; (a = *pa)->idx != idx; pa = &a->next)
1110: ;
1111:
1112: /* detach from list */
1113: *pa = a->next;
1114:
1115: /* attach at head */
1116: a->next = d->alt_list;
1117: d->alt_list = a;
1118:
1119: /* reopen device with the new alt */
1120: if (idx != d->alt_num)
1121: dev_reopen(d);
1122: }
1123:
1124: /*
1.1 ratchov 1125: * adjust device parameters and mode
1126: */
1127: void
1128: dev_adjpar(struct dev *d, int mode,
1.25 ratchov 1129: int pmax, int rmax)
1.1 ratchov 1130: {
1131: d->reqmode |= mode & MODE_AUDIOMASK;
1132: if (mode & MODE_PLAY) {
1133: if (d->reqpchan < pmax + 1)
1134: d->reqpchan = pmax + 1;
1135: }
1136: if (mode & MODE_REC) {
1137: if (d->reqrchan < rmax + 1)
1138: d->reqrchan = rmax + 1;
1139: }
1140: }
1141:
1142: /*
1143: * Open the device with the dev_reqxxx capabilities. Setup a mixer, demuxer,
1144: * monitor, midi control, and any necessary conversions.
1.91 ! edd 1145: *
! 1146: * Note that record and play buffers are always allocated, even if the
! 1147: * underlying device doesn't support both modes.
1.1 ratchov 1148: */
1149: int
1.59 ratchov 1150: dev_allocbufs(struct dev *d)
1.1 ratchov 1151: {
1.91 ! edd 1152: /*
! 1153: * Create record buffer.
! 1154: */
! 1155:
! 1156: /* Create device <-> demuxer buffer */
! 1157: d->rbuf = xmalloc(d->round * d->rchan * sizeof(adata_t));
! 1158:
! 1159: /* Insert a converter, if needed. */
! 1160: if (!aparams_native(&d->par)) {
! 1161: dec_init(&d->dec, &d->par, d->rchan);
! 1162: d->decbuf = xmalloc(d->round * d->rchan * d->par.bps);
! 1163: } else
! 1164: d->decbuf = NULL;
! 1165:
! 1166: /*
! 1167: * Create play buffer
! 1168: */
! 1169:
! 1170: /* Create device <-> mixer buffer */
! 1171: d->poffs = 0;
! 1172: d->psize = d->bufsz + d->round;
! 1173: d->pbuf = xmalloc(d->psize * d->pchan * sizeof(adata_t));
! 1174: d->mode |= MODE_MON;
! 1175:
! 1176: /* Append a converter, if needed. */
! 1177: if (!aparams_native(&d->par)) {
! 1178: enc_init(&d->enc, &d->par, d->pchan);
! 1179: d->encbuf = xmalloc(d->round * d->pchan * d->par.bps);
! 1180: } else
! 1181: d->encbuf = NULL;
1.1 ratchov 1182:
1.91 ! edd 1183: /*
! 1184: * Initially fill the record buffer with zeroed samples. This ensures
! 1185: * that when a client records from a play-only device the client just
! 1186: * gets silence.
! 1187: */
! 1188: memset(d->rbuf, 0, d->round * d->rchan * sizeof(adata_t));
1.1 ratchov 1189:
1190: if (log_level >= 2) {
1191: dev_log(d);
1192: log_puts(": ");
1193: log_putu(d->rate);
1194: log_puts("Hz, ");
1195: aparams_log(&d->par);
1196: if (d->mode & MODE_PLAY) {
1197: log_puts(", play 0:");
1198: log_puti(d->pchan - 1);
1199: }
1200: if (d->mode & MODE_REC) {
1201: log_puts(", rec 0:");
1202: log_puti(d->rchan - 1);
1203: }
1204: log_puts(", ");
1205: log_putu(d->bufsz / d->round);
1206: log_puts(" blocks of ");
1207: log_putu(d->round);
1208: log_puts(" frames\n");
1209: }
1.57 ratchov 1210: return 1;
1211: }
1212:
1213: /*
1214: * Reset parameters and open the device.
1215: */
1216: int
1217: dev_open(struct dev *d)
1218: {
1.64 ratchov 1219: int i;
1220: char name[CTL_NAMEMAX];
1.75 ratchov 1221: struct dev_alt *a;
1.84 ratchov 1222: struct slot *s;
1.64 ratchov 1223:
1.70 ratchov 1224: d->master_enabled = 0;
1.57 ratchov 1225: d->mode = d->reqmode;
1226: d->round = d->reqround;
1227: d->bufsz = d->reqbufsz;
1228: d->rate = d->reqrate;
1229: d->pchan = d->reqpchan;
1230: d->rchan = d->reqrchan;
1231: d->par = d->reqpar;
1232: if (d->pchan == 0)
1233: d->pchan = 2;
1234: if (d->rchan == 0)
1235: d->rchan = 2;
1.59 ratchov 1236: if (!dev_sio_open(d)) {
1237: if (log_level >= 1) {
1238: dev_log(d);
1239: log_puts(": failed to open audio device\n");
1240: }
1241: return 0;
1242: }
1243: if (!dev_allocbufs(d))
1.57 ratchov 1244: return 0;
1.64 ratchov 1245:
1.84 ratchov 1246: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.89 ratchov 1247: if (s->opt == NULL || s->opt->dev != d || s->name[0] == 0)
1.69 ratchov 1248: continue;
1.84 ratchov 1249: slot_ctlname(s, name, CTL_NAMEMAX);
1.64 ratchov 1250: dev_addctl(d, "app", CTL_NUM,
1251: CTLADDR_SLOT_LEVEL(i),
1252: name, -1, "level",
1.84 ratchov 1253: NULL, -1, 127, s->vol);
1.64 ratchov 1254: }
1255:
1.77 ratchov 1256: /* if there are multiple alt devs, add server.device knob */
1257: if (d->alt_list->next != NULL) {
1258: for (a = d->alt_list; a != NULL; a = a->next) {
1259: snprintf(name, sizeof(name), "%d", a->idx);
1260: dev_addctl(d, "", CTL_SEL,
1261: CTLADDR_ALT_SEL + a->idx,
1262: "server", -1, "device",
1263: name, -1, 1, a->idx == d->alt_num);
1264: }
1.75 ratchov 1265: }
1266:
1.59 ratchov 1267: d->pstate = DEV_INIT;
1.1 ratchov 1268: return 1;
1269: }
1270:
1271: /*
1.72 ratchov 1272: * Force all slots to exit and close device, called after an error
1.55 ratchov 1273: */
1274: void
1.72 ratchov 1275: dev_abort(struct dev *d)
1.55 ratchov 1276: {
1277: int i;
1278: struct slot *s;
1.64 ratchov 1279: struct ctlslot *c;
1.55 ratchov 1280:
1.84 ratchov 1281: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.89 ratchov 1282: if (s->opt == NULL || s->opt->dev != d)
1.84 ratchov 1283: continue;
1.89 ratchov 1284: if (s->ops) {
1.55 ratchov 1285: s->ops->exit(s->arg);
1.89 ratchov 1286: s->ops = NULL;
1287: }
1.55 ratchov 1288: }
1289: d->slot_list = NULL;
1.64 ratchov 1290:
1.85 ratchov 1291: for (c = ctlslot_array, i = DEV_NCTLSLOT; i > 0; i--, c++) {
1.90 ratchov 1292: if (c->ops == NULL)
1293: continue;
1.88 ratchov 1294: if (c->opt->dev != d)
1.85 ratchov 1295: continue;
1.90 ratchov 1296: c->ops->exit(c->arg);
1297: c->ops = NULL;
1.64 ratchov 1298: }
1.83 ratchov 1299:
1300: midi_abort(d->midi);
1.72 ratchov 1301:
1302: if (d->pstate != DEV_CFG)
1303: dev_close(d);
1.55 ratchov 1304: }
1305:
1306: /*
1.1 ratchov 1307: * force the device to go in DEV_CFG state, the caller is supposed to
1308: * ensure buffers are drained
1309: */
1310: void
1.59 ratchov 1311: dev_freebufs(struct dev *d)
1.1 ratchov 1312: {
1313: #ifdef DEBUG
1314: if (log_level >= 3) {
1315: dev_log(d);
1316: log_puts(": closing\n");
1317: }
1318: #endif
1319: if (d->mode & MODE_PLAY) {
1320: if (d->encbuf != NULL)
1321: xfree(d->encbuf);
1322: xfree(d->pbuf);
1323: }
1324: if (d->mode & MODE_REC) {
1325: if (d->decbuf != NULL)
1326: xfree(d->decbuf);
1327: xfree(d->rbuf);
1328: }
1.58 ratchov 1329: }
1330:
1331: /*
1332: * Close the device and exit all slots
1333: */
1334: void
1335: dev_close(struct dev *d)
1336: {
1.64 ratchov 1337: struct ctl *c;
1338:
1.59 ratchov 1339: d->pstate = DEV_CFG;
1340: dev_sio_close(d);
1341: dev_freebufs(d);
1.64 ratchov 1342:
1343: /* there are no clients, just free remaining local controls */
1344: while ((c = d->ctl_list) != NULL) {
1345: d->ctl_list = c->next;
1346: xfree(c);
1347: }
1.1 ratchov 1348: }
1349:
1.62 ratchov 1350: /*
1351: * Close the device, but attempt to migrate everything to a new sndio
1352: * device.
1353: */
1354: int
1355: dev_reopen(struct dev *d)
1356: {
1357: struct slot *s;
1358: long long pos;
1359: unsigned int pstate;
1360: int delta;
1361:
1362: /* not opened */
1363: if (d->pstate == DEV_CFG)
1364: return 1;
1365:
1366: /* save state */
1367: delta = d->delta;
1368: pstate = d->pstate;
1369:
1370: if (!dev_sio_reopen(d))
1371: return 0;
1372:
1373: /* reopen returns a stopped device */
1374: d->pstate = DEV_INIT;
1375:
1376: /* reallocate new buffers, with new parameters */
1377: dev_freebufs(d);
1378: dev_allocbufs(d);
1379:
1380: /*
1381: * adjust time positions, make anything go back delta ticks, so
1382: * that the new device can start at zero
1383: */
1384: for (s = d->slot_list; s != NULL; s = s->next) {
1385: pos = (long long)s->delta * d->round + s->delta_rem;
1386: pos -= (long long)delta * s->round;
1387: s->delta_rem = pos % (int)d->round;
1388: s->delta = pos / (int)d->round;
1389: if (log_level >= 3) {
1390: slot_log(s);
1391: log_puts(": adjusted: delta -> ");
1392: log_puti(s->delta);
1393: log_puts(", delta_rem -> ");
1394: log_puti(s->delta_rem);
1395: log_puts("\n");
1396: }
1397:
1398: /* reinitilize the format conversion chain */
1399: slot_initconv(s);
1400: }
1401: if (d->tstate == MMC_RUN) {
1402: d->mtc.delta -= delta * MTC_SEC;
1403: if (log_level >= 2) {
1404: dev_log(d);
1405: log_puts(": adjusted mtc: delta ->");
1406: log_puti(d->mtc.delta);
1407: log_puts("\n");
1408: }
1409: }
1410:
1.71 ratchov 1411: /* remove old controls and add new ones */
1412: dev_sioctl_close(d);
1.64 ratchov 1413: dev_sioctl_open(d);
1414:
1.62 ratchov 1415: /* start the device if needed */
1416: if (pstate == DEV_RUN)
1417: dev_wakeup(d);
1418:
1419: return 1;
1420: }
1421:
1.1 ratchov 1422: int
1423: dev_ref(struct dev *d)
1424: {
1425: #ifdef DEBUG
1426: if (log_level >= 3) {
1427: dev_log(d);
1428: log_puts(": device requested\n");
1429: }
1430: #endif
1431: if (d->pstate == DEV_CFG && !dev_open(d))
1432: return 0;
1433: d->refcnt++;
1434: return 1;
1435: }
1436:
1437: void
1438: dev_unref(struct dev *d)
1439: {
1440: #ifdef DEBUG
1441: if (log_level >= 3) {
1442: dev_log(d);
1443: log_puts(": device released\n");
1444: }
1445: #endif
1446: d->refcnt--;
1447: if (d->refcnt == 0 && d->pstate == DEV_INIT)
1448: dev_close(d);
1449: }
1450:
1451: /*
1452: * initialize the device with the current parameters
1453: */
1454: int
1455: dev_init(struct dev *d)
1456: {
1457: if ((d->reqmode & MODE_AUDIOMASK) == 0) {
1458: #ifdef DEBUG
1459: dev_log(d);
1460: log_puts(": has no streams\n");
1461: #endif
1462: return 0;
1463: }
1464: if (d->hold && !dev_ref(d))
1465: return 0;
1466: return 1;
1467: }
1468:
1469: /*
1470: * Unless the device is already in process of closing, request it to close
1471: */
1472: void
1473: dev_done(struct dev *d)
1474: {
1475: #ifdef DEBUG
1476: if (log_level >= 3) {
1477: dev_log(d);
1478: log_puts(": draining\n");
1479: }
1480: #endif
1.20 ratchov 1481: if (d->tstate != MMC_STOP)
1482: dev_mmcstop(d);
1.1 ratchov 1483: if (d->hold)
1484: dev_unref(d);
1485: }
1486:
1487: struct dev *
1488: dev_bynum(int num)
1489: {
1490: struct dev *d;
1491:
1492: for (d = dev_list; d != NULL; d = d->next) {
1.19 ratchov 1493: if (d->num == num)
1.1 ratchov 1494: return d;
1495: }
1496: return NULL;
1497: }
1498:
1499: /*
1500: * Free the device
1501: */
1502: void
1503: dev_del(struct dev *d)
1504: {
1505: struct dev **p;
1.73 ratchov 1506: struct dev_alt *a;
1.1 ratchov 1507:
1508: #ifdef DEBUG
1509: if (log_level >= 3) {
1510: dev_log(d);
1511: log_puts(": deleting\n");
1512: }
1513: #endif
1514: if (d->pstate != DEV_CFG)
1515: dev_close(d);
1516: for (p = &dev_list; *p != d; p = &(*p)->next) {
1517: #ifdef DEBUG
1518: if (*p == NULL) {
1519: dev_log(d);
1520: log_puts(": device to delete not on the list\n");
1521: panic();
1522: }
1523: #endif
1524: }
1525: midi_del(d->midi);
1526: *p = d->next;
1.73 ratchov 1527: while ((a = d->alt_list) != NULL) {
1528: d->alt_list = a->next;
1529: xfree(a);
1530: }
1.1 ratchov 1531: xfree(d);
1532: }
1533:
1534: unsigned int
1535: dev_roundof(struct dev *d, unsigned int newrate)
1536: {
1537: return (d->round * newrate + d->rate / 2) / d->rate;
1538: }
1539:
1540: /*
1541: * If the device is paused, then resume it.
1542: */
1543: void
1544: dev_wakeup(struct dev *d)
1545: {
1546: if (d->pstate == DEV_INIT) {
1547: if (log_level >= 2) {
1548: dev_log(d);
1549: log_puts(": device started\n");
1550: }
1551: if (d->mode & MODE_PLAY) {
1552: d->prime = d->bufsz;
1553: } else {
1554: d->prime = 0;
1555: }
1.16 ratchov 1556: d->poffs = 0;
1.12 ratchov 1557:
1.23 ratchov 1558: /*
1.16 ratchov 1559: * empty cycles don't increment delta, so it's ok to
1560: * start at 0
1561: **/
1.23 ratchov 1562: d->delta = 0;
1.12 ratchov 1563:
1.1 ratchov 1564: d->pstate = DEV_RUN;
1565: dev_sio_start(d);
1566: }
1567: }
1568:
1569: /*
1570: * check that all clients controlled by MMC are ready to start, if so,
1571: * attach them all at the same position
1572: */
1573: void
1574: dev_sync_attach(struct dev *d)
1575: {
1576: int i;
1577: struct slot *s;
1578:
1579: if (d->tstate != MMC_START) {
1580: if (log_level >= 2) {
1581: dev_log(d);
1582: log_puts(": not started by mmc yet, waiting...\n");
1583: }
1584: return;
1585: }
1.84 ratchov 1586:
1587: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.89 ratchov 1588: if (s->opt == NULL || s->opt->dev != d || !s->ops || !s->opt->mmc)
1.1 ratchov 1589: continue;
1.46 ratchov 1590: if (s->pstate != SLOT_READY) {
1.1 ratchov 1591: #ifdef DEBUG
1592: if (log_level >= 3) {
1593: slot_log(s);
1594: log_puts(": not ready, start delayed\n");
1595: }
1596: #endif
1597: return;
1598: }
1599: }
1600: if (!dev_ref(d))
1601: return;
1.84 ratchov 1602:
1603: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.89 ratchov 1604: if (s->opt == NULL || s->opt->dev != d || !s->ops || !s->opt->mmc)
1.1 ratchov 1605: continue;
1.46 ratchov 1606: slot_attach(s);
1.79 ratchov 1607: s->pstate = SLOT_RUN;
1.1 ratchov 1608: }
1609: d->tstate = MMC_RUN;
1610: dev_midi_full(d);
1611: dev_wakeup(d);
1612: }
1613:
1614: /*
1615: * start all slots simultaneously
1616: */
1617: void
1618: dev_mmcstart(struct dev *d)
1619: {
1620: if (d->tstate == MMC_STOP) {
1621: d->tstate = MMC_START;
1622: dev_sync_attach(d);
1623: #ifdef DEBUG
1624: } else {
1625: if (log_level >= 3) {
1626: dev_log(d);
1627: log_puts(": ignoring mmc start\n");
1628: }
1629: #endif
1630: }
1631: }
1632:
1633: /*
1634: * stop all slots simultaneously
1635: */
1636: void
1637: dev_mmcstop(struct dev *d)
1638: {
1639: switch (d->tstate) {
1640: case MMC_START:
1641: d->tstate = MMC_STOP;
1642: return;
1643: case MMC_RUN:
1644: d->tstate = MMC_STOP;
1645: dev_unref(d);
1646: break;
1647: default:
1648: #ifdef DEBUG
1649: if (log_level >= 3) {
1650: dev_log(d);
1651: log_puts(": ignored mmc stop\n");
1652: }
1653: #endif
1654: return;
1655: }
1656: }
1657:
1658: /*
1659: * relocate all slots simultaneously
1660: */
1661: void
1662: dev_mmcloc(struct dev *d, unsigned int origin)
1663: {
1664: if (log_level >= 2) {
1665: dev_log(d);
1666: log_puts(": relocated to ");
1667: log_putu(origin);
1668: log_puts("\n");
1669: }
1670: if (d->tstate == MMC_RUN)
1671: dev_mmcstop(d);
1672: d->mtc.origin = origin;
1673: if (d->tstate == MMC_RUN)
1674: dev_mmcstart(d);
1675: }
1676:
1.35 ratchov 1677: /*
1678: * allocate buffers & conversion chain
1679: */
1680: void
1.60 ratchov 1681: slot_initconv(struct slot *s)
1.35 ratchov 1682: {
1.63 ratchov 1683: unsigned int dev_nch;
1.89 ratchov 1684: struct dev *d = s->opt->dev;
1.35 ratchov 1685:
1686: if (s->mode & MODE_PLAY) {
1687: cmap_init(&s->mix.cmap,
1.42 ratchov 1688: s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1689: s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1.35 ratchov 1690: 0, d->pchan - 1,
1.40 ratchov 1691: s->opt->pmin, s->opt->pmax);
1.35 ratchov 1692: if (!aparams_native(&s->par)) {
1.42 ratchov 1693: dec_init(&s->mix.dec, &s->par, s->mix.nch);
1.35 ratchov 1694: }
1695: if (s->rate != d->rate) {
1696: resamp_init(&s->mix.resamp, s->round, d->round,
1.42 ratchov 1697: s->mix.nch);
1.35 ratchov 1698: }
1.61 ratchov 1699: s->mix.join = 1;
1700: s->mix.expand = 1;
1.63 ratchov 1701: if (s->opt->dup && s->mix.cmap.nch > 0) {
1702: dev_nch = d->pchan < (s->opt->pmax + 1) ?
1703: d->pchan - s->opt->pmin :
1704: s->opt->pmax - s->opt->pmin + 1;
1705: if (dev_nch > s->mix.nch)
1706: s->mix.expand = dev_nch / s->mix.nch;
1707: else if (s->mix.nch > dev_nch)
1708: s->mix.join = s->mix.nch / dev_nch;
1.61 ratchov 1709: }
1.35 ratchov 1710: }
1711:
1712: if (s->mode & MODE_RECMASK) {
1.63 ratchov 1713: unsigned int outchan = (s->mode & MODE_MON) ?
1714: d->pchan : d->rchan;
1715:
1.35 ratchov 1716: cmap_init(&s->sub.cmap,
1.63 ratchov 1717: 0, outchan - 1,
1.40 ratchov 1718: s->opt->rmin, s->opt->rmax,
1.42 ratchov 1719: s->opt->rmin, s->opt->rmin + s->sub.nch - 1,
1720: s->opt->rmin, s->opt->rmin + s->sub.nch - 1);
1.35 ratchov 1721: if (s->rate != d->rate) {
1722: resamp_init(&s->sub.resamp, d->round, s->round,
1.42 ratchov 1723: s->sub.nch);
1.35 ratchov 1724: }
1725: if (!aparams_native(&s->par)) {
1.42 ratchov 1726: enc_init(&s->sub.enc, &s->par, s->sub.nch);
1.61 ratchov 1727: }
1728: s->sub.join = 1;
1729: s->sub.expand = 1;
1.63 ratchov 1730: if (s->opt->dup && s->sub.cmap.nch > 0) {
1731: dev_nch = outchan < (s->opt->rmax + 1) ?
1732: outchan - s->opt->rmin :
1733: s->opt->rmax - s->opt->rmin + 1;
1734: if (dev_nch > s->sub.nch)
1735: s->sub.join = dev_nch / s->sub.nch;
1736: else if (s->sub.nch > dev_nch)
1737: s->sub.expand = s->sub.nch / dev_nch;
1.35 ratchov 1738: }
1739:
1740: /*
1741: * cmap_copy() doesn't write samples in all channels,
1742: * for instance when mono->stereo conversion is
1743: * disabled. So we have to prefill cmap_copy() output
1744: * with silence.
1745: */
1746: if (s->sub.resampbuf) {
1747: memset(s->sub.resampbuf, 0,
1.42 ratchov 1748: d->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1749: } else if (s->sub.encbuf) {
1750: memset(s->sub.encbuf, 0,
1.42 ratchov 1751: s->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1752: } else {
1753: memset(s->sub.buf.data, 0,
1.42 ratchov 1754: s->appbufsz * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1755: }
1756: }
1.60 ratchov 1757: }
1758:
1759: /*
1760: * allocate buffers & conversion chain
1761: */
1762: void
1763: slot_allocbufs(struct slot *s)
1764: {
1.89 ratchov 1765: struct dev *d = s->opt->dev;
1.60 ratchov 1766:
1767: if (s->mode & MODE_PLAY) {
1768: s->mix.bpf = s->par.bps * s->mix.nch;
1769: abuf_init(&s->mix.buf, s->appbufsz * s->mix.bpf);
1770:
1771: s->mix.decbuf = NULL;
1772: s->mix.resampbuf = NULL;
1773: if (!aparams_native(&s->par)) {
1774: s->mix.decbuf =
1775: xmalloc(s->round * s->mix.nch * sizeof(adata_t));
1776: }
1777: if (s->rate != d->rate) {
1778: s->mix.resampbuf =
1779: xmalloc(d->round * s->mix.nch * sizeof(adata_t));
1780: }
1781: }
1782:
1783: if (s->mode & MODE_RECMASK) {
1784: s->sub.bpf = s->par.bps * s->sub.nch;
1785: abuf_init(&s->sub.buf, s->appbufsz * s->sub.bpf);
1786:
1787: s->sub.encbuf = NULL;
1788: s->sub.resampbuf = NULL;
1789: if (s->rate != d->rate) {
1790: s->sub.resampbuf =
1791: xmalloc(d->round * s->sub.nch * sizeof(adata_t));
1792: }
1793: if (!aparams_native(&s->par)) {
1794: s->sub.encbuf =
1795: xmalloc(s->round * s->sub.nch * sizeof(adata_t));
1796: }
1797: }
1798:
1799: slot_initconv(s);
1.35 ratchov 1800:
1801: #ifdef DEBUG
1802: if (log_level >= 3) {
1803: slot_log(s);
1804: log_puts(": allocated ");
1805: log_putu(s->appbufsz);
1806: log_puts("/");
1807: log_putu(SLOT_BUFSZ(s));
1808: log_puts(" fr buffers\n");
1809: }
1810: #endif
1811: }
1812:
1813: /*
1814: * free buffers & conversion chain
1815: */
1816: void
1817: slot_freebufs(struct slot *s)
1818: {
1819: if (s->mode & MODE_RECMASK) {
1820: abuf_done(&s->sub.buf);
1821: if (s->sub.encbuf)
1822: xfree(s->sub.encbuf);
1823: if (s->sub.resampbuf)
1824: xfree(s->sub.resampbuf);
1825: }
1826:
1827: if (s->mode & MODE_PLAY) {
1828: abuf_done(&s->mix.buf);
1829: if (s->mix.decbuf)
1830: xfree(s->mix.decbuf);
1831: if (s->mix.resampbuf)
1832: xfree(s->mix.resampbuf);
1833: }
1834: }
1835:
1.1 ratchov 1836: /*
1837: * allocate a new slot and register the given call-backs
1838: */
1839: struct slot *
1.89 ratchov 1840: slot_new(struct opt *opt, unsigned int id, char *who,
1.37 ratchov 1841: struct slotops *ops, void *arg, int mode)
1.1 ratchov 1842: {
1843: char *p;
1844: char name[SLOT_NAMEMAX];
1.52 ratchov 1845: unsigned int i, ser, bestser, bestidx;
1846: struct slot *unit[DEV_NSLOT];
1.1 ratchov 1847: struct slot *s;
1848:
1849: /*
1.27 ratchov 1850: * create a ``valid'' control name (lowcase, remove [^a-z], truncate)
1.1 ratchov 1851: */
1852: for (i = 0, p = who; ; p++) {
1853: if (i == SLOT_NAMEMAX - 1 || *p == '\0') {
1854: name[i] = '\0';
1855: break;
1856: } else if (*p >= 'A' && *p <= 'Z') {
1857: name[i++] = *p + 'a' - 'A';
1858: } else if (*p >= 'a' && *p <= 'z')
1859: name[i++] = *p;
1860: }
1861: if (i == 0)
1862: strlcpy(name, "noname", SLOT_NAMEMAX);
1863:
1864: /*
1.52 ratchov 1865: * build a unit-to-slot map for this name
1.1 ratchov 1866: */
1.52 ratchov 1867: for (i = 0; i < DEV_NSLOT; i++)
1868: unit[i] = NULL;
1.84 ratchov 1869: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.1 ratchov 1870: if (strcmp(s->name, name) == 0)
1.52 ratchov 1871: unit[s->unit] = s;
1.1 ratchov 1872: }
1873:
1874: /*
1.54 ratchov 1875: * find the free slot with the least unit number and same id
1876: */
1877: for (i = 0; i < DEV_NSLOT; i++) {
1878: s = unit[i];
1879: if (s != NULL && s->ops == NULL && s->id == id)
1880: goto found;
1881: }
1882:
1883: /*
1.52 ratchov 1884: * find the free slot with the least unit number
1.1 ratchov 1885: */
1.52 ratchov 1886: for (i = 0; i < DEV_NSLOT; i++) {
1887: s = unit[i];
1.54 ratchov 1888: if (s != NULL && s->ops == NULL) {
1889: s->id = id;
1.1 ratchov 1890: goto found;
1.54 ratchov 1891: }
1.1 ratchov 1892: }
1893:
1894: /*
1.18 ratchov 1895: * couldn't find a matching slot, pick oldest free slot
1.1 ratchov 1896: * and set its name/unit
1897: */
1898: bestser = 0;
1899: bestidx = DEV_NSLOT;
1.84 ratchov 1900: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.1 ratchov 1901: if (s->ops != NULL)
1902: continue;
1.84 ratchov 1903: ser = slot_serial - s->serial;
1.1 ratchov 1904: if (ser > bestser) {
1905: bestser = ser;
1906: bestidx = i;
1907: }
1908: }
1.51 ratchov 1909: if (bestidx != DEV_NSLOT) {
1.84 ratchov 1910: s = slot_array + bestidx;
1.51 ratchov 1911: s->vol = MIDI_MAXCTL;
1912: strlcpy(s->name, name, SLOT_NAMEMAX);
1.84 ratchov 1913: s->serial = slot_serial++;
1.52 ratchov 1914: for (i = 0; unit[i] != NULL; i++)
1915: ; /* nothing */
1916: s->unit = i;
1.54 ratchov 1917: s->id = id;
1.51 ratchov 1918: goto found;
1.1 ratchov 1919: }
1.53 ratchov 1920:
1.51 ratchov 1921: if (log_level >= 1) {
1.1 ratchov 1922: log_puts(name);
1.51 ratchov 1923: log_puts(": out of sub-device slots\n");
1.1 ratchov 1924: }
1.51 ratchov 1925: return NULL;
1.1 ratchov 1926:
1927: found:
1.37 ratchov 1928: if ((mode & MODE_REC) && (opt->mode & MODE_MON)) {
1929: mode |= MODE_MON;
1930: mode &= ~MODE_REC;
1931: }
1932: if ((mode & opt->mode) != mode) {
1933: if (log_level >= 1) {
1934: slot_log(s);
1935: log_puts(": requested mode not allowed\n");
1936: }
1.89 ratchov 1937: return NULL;
1.37 ratchov 1938: }
1.89 ratchov 1939: if (!dev_ref(opt->dev))
1.1 ratchov 1940: return NULL;
1.89 ratchov 1941: if ((mode & opt->dev->mode) != mode) {
1.1 ratchov 1942: if (log_level >= 1) {
1943: slot_log(s);
1944: log_puts(": requested mode not supported\n");
1945: }
1946: }
1.37 ratchov 1947: s->opt = opt;
1.31 ratchov 1948: s->ops = ops;
1949: s->arg = arg;
1950: s->pstate = SLOT_INIT;
1.1 ratchov 1951: s->mode = mode;
1.6 ratchov 1952: aparams_init(&s->par);
1.41 ratchov 1953: if (s->mode & MODE_PLAY)
1.42 ratchov 1954: s->mix.nch = s->opt->pmax - s->opt->pmin + 1;
1.41 ratchov 1955: if (s->mode & MODE_RECMASK)
1.42 ratchov 1956: s->sub.nch = s->opt->rmax - s->opt->rmin + 1;
1.46 ratchov 1957: s->xrun = s->opt->mmc ? XRUN_SYNC : XRUN_IGNORE;
1.89 ratchov 1958: s->appbufsz = s->opt->dev->bufsz;
1959: s->round = s->opt->dev->round;
1960: s->rate = s->opt->dev->rate;
1961: dev_label(s->opt->dev, s - slot_array);
1962: dev_midi_slotdesc(s->opt->dev, s);
1963: dev_midi_vol(s->opt->dev, s);
1.43 ratchov 1964: #ifdef DEBUG
1965: if (log_level >= 3) {
1966: slot_log(s);
1967: log_puts(": using ");
1.89 ratchov 1968: dev_log(s->opt->dev);
1.43 ratchov 1969: log_puts(".");
1.89 ratchov 1970: log_puts(s->opt->name);
1.43 ratchov 1971: log_puts(", mode = ");
1972: log_putx(mode);
1973: log_puts("\n");
1974: }
1975: #endif
1.1 ratchov 1976: return s;
1977: }
1978:
1979: /*
1980: * release the given slot
1981: */
1982: void
1983: slot_del(struct slot *s)
1984: {
1985: s->arg = s;
1986: s->ops = &zomb_slotops;
1987: switch (s->pstate) {
1988: case SLOT_INIT:
1989: s->ops = NULL;
1990: break;
1991: case SLOT_START:
1992: case SLOT_READY:
1993: case SLOT_RUN:
1994: case SLOT_STOP:
1.82 ratchov 1995: slot_stop(s, 0);
1.1 ratchov 1996: break;
1997: }
1.89 ratchov 1998: dev_unref(s->opt->dev);
1.1 ratchov 1999: }
2000:
2001: /*
2002: * change the slot play volume; called either by the slot or by MIDI
2003: */
2004: void
2005: slot_setvol(struct slot *s, unsigned int vol)
2006: {
2007: #ifdef DEBUG
2008: if (log_level >= 3) {
2009: slot_log(s);
2010: log_puts(": setting volume ");
2011: log_putu(vol);
2012: log_puts("\n");
2013: }
2014: #endif
2015: s->vol = vol;
2016: s->mix.vol = MIDI_TO_ADATA(s->vol);
2017: }
2018:
2019: /*
2020: * attach the slot to the device (ie start playing & recording
2021: */
2022: void
2023: slot_attach(struct slot *s)
2024: {
1.89 ratchov 2025: struct dev *d = s->opt->dev;
1.12 ratchov 2026: long long pos;
1.1 ratchov 2027:
2028: /*
2029: * start the device if not started
2030: */
2031: dev_wakeup(d);
1.23 ratchov 2032:
1.1 ratchov 2033: /*
1.12 ratchov 2034: * adjust initial clock
2035: */
1.79 ratchov 2036: pos = s->delta_rem +
2037: (long long)s->delta * d->round +
2038: (long long)d->delta * s->round;
2039: s->delta = pos / (int)d->round;
1.12 ratchov 2040: s->delta_rem = pos % d->round;
1.79 ratchov 2041: if (s->delta_rem < 0) {
2042: s->delta_rem += d->round;
2043: s->delta--;
2044: }
1.12 ratchov 2045:
1.1 ratchov 2046: #ifdef DEBUG
1.17 ratchov 2047: if (log_level >= 2) {
1.1 ratchov 2048: slot_log(s);
2049: log_puts(": attached at ");
1.79 ratchov 2050: log_puti(s->delta);
2051: log_puts(" + ");
2052: log_puti(s->delta_rem);
2053: log_puts("/");
2054: log_puti(s->round);
1.1 ratchov 2055: log_puts("\n");
2056: }
2057: #endif
2058:
2059: /*
2060: * We dont check whether the device is dying,
2061: * because dev_xxx() functions are supposed to
2062: * work (i.e., not to crash)
2063: */
1.91 ! edd 2064:
1.1 ratchov 2065: s->next = d->slot_list;
2066: d->slot_list = s;
2067: if (s->mode & MODE_PLAY) {
2068: s->mix.vol = MIDI_TO_ADATA(s->vol);
2069: dev_mix_adjvol(d);
2070: }
2071: }
2072:
2073: /*
2074: * if MMC is enabled, and try to attach all slots synchronously, else
2075: * simply attach the slot
2076: */
2077: void
2078: slot_ready(struct slot *s)
2079: {
1.3 ratchov 2080: /*
2081: * device may be disconnected, and if so we're called from
2082: * slot->ops->exit() on a closed device
1.23 ratchov 2083: */
1.89 ratchov 2084: if (s->opt->dev->pstate == DEV_CFG)
1.3 ratchov 2085: return;
1.79 ratchov 2086: if (!s->opt->mmc) {
1.1 ratchov 2087: slot_attach(s);
1.79 ratchov 2088: s->pstate = SLOT_RUN;
2089: } else
1.89 ratchov 2090: dev_sync_attach(s->opt->dev);
1.1 ratchov 2091: }
2092:
2093: /*
2094: * setup buffers & conversion layers, prepare the slot to receive data
2095: * (for playback) or start (recording).
2096: */
2097: void
2098: slot_start(struct slot *s)
2099: {
1.89 ratchov 2100: struct dev *d = s->opt->dev;
1.1 ratchov 2101: #ifdef DEBUG
2102: if (s->pstate != SLOT_INIT) {
2103: slot_log(s);
2104: log_puts(": slot_start: wrong state\n");
2105: panic();
2106: }
2107: if (s->mode & MODE_PLAY) {
2108: if (log_level >= 3) {
2109: slot_log(s);
2110: log_puts(": playing ");
2111: aparams_log(&s->par);
2112: log_puts(" -> ");
1.81 ratchov 2113: aparams_log(&d->par);
1.1 ratchov 2114: log_puts("\n");
2115: }
2116: }
2117: if (s->mode & MODE_RECMASK) {
2118: if (log_level >= 3) {
2119: slot_log(s);
2120: log_puts(": recording ");
2121: aparams_log(&s->par);
2122: log_puts(" <- ");
1.81 ratchov 2123: aparams_log(&d->par);
1.1 ratchov 2124: log_puts("\n");
1.35 ratchov 2125: }
1.1 ratchov 2126: }
2127: #endif
1.35 ratchov 2128: slot_allocbufs(s);
1.47 ratchov 2129:
2130: if (s->mode & MODE_RECMASK) {
2131: /*
2132: * N-th recorded block is the N-th played block
2133: */
1.81 ratchov 2134: s->sub.prime = -dev_getpos(d) / d->round;
1.47 ratchov 2135: }
2136: s->skip = 0;
2137:
1.79 ratchov 2138: /*
2139: * get the current position, the origin is when the first sample
2140: * played and/or recorded
2141: */
1.81 ratchov 2142: s->delta = dev_getpos(d) * (int)s->round / (int)d->round;
1.79 ratchov 2143: s->delta_rem = 0;
2144:
1.1 ratchov 2145: if (s->mode & MODE_PLAY) {
2146: s->pstate = SLOT_START;
2147: } else {
2148: s->pstate = SLOT_READY;
2149: slot_ready(s);
2150: }
2151: }
2152:
2153: /*
2154: * stop playback and recording, and free conversion layers
2155: */
2156: void
2157: slot_detach(struct slot *s)
2158: {
2159: struct slot **ps;
1.89 ratchov 2160: struct dev *d = s->opt->dev;
1.79 ratchov 2161: long long pos;
1.1 ratchov 2162:
1.81 ratchov 2163: for (ps = &d->slot_list; *ps != s; ps = &(*ps)->next) {
1.1 ratchov 2164: #ifdef DEBUG
1.28 ratchov 2165: if (*ps == NULL) {
1.1 ratchov 2166: slot_log(s);
2167: log_puts(": can't detach, not on list\n");
2168: panic();
2169: }
2170: #endif
1.23 ratchov 2171: }
1.1 ratchov 2172: *ps = s->next;
1.79 ratchov 2173:
2174: /*
2175: * adjust clock, go back d->delta ticks so that slot_attach()
2176: * could be called with the resulting state
2177: */
2178: pos = s->delta_rem +
2179: (long long)s->delta * d->round -
2180: (long long)d->delta * s->round;
2181: s->delta = pos / (int)d->round;
2182: s->delta_rem = pos % d->round;
2183: if (s->delta_rem < 0) {
2184: s->delta_rem += d->round;
2185: s->delta--;
2186: }
2187:
2188: #ifdef DEBUG
2189: if (log_level >= 2) {
2190: slot_log(s);
2191: log_puts(": detached at ");
2192: log_puti(s->delta);
2193: log_puts(" + ");
2194: log_puti(s->delta_rem);
2195: log_puts("/");
2196: log_puti(d->round);
2197: log_puts("\n");
2198: }
2199: #endif
1.35 ratchov 2200: if (s->mode & MODE_PLAY)
1.81 ratchov 2201: dev_mix_adjvol(d);
1.1 ratchov 2202: }
2203:
2204: /*
2205: * put the slot in stopping state (draining play buffers) or
2206: * stop & detach if no data to drain.
2207: */
2208: void
1.82 ratchov 2209: slot_stop(struct slot *s, int drain)
1.1 ratchov 2210: {
2211: #ifdef DEBUG
2212: if (log_level >= 3) {
2213: slot_log(s);
2214: log_puts(": stopping\n");
2215: }
2216: #endif
2217: if (s->pstate == SLOT_START) {
1.33 ratchov 2218: /*
2219: * If in rec-only mode, we're already in the READY or
2220: * RUN states. We're here because the play buffer was
2221: * not full enough, try to start so it's drained.
2222: */
2223: s->pstate = SLOT_READY;
2224: slot_ready(s);
1.1 ratchov 2225: }
1.34 ratchov 2226:
2227: if (s->pstate == SLOT_RUN) {
1.82 ratchov 2228: if ((s->mode & MODE_PLAY) && drain) {
1.34 ratchov 2229: /*
2230: * Don't detach, dev_cycle() will do it for us
2231: * when the buffer is drained.
2232: */
2233: s->pstate = SLOT_STOP;
2234: return;
2235: }
1.82 ratchov 2236: slot_detach(s);
2237: } else if (s->pstate == SLOT_STOP) {
1.34 ratchov 2238: slot_detach(s);
2239: } else {
1.1 ratchov 2240: #ifdef DEBUG
2241: if (log_level >= 3) {
2242: slot_log(s);
2243: log_puts(": not drained (blocked by mmc)\n");
2244: }
2245: #endif
2246: }
1.35 ratchov 2247:
1.34 ratchov 2248: s->pstate = SLOT_INIT;
2249: s->ops->eof(s->arg);
1.35 ratchov 2250: slot_freebufs(s);
1.1 ratchov 2251: }
2252:
1.12 ratchov 2253: void
2254: slot_skip_update(struct slot *s)
2255: {
2256: int skip;
2257:
2258: skip = slot_skip(s);
2259: while (skip > 0) {
2260: #ifdef DEBUG
2261: if (log_level >= 4) {
2262: slot_log(s);
2263: log_puts(": catching skipped block\n");
2264: }
2265: #endif
2266: if (s->mode & MODE_RECMASK)
2267: s->ops->flush(s->arg);
2268: if (s->mode & MODE_PLAY)
2269: s->ops->fill(s->arg);
2270: skip--;
2271: }
2272: }
2273:
1.1 ratchov 2274: /*
2275: * notify the slot that we just wrote in the play buffer, must be called
2276: * after each write
2277: */
2278: void
2279: slot_write(struct slot *s)
2280: {
2281: if (s->pstate == SLOT_START && s->mix.buf.used == s->mix.buf.len) {
2282: #ifdef DEBUG
2283: if (log_level >= 4) {
2284: slot_log(s);
2285: log_puts(": switching to READY state\n");
2286: }
2287: #endif
2288: s->pstate = SLOT_READY;
2289: slot_ready(s);
2290: }
1.12 ratchov 2291: slot_skip_update(s);
1.1 ratchov 2292: }
2293:
2294: /*
2295: * notify the slot that we freed some space in the rec buffer
2296: */
2297: void
2298: slot_read(struct slot *s)
2299: {
1.12 ratchov 2300: slot_skip_update(s);
1.64 ratchov 2301: }
2302:
2303: /*
2304: * allocate at control slot
2305: */
2306: struct ctlslot *
1.88 ratchov 2307: ctlslot_new(struct opt *o, struct ctlops *ops, void *arg)
1.64 ratchov 2308: {
2309: struct ctlslot *s;
2310: struct ctl *c;
2311: int i;
2312:
2313: i = 0;
2314: for (;;) {
2315: if (i == DEV_NCTLSLOT)
2316: return NULL;
1.85 ratchov 2317: s = ctlslot_array + i;
1.64 ratchov 2318: if (s->ops == NULL)
2319: break;
2320: i++;
2321: }
1.88 ratchov 2322: s->opt = o;
1.87 ratchov 2323: s->self = 1 << i;
1.88 ratchov 2324: if (!dev_ref(o->dev))
1.64 ratchov 2325: return NULL;
2326: s->ops = ops;
2327: s->arg = arg;
1.88 ratchov 2328: for (c = o->dev->ctl_list; c != NULL; c = c->next)
1.87 ratchov 2329: c->refs_mask |= s->self;
1.64 ratchov 2330: return s;
2331: }
2332:
2333: /*
2334: * free control slot
2335: */
2336: void
2337: ctlslot_del(struct ctlslot *s)
2338: {
2339: struct ctl *c, **pc;
2340:
1.88 ratchov 2341: pc = &s->opt->dev->ctl_list;
1.64 ratchov 2342: while ((c = *pc) != NULL) {
1.87 ratchov 2343: c->refs_mask &= ~s->self;
1.64 ratchov 2344: if (c->refs_mask == 0) {
2345: *pc = c->next;
2346: xfree(c);
2347: } else
2348: pc = &c->next;
2349: }
2350: s->ops = NULL;
1.88 ratchov 2351: dev_unref(s->opt->dev);
1.64 ratchov 2352: }
2353:
2354: void
2355: ctl_node_log(struct ctl_node *c)
2356: {
2357: log_puts(c->name);
2358: if (c->unit >= 0)
2359: log_putu(c->unit);
2360: }
2361:
2362: void
2363: ctl_log(struct ctl *c)
2364: {
2365: if (c->group[0] != 0) {
2366: log_puts(c->group);
2367: log_puts("/");
2368: }
2369: ctl_node_log(&c->node0);
2370: log_puts(".");
2371: log_puts(c->func);
2372: log_puts("=");
2373: switch (c->type) {
1.67 ratchov 2374: case CTL_NONE:
2375: log_puts("none");
2376: break;
1.64 ratchov 2377: case CTL_NUM:
2378: case CTL_SW:
2379: log_putu(c->curval);
2380: break;
2381: case CTL_VEC:
2382: case CTL_LIST:
1.74 ratchov 2383: case CTL_SEL:
1.64 ratchov 2384: ctl_node_log(&c->node1);
2385: log_puts(":");
2386: log_putu(c->curval);
2387: }
2388: log_puts(" at ");
2389: log_putu(c->addr);
2390: }
2391:
2392: /*
2393: * add a ctl
2394: */
2395: struct ctl *
2396: dev_addctl(struct dev *d, char *gstr, int type, int addr,
2397: char *str0, int unit0, char *func, char *str1, int unit1, int maxval, int val)
2398: {
2399: struct ctl *c, **pc;
2400: int i;
2401:
2402: c = xmalloc(sizeof(struct ctl));
2403: c->type = type;
2404: strlcpy(c->func, func, CTL_NAMEMAX);
2405: strlcpy(c->group, gstr, CTL_NAMEMAX);
2406: strlcpy(c->node0.name, str0, CTL_NAMEMAX);
2407: c->node0.unit = unit0;
1.74 ratchov 2408: if (c->type == CTL_VEC || c->type == CTL_LIST || c->type == CTL_SEL) {
1.64 ratchov 2409: strlcpy(c->node1.name, str1, CTL_NAMEMAX);
2410: c->node1.unit = unit1;
2411: } else
2412: memset(&c->node1, 0, sizeof(struct ctl_node));
2413: c->addr = addr;
2414: c->maxval = maxval;
2415: c->val_mask = ~0;
2416: c->desc_mask = ~0;
2417: c->curval = val;
2418: c->dirty = 0;
2419: c->refs_mask = 0;
2420: for (i = 0; i < DEV_NCTLSLOT; i++) {
2421: c->refs_mask |= CTL_DEVMASK;
1.85 ratchov 2422: if (ctlslot_array[i].ops != NULL)
1.64 ratchov 2423: c->refs_mask |= 1 << i;
2424: }
2425: for (pc = &d->ctl_list; *pc != NULL; pc = &(*pc)->next)
2426: ; /* nothing */
2427: c->next = NULL;
2428: *pc = c;
2429: #ifdef DEBUG
2430: if (log_level >= 3) {
2431: dev_log(d);
2432: log_puts(": adding ");
2433: ctl_log(c);
2434: log_puts("\n");
2435: }
2436: #endif
2437: return c;
2438: }
2439:
2440: void
2441: dev_rmctl(struct dev *d, int addr)
2442: {
2443: struct ctl *c, **pc;
2444:
2445: pc = &d->ctl_list;
2446: for (;;) {
2447: c = *pc;
2448: if (c == NULL)
2449: return;
2450: if (c->type != CTL_NONE && c->addr == addr)
2451: break;
2452: pc = &c->next;
2453: }
2454: c->type = CTL_NONE;
2455: #ifdef DEBUG
2456: if (log_level >= 3) {
2457: dev_log(d);
2458: log_puts(": removing ");
2459: ctl_log(c);
2460: log_puts(", refs_mask = 0x");
2461: log_putx(c->refs_mask);
2462: log_puts("\n");
2463: }
2464: #endif
2465: c->refs_mask &= ~CTL_DEVMASK;
1.68 ratchov 2466: if (c->refs_mask == 0) {
2467: *pc = c->next;
2468: xfree(c);
1.64 ratchov 2469: return;
1.68 ratchov 2470: }
2471: c->desc_mask = ~0;
1.65 ratchov 2472: }
2473:
2474: void
2475: dev_ctlsync(struct dev *d)
2476: {
1.70 ratchov 2477: struct ctl *c;
1.65 ratchov 2478: struct ctlslot *s;
1.70 ratchov 2479: int found, i;
2480:
2481: found = 0;
2482: for (c = d->ctl_list; c != NULL; c = c->next) {
2483: if (c->addr != CTLADDR_MASTER &&
2484: c->type == CTL_NUM &&
2485: strcmp(c->group, "") == 0 &&
2486: strcmp(c->node0.name, "output") == 0 &&
2487: strcmp(c->func, "level") == 0)
2488: found = 1;
2489: }
2490:
2491: if (d->master_enabled && found) {
2492: if (log_level >= 2) {
2493: dev_log(d);
2494: log_puts(": software master level control disabled\n");
2495: }
2496: d->master_enabled = 0;
2497: dev_rmctl(d, CTLADDR_MASTER);
2498: } else if (!d->master_enabled && !found) {
2499: if (log_level >= 2) {
2500: dev_log(d);
2501: log_puts(": software master level control enabled\n");
2502: }
2503: d->master_enabled = 1;
2504: dev_addctl(d, "", CTL_NUM, CTLADDR_MASTER,
2505: "output", -1, "level", NULL, -1, 127, d->master);
2506: }
1.65 ratchov 2507:
1.85 ratchov 2508: for (s = ctlslot_array, i = DEV_NCTLSLOT; i > 0; i--, s++) {
1.88 ratchov 2509: if (s->ops && s->opt->dev == d)
1.65 ratchov 2510: s->ops->sync(s->arg);
2511: }
1.64 ratchov 2512: }
2513:
2514: int
2515: dev_setctl(struct dev *d, int addr, int val)
2516: {
2517: struct ctl *c;
1.84 ratchov 2518: struct slot *s;
1.64 ratchov 2519: int num;
2520:
2521: c = d->ctl_list;
2522: for (;;) {
2523: if (c == NULL) {
2524: if (log_level >= 3) {
2525: dev_log(d);
2526: log_puts(": ");
2527: log_putu(addr);
2528: log_puts(": no such ctl address\n");
2529: }
2530: return 0;
2531: }
2532: if (c->type != CTL_NONE && c->addr == addr)
2533: break;
2534: c = c->next;
2535: }
2536: if (c->curval == val) {
2537: if (log_level >= 3) {
2538: ctl_log(c);
2539: log_puts(": already set\n");
2540: }
2541: return 1;
2542: }
2543: if (val < 0 || val > c->maxval) {
2544: if (log_level >= 3) {
2545: dev_log(d);
2546: log_puts(": ");
2547: log_putu(val);
2548: log_puts(": ctl val out of bounds\n");
2549: }
2550: return 0;
2551: }
2552: if (addr >= CTLADDR_END) {
2553: if (log_level >= 3) {
2554: ctl_log(c);
2555: log_puts(": marked as dirty\n");
2556: }
2557: c->dirty = 1;
2558: dev_ref(d);
2559: } else {
1.75 ratchov 2560: if (addr >= CTLADDR_ALT_SEL) {
2561: if (val) {
2562: num = addr - CTLADDR_ALT_SEL;
2563: dev_setalt(d, num);
2564: }
2565: return 1;
2566: } else if (addr == CTLADDR_MASTER) {
1.70 ratchov 2567: if (d->master_enabled) {
2568: dev_master(d, val);
2569: dev_midi_master(d);
2570: }
1.64 ratchov 2571: } else {
2572: num = addr - CTLADDR_SLOT_LEVEL(0);
1.84 ratchov 2573: s = slot_array + num;
1.89 ratchov 2574: if (s->opt->dev != d)
1.84 ratchov 2575: return 1;
2576: slot_setvol(s, val);
2577: dev_midi_vol(d, s);
1.64 ratchov 2578: }
1.66 ratchov 2579: c->val_mask = ~0U;
1.64 ratchov 2580: }
2581: c->curval = val;
2582: return 1;
2583: }
2584:
2585: int
2586: dev_onval(struct dev *d, int addr, int val)
2587: {
2588: struct ctl *c;
2589:
2590: c = d->ctl_list;
2591: for (;;) {
2592: if (c == NULL)
2593: return 0;
2594: if (c->type != CTL_NONE && c->addr == addr)
2595: break;
2596: c = c->next;
2597: }
2598: c->curval = val;
2599: c->val_mask = ~0U;
2600: return 1;
2601: }
2602:
2603: void
2604: dev_label(struct dev *d, int i)
2605: {
2606: struct ctl *c;
2607: char name[CTL_NAMEMAX];
2608:
1.84 ratchov 2609: slot_ctlname(&slot_array[i], name, CTL_NAMEMAX);
1.69 ratchov 2610:
1.64 ratchov 2611: c = d->ctl_list;
2612: for (;;) {
1.69 ratchov 2613: if (c == NULL) {
2614: dev_addctl(d, "app", CTL_NUM,
2615: CTLADDR_SLOT_LEVEL(i),
2616: name, -1, "level",
1.84 ratchov 2617: NULL, -1, 127, slot_array[i].vol);
1.64 ratchov 2618: return;
1.69 ratchov 2619: }
1.64 ratchov 2620: if (c->addr == CTLADDR_SLOT_LEVEL(i))
2621: break;
2622: c = c->next;
2623: }
2624: if (strcmp(c->node0.name, name) == 0)
2625: return;
2626: strlcpy(c->node0.name, name, CTL_NAMEMAX);
2627: c->desc_mask = ~0;
1.1 ratchov 2628: }