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