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