Annotation of src/usr.bin/sndiod/dev.c, Revision 1.98
1.98 ! ratchov 1: /* $OpenBSD: dev.c,v 1.97 2021/03/08 09:42:50 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: {
1.97 ratchov 919: struct dev *d, **pd;
1.1 ratchov 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.97 ratchov 946: for (pd = &dev_list; *pd != NULL; pd = &(*pd)->next)
947: ;
948: d->next = *pd;
949: *pd = d;
1.1 ratchov 950: return d;
951: }
952:
953: /*
1.73 ratchov 954: * add a alternate name
955: */
956: int
957: dev_addname(struct dev *d, char *name)
958: {
959: struct dev_alt *a;
960:
961: if (d->alt_list != NULL && d->alt_list->idx == DEV_NMAX - 1) {
962: log_puts(name);
963: log_puts(": too many alternate names\n");
964: return 0;
965: }
966: a = xmalloc(sizeof(struct dev_alt));
967: a->name = name;
968: a->idx = (d->alt_list == NULL) ? 0 : d->alt_list->idx + 1;
969: a->next = d->alt_list;
970: d->alt_list = a;
971: return 1;
972: }
973:
974: /*
1.75 ratchov 975: * set prefered alt device name
976: */
977: void
978: dev_setalt(struct dev *d, unsigned int idx)
979: {
980: struct dev_alt **pa, *a;
981:
982: /* find alt with given index */
983: for (pa = &d->alt_list; (a = *pa)->idx != idx; pa = &a->next)
984: ;
985:
986: /* detach from list */
987: *pa = a->next;
988:
989: /* attach at head */
990: a->next = d->alt_list;
991: d->alt_list = a;
992:
993: /* reopen device with the new alt */
994: if (idx != d->alt_num)
995: dev_reopen(d);
996: }
997:
998: /*
1.1 ratchov 999: * adjust device parameters and mode
1000: */
1001: void
1002: dev_adjpar(struct dev *d, int mode,
1.25 ratchov 1003: int pmax, int rmax)
1.1 ratchov 1004: {
1005: d->reqmode |= mode & MODE_AUDIOMASK;
1006: if (mode & MODE_PLAY) {
1007: if (d->reqpchan < pmax + 1)
1008: d->reqpchan = pmax + 1;
1009: }
1010: if (mode & MODE_REC) {
1011: if (d->reqrchan < rmax + 1)
1012: d->reqrchan = rmax + 1;
1013: }
1014: }
1015:
1016: /*
1017: * Open the device with the dev_reqxxx capabilities. Setup a mixer, demuxer,
1018: * monitor, midi control, and any necessary conversions.
1.91 edd 1019: *
1020: * Note that record and play buffers are always allocated, even if the
1021: * underlying device doesn't support both modes.
1.1 ratchov 1022: */
1023: int
1.59 ratchov 1024: dev_allocbufs(struct dev *d)
1.1 ratchov 1025: {
1.91 edd 1026: /*
1027: * Create record buffer.
1028: */
1029:
1030: /* Create device <-> demuxer buffer */
1031: d->rbuf = xmalloc(d->round * d->rchan * sizeof(adata_t));
1032:
1033: /* Insert a converter, if needed. */
1034: if (!aparams_native(&d->par)) {
1035: dec_init(&d->dec, &d->par, d->rchan);
1036: d->decbuf = xmalloc(d->round * d->rchan * d->par.bps);
1037: } else
1038: d->decbuf = NULL;
1039:
1040: /*
1041: * Create play buffer
1042: */
1043:
1044: /* Create device <-> mixer buffer */
1045: d->poffs = 0;
1046: d->psize = d->bufsz + d->round;
1047: d->pbuf = xmalloc(d->psize * d->pchan * sizeof(adata_t));
1048: d->mode |= MODE_MON;
1049:
1050: /* Append a converter, if needed. */
1051: if (!aparams_native(&d->par)) {
1052: enc_init(&d->enc, &d->par, d->pchan);
1053: d->encbuf = xmalloc(d->round * d->pchan * d->par.bps);
1054: } else
1055: d->encbuf = NULL;
1.1 ratchov 1056:
1.91 edd 1057: /*
1058: * Initially fill the record buffer with zeroed samples. This ensures
1059: * that when a client records from a play-only device the client just
1060: * gets silence.
1061: */
1062: memset(d->rbuf, 0, d->round * d->rchan * sizeof(adata_t));
1.1 ratchov 1063:
1064: if (log_level >= 2) {
1065: dev_log(d);
1066: log_puts(": ");
1067: log_putu(d->rate);
1068: log_puts("Hz, ");
1069: aparams_log(&d->par);
1070: if (d->mode & MODE_PLAY) {
1071: log_puts(", play 0:");
1072: log_puti(d->pchan - 1);
1073: }
1074: if (d->mode & MODE_REC) {
1075: log_puts(", rec 0:");
1076: log_puti(d->rchan - 1);
1077: }
1078: log_puts(", ");
1079: log_putu(d->bufsz / d->round);
1080: log_puts(" blocks of ");
1081: log_putu(d->round);
1.94 ratchov 1082: log_puts(" frames");
1083: if (d == mtc_array[0].dev)
1084: log_puts(", mtc");
1085: log_puts("\n");
1.1 ratchov 1086: }
1.57 ratchov 1087: return 1;
1088: }
1089:
1090: /*
1091: * Reset parameters and open the device.
1092: */
1093: int
1094: dev_open(struct dev *d)
1095: {
1.64 ratchov 1096: char name[CTL_NAMEMAX];
1.75 ratchov 1097: struct dev_alt *a;
1.64 ratchov 1098:
1.57 ratchov 1099: d->mode = d->reqmode;
1100: d->round = d->reqround;
1101: d->bufsz = d->reqbufsz;
1102: d->rate = d->reqrate;
1103: d->pchan = d->reqpchan;
1104: d->rchan = d->reqrchan;
1105: d->par = d->reqpar;
1106: if (d->pchan == 0)
1107: d->pchan = 2;
1108: if (d->rchan == 0)
1109: d->rchan = 2;
1.59 ratchov 1110: if (!dev_sio_open(d)) {
1111: if (log_level >= 1) {
1112: dev_log(d);
1113: log_puts(": failed to open audio device\n");
1114: }
1115: return 0;
1116: }
1117: if (!dev_allocbufs(d))
1.57 ratchov 1118: return 0;
1.64 ratchov 1119:
1.77 ratchov 1120: /* if there are multiple alt devs, add server.device knob */
1121: if (d->alt_list->next != NULL) {
1122: for (a = d->alt_list; a != NULL; a = a->next) {
1123: snprintf(name, sizeof(name), "%d", a->idx);
1.92 ratchov 1124: ctl_new(CTL_DEV_ALT, d, &a->idx,
1125: CTL_SEL, d->name, "server", -1, "device",
1.77 ratchov 1126: name, -1, 1, a->idx == d->alt_num);
1127: }
1.75 ratchov 1128: }
1129:
1.59 ratchov 1130: d->pstate = DEV_INIT;
1.1 ratchov 1131: return 1;
1132: }
1133:
1134: /*
1.72 ratchov 1135: * Force all slots to exit and close device, called after an error
1.55 ratchov 1136: */
1137: void
1.72 ratchov 1138: dev_abort(struct dev *d)
1.55 ratchov 1139: {
1140: int i;
1141: struct slot *s;
1.64 ratchov 1142: struct ctlslot *c;
1.93 ratchov 1143: struct opt *o;
1.55 ratchov 1144:
1.84 ratchov 1145: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.89 ratchov 1146: if (s->opt == NULL || s->opt->dev != d)
1.84 ratchov 1147: continue;
1.89 ratchov 1148: if (s->ops) {
1.55 ratchov 1149: s->ops->exit(s->arg);
1.89 ratchov 1150: s->ops = NULL;
1151: }
1.55 ratchov 1152: }
1153: d->slot_list = NULL;
1.64 ratchov 1154:
1.95 ratchov 1155: for (c = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, c++) {
1.90 ratchov 1156: if (c->ops == NULL)
1157: continue;
1.88 ratchov 1158: if (c->opt->dev != d)
1.85 ratchov 1159: continue;
1.90 ratchov 1160: c->ops->exit(c->arg);
1161: c->ops = NULL;
1.64 ratchov 1162: }
1.83 ratchov 1163:
1.93 ratchov 1164: for (o = opt_list; o != NULL; o = o->next) {
1165: if (o->dev != d)
1166: continue;
1167: midi_abort(o->midi);
1168: }
1.72 ratchov 1169:
1170: if (d->pstate != DEV_CFG)
1171: dev_close(d);
1.55 ratchov 1172: }
1173:
1174: /*
1.1 ratchov 1175: * force the device to go in DEV_CFG state, the caller is supposed to
1176: * ensure buffers are drained
1177: */
1178: void
1.59 ratchov 1179: dev_freebufs(struct dev *d)
1.1 ratchov 1180: {
1181: #ifdef DEBUG
1182: if (log_level >= 3) {
1183: dev_log(d);
1184: log_puts(": closing\n");
1185: }
1186: #endif
1187: if (d->mode & MODE_PLAY) {
1188: if (d->encbuf != NULL)
1189: xfree(d->encbuf);
1190: xfree(d->pbuf);
1191: }
1192: if (d->mode & MODE_REC) {
1193: if (d->decbuf != NULL)
1194: xfree(d->decbuf);
1195: xfree(d->rbuf);
1196: }
1.58 ratchov 1197: }
1198:
1199: /*
1200: * Close the device and exit all slots
1201: */
1202: void
1203: dev_close(struct dev *d)
1204: {
1.92 ratchov 1205: struct dev_alt *a;
1206: unsigned int idx;
1.64 ratchov 1207:
1.59 ratchov 1208: d->pstate = DEV_CFG;
1209: dev_sio_close(d);
1210: dev_freebufs(d);
1.64 ratchov 1211:
1.92 ratchov 1212: if (d->master_enabled) {
1213: d->master_enabled = 0;
1214: ctl_del(CTL_DEV_MASTER, d, NULL);
1.64 ratchov 1215: }
1.92 ratchov 1216: for (idx = 0, a = d->alt_list; a != NULL; idx++, a = a->next)
1217: ctl_del(CTL_DEV_ALT, d, &idx);
1.1 ratchov 1218: }
1219:
1.62 ratchov 1220: /*
1221: * Close the device, but attempt to migrate everything to a new sndio
1222: * device.
1223: */
1224: int
1225: dev_reopen(struct dev *d)
1226: {
1.94 ratchov 1227: struct mtc *mtc;
1.62 ratchov 1228: struct slot *s;
1229: long long pos;
1230: unsigned int pstate;
1231: int delta;
1232:
1233: /* not opened */
1234: if (d->pstate == DEV_CFG)
1235: return 1;
1236:
1237: /* save state */
1238: delta = d->delta;
1239: pstate = d->pstate;
1240:
1241: if (!dev_sio_reopen(d))
1242: return 0;
1243:
1244: /* reopen returns a stopped device */
1245: d->pstate = DEV_INIT;
1246:
1247: /* reallocate new buffers, with new parameters */
1248: dev_freebufs(d);
1249: dev_allocbufs(d);
1250:
1251: /*
1252: * adjust time positions, make anything go back delta ticks, so
1253: * that the new device can start at zero
1254: */
1255: for (s = d->slot_list; s != NULL; s = s->next) {
1256: pos = (long long)s->delta * d->round + s->delta_rem;
1257: pos -= (long long)delta * s->round;
1258: s->delta_rem = pos % (int)d->round;
1259: s->delta = pos / (int)d->round;
1260: if (log_level >= 3) {
1261: slot_log(s);
1262: log_puts(": adjusted: delta -> ");
1263: log_puti(s->delta);
1264: log_puts(", delta_rem -> ");
1265: log_puti(s->delta_rem);
1266: log_puts("\n");
1267: }
1268:
1269: /* reinitilize the format conversion chain */
1270: slot_initconv(s);
1271: }
1.94 ratchov 1272: mtc = &mtc_array[0];
1273: if (mtc->dev == d && mtc->tstate == MTC_RUN) {
1274: mtc->delta -= delta * MTC_SEC;
1.62 ratchov 1275: if (log_level >= 2) {
1.94 ratchov 1276: dev_log(mtc->dev);
1.62 ratchov 1277: log_puts(": adjusted mtc: delta ->");
1.94 ratchov 1278: log_puti(mtc->delta);
1.62 ratchov 1279: log_puts("\n");
1280: }
1281: }
1282:
1.71 ratchov 1283: /* remove old controls and add new ones */
1284: dev_sioctl_close(d);
1.64 ratchov 1285: dev_sioctl_open(d);
1286:
1.62 ratchov 1287: /* start the device if needed */
1288: if (pstate == DEV_RUN)
1289: dev_wakeup(d);
1290:
1291: return 1;
1292: }
1293:
1.1 ratchov 1294: int
1295: dev_ref(struct dev *d)
1296: {
1297: #ifdef DEBUG
1298: if (log_level >= 3) {
1299: dev_log(d);
1300: log_puts(": device requested\n");
1301: }
1302: #endif
1303: if (d->pstate == DEV_CFG && !dev_open(d))
1304: return 0;
1305: d->refcnt++;
1306: return 1;
1307: }
1308:
1309: void
1310: dev_unref(struct dev *d)
1311: {
1312: #ifdef DEBUG
1313: if (log_level >= 3) {
1314: dev_log(d);
1315: log_puts(": device released\n");
1316: }
1317: #endif
1318: d->refcnt--;
1319: if (d->refcnt == 0 && d->pstate == DEV_INIT)
1320: dev_close(d);
1321: }
1322:
1323: /*
1324: * initialize the device with the current parameters
1325: */
1326: int
1327: dev_init(struct dev *d)
1328: {
1329: if ((d->reqmode & MODE_AUDIOMASK) == 0) {
1330: #ifdef DEBUG
1331: dev_log(d);
1332: log_puts(": has no streams\n");
1333: #endif
1334: return 0;
1335: }
1336: if (d->hold && !dev_ref(d))
1337: return 0;
1338: return 1;
1339: }
1340:
1341: /*
1342: * Unless the device is already in process of closing, request it to close
1343: */
1344: void
1345: dev_done(struct dev *d)
1346: {
1347: #ifdef DEBUG
1348: if (log_level >= 3) {
1349: dev_log(d);
1350: log_puts(": draining\n");
1351: }
1352: #endif
1.94 ratchov 1353: if (mtc_array[0].dev == d && mtc_array[0].tstate != MTC_STOP)
1354: mtc_stop(&mtc_array[0]);
1.1 ratchov 1355: if (d->hold)
1356: dev_unref(d);
1357: }
1358:
1359: struct dev *
1360: dev_bynum(int num)
1361: {
1362: struct dev *d;
1363:
1364: for (d = dev_list; d != NULL; d = d->next) {
1.19 ratchov 1365: if (d->num == num)
1.1 ratchov 1366: return d;
1367: }
1368: return NULL;
1369: }
1370:
1371: /*
1372: * Free the device
1373: */
1374: void
1375: dev_del(struct dev *d)
1376: {
1377: struct dev **p;
1.73 ratchov 1378: struct dev_alt *a;
1.1 ratchov 1379:
1380: #ifdef DEBUG
1381: if (log_level >= 3) {
1382: dev_log(d);
1383: log_puts(": deleting\n");
1384: }
1385: #endif
1386: if (d->pstate != DEV_CFG)
1387: dev_close(d);
1388: for (p = &dev_list; *p != d; p = &(*p)->next) {
1389: #ifdef DEBUG
1390: if (*p == NULL) {
1391: dev_log(d);
1392: log_puts(": device to delete not on the list\n");
1393: panic();
1394: }
1395: #endif
1396: }
1397: *p = d->next;
1.73 ratchov 1398: while ((a = d->alt_list) != NULL) {
1399: d->alt_list = a->next;
1400: xfree(a);
1401: }
1.1 ratchov 1402: xfree(d);
1403: }
1404:
1405: unsigned int
1406: dev_roundof(struct dev *d, unsigned int newrate)
1407: {
1408: return (d->round * newrate + d->rate / 2) / d->rate;
1409: }
1410:
1411: /*
1412: * If the device is paused, then resume it.
1413: */
1414: void
1415: dev_wakeup(struct dev *d)
1416: {
1417: if (d->pstate == DEV_INIT) {
1418: if (log_level >= 2) {
1419: dev_log(d);
1420: log_puts(": device started\n");
1421: }
1422: if (d->mode & MODE_PLAY) {
1423: d->prime = d->bufsz;
1424: } else {
1425: d->prime = 0;
1426: }
1.16 ratchov 1427: d->poffs = 0;
1.12 ratchov 1428:
1.23 ratchov 1429: /*
1.16 ratchov 1430: * empty cycles don't increment delta, so it's ok to
1431: * start at 0
1432: **/
1.23 ratchov 1433: d->delta = 0;
1.12 ratchov 1434:
1.1 ratchov 1435: d->pstate = DEV_RUN;
1436: dev_sio_start(d);
1437: }
1438: }
1439:
1440: /*
1441: * check that all clients controlled by MMC are ready to start, if so,
1442: * attach them all at the same position
1443: */
1444: void
1.94 ratchov 1445: mtc_trigger(struct mtc *mtc)
1.1 ratchov 1446: {
1447: int i;
1448: struct slot *s;
1449:
1.94 ratchov 1450: if (mtc->tstate != MTC_START) {
1.1 ratchov 1451: if (log_level >= 2) {
1.94 ratchov 1452: dev_log(mtc->dev);
1.1 ratchov 1453: log_puts(": not started by mmc yet, waiting...\n");
1454: }
1455: return;
1456: }
1.84 ratchov 1457:
1458: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.94 ratchov 1459: if (s->opt == NULL || s->opt->mtc != mtc)
1.1 ratchov 1460: continue;
1.46 ratchov 1461: if (s->pstate != SLOT_READY) {
1.1 ratchov 1462: #ifdef DEBUG
1463: if (log_level >= 3) {
1464: slot_log(s);
1465: log_puts(": not ready, start delayed\n");
1466: }
1467: #endif
1468: return;
1469: }
1470: }
1.94 ratchov 1471: if (!dev_ref(mtc->dev))
1.1 ratchov 1472: return;
1.84 ratchov 1473:
1474: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.94 ratchov 1475: if (s->opt == NULL || s->opt->mtc != mtc)
1.1 ratchov 1476: continue;
1.46 ratchov 1477: slot_attach(s);
1.79 ratchov 1478: s->pstate = SLOT_RUN;
1.1 ratchov 1479: }
1.94 ratchov 1480: mtc->tstate = MTC_RUN;
1481: mtc_midi_full(mtc);
1482: dev_wakeup(mtc->dev);
1.1 ratchov 1483: }
1484:
1485: /*
1486: * start all slots simultaneously
1487: */
1488: void
1.94 ratchov 1489: mtc_start(struct mtc *mtc)
1.1 ratchov 1490: {
1.94 ratchov 1491: if (mtc->tstate == MTC_STOP) {
1492: mtc->tstate = MTC_START;
1493: mtc_trigger(mtc);
1.1 ratchov 1494: #ifdef DEBUG
1495: } else {
1496: if (log_level >= 3) {
1.94 ratchov 1497: dev_log(mtc->dev);
1.1 ratchov 1498: log_puts(": ignoring mmc start\n");
1499: }
1500: #endif
1501: }
1502: }
1503:
1504: /*
1505: * stop all slots simultaneously
1506: */
1507: void
1.94 ratchov 1508: mtc_stop(struct mtc *mtc)
1.1 ratchov 1509: {
1.94 ratchov 1510: switch (mtc->tstate) {
1511: case MTC_START:
1512: mtc->tstate = MTC_STOP;
1.1 ratchov 1513: return;
1.94 ratchov 1514: case MTC_RUN:
1515: mtc->tstate = MTC_STOP;
1516: dev_unref(mtc->dev);
1.1 ratchov 1517: break;
1518: default:
1519: #ifdef DEBUG
1520: if (log_level >= 3) {
1.94 ratchov 1521: dev_log(mtc->dev);
1.1 ratchov 1522: log_puts(": ignored mmc stop\n");
1523: }
1524: #endif
1525: return;
1526: }
1527: }
1528:
1529: /*
1530: * relocate all slots simultaneously
1531: */
1532: void
1.94 ratchov 1533: mtc_loc(struct mtc *mtc, unsigned int origin)
1.1 ratchov 1534: {
1535: if (log_level >= 2) {
1.94 ratchov 1536: dev_log(mtc->dev);
1.1 ratchov 1537: log_puts(": relocated to ");
1538: log_putu(origin);
1539: log_puts("\n");
1540: }
1.94 ratchov 1541: if (mtc->tstate == MTC_RUN)
1542: mtc_stop(mtc);
1543: mtc->origin = origin;
1544: if (mtc->tstate == MTC_RUN)
1545: mtc_start(mtc);
1.1 ratchov 1546: }
1547:
1.35 ratchov 1548: /*
1549: * allocate buffers & conversion chain
1550: */
1551: void
1.60 ratchov 1552: slot_initconv(struct slot *s)
1.35 ratchov 1553: {
1.63 ratchov 1554: unsigned int dev_nch;
1.89 ratchov 1555: struct dev *d = s->opt->dev;
1.35 ratchov 1556:
1557: if (s->mode & MODE_PLAY) {
1558: cmap_init(&s->mix.cmap,
1.42 ratchov 1559: s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1560: s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1.35 ratchov 1561: 0, d->pchan - 1,
1.40 ratchov 1562: s->opt->pmin, s->opt->pmax);
1.35 ratchov 1563: if (!aparams_native(&s->par)) {
1.42 ratchov 1564: dec_init(&s->mix.dec, &s->par, s->mix.nch);
1.35 ratchov 1565: }
1566: if (s->rate != d->rate) {
1567: resamp_init(&s->mix.resamp, s->round, d->round,
1.42 ratchov 1568: s->mix.nch);
1.35 ratchov 1569: }
1.61 ratchov 1570: s->mix.join = 1;
1571: s->mix.expand = 1;
1.63 ratchov 1572: if (s->opt->dup && s->mix.cmap.nch > 0) {
1573: dev_nch = d->pchan < (s->opt->pmax + 1) ?
1574: d->pchan - s->opt->pmin :
1575: s->opt->pmax - s->opt->pmin + 1;
1576: if (dev_nch > s->mix.nch)
1577: s->mix.expand = dev_nch / s->mix.nch;
1578: else if (s->mix.nch > dev_nch)
1579: s->mix.join = s->mix.nch / dev_nch;
1.61 ratchov 1580: }
1.35 ratchov 1581: }
1582:
1583: if (s->mode & MODE_RECMASK) {
1.63 ratchov 1584: unsigned int outchan = (s->mode & MODE_MON) ?
1585: d->pchan : d->rchan;
1586:
1.35 ratchov 1587: cmap_init(&s->sub.cmap,
1.63 ratchov 1588: 0, outchan - 1,
1.40 ratchov 1589: s->opt->rmin, s->opt->rmax,
1.42 ratchov 1590: s->opt->rmin, s->opt->rmin + s->sub.nch - 1,
1591: s->opt->rmin, s->opt->rmin + s->sub.nch - 1);
1.35 ratchov 1592: if (s->rate != d->rate) {
1593: resamp_init(&s->sub.resamp, d->round, s->round,
1.42 ratchov 1594: s->sub.nch);
1.35 ratchov 1595: }
1596: if (!aparams_native(&s->par)) {
1.42 ratchov 1597: enc_init(&s->sub.enc, &s->par, s->sub.nch);
1.61 ratchov 1598: }
1599: s->sub.join = 1;
1600: s->sub.expand = 1;
1.63 ratchov 1601: if (s->opt->dup && s->sub.cmap.nch > 0) {
1602: dev_nch = outchan < (s->opt->rmax + 1) ?
1603: outchan - s->opt->rmin :
1604: s->opt->rmax - s->opt->rmin + 1;
1605: if (dev_nch > s->sub.nch)
1606: s->sub.join = dev_nch / s->sub.nch;
1607: else if (s->sub.nch > dev_nch)
1608: s->sub.expand = s->sub.nch / dev_nch;
1.35 ratchov 1609: }
1610:
1611: /*
1612: * cmap_copy() doesn't write samples in all channels,
1613: * for instance when mono->stereo conversion is
1614: * disabled. So we have to prefill cmap_copy() output
1615: * with silence.
1616: */
1617: if (s->sub.resampbuf) {
1618: memset(s->sub.resampbuf, 0,
1.42 ratchov 1619: d->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1620: } else if (s->sub.encbuf) {
1621: memset(s->sub.encbuf, 0,
1.42 ratchov 1622: s->round * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1623: } else {
1624: memset(s->sub.buf.data, 0,
1.42 ratchov 1625: s->appbufsz * s->sub.nch * sizeof(adata_t));
1.35 ratchov 1626: }
1627: }
1.60 ratchov 1628: }
1629:
1630: /*
1631: * allocate buffers & conversion chain
1632: */
1633: void
1634: slot_allocbufs(struct slot *s)
1635: {
1.89 ratchov 1636: struct dev *d = s->opt->dev;
1.60 ratchov 1637:
1638: if (s->mode & MODE_PLAY) {
1639: s->mix.bpf = s->par.bps * s->mix.nch;
1640: abuf_init(&s->mix.buf, s->appbufsz * s->mix.bpf);
1641:
1642: s->mix.decbuf = NULL;
1643: s->mix.resampbuf = NULL;
1644: if (!aparams_native(&s->par)) {
1645: s->mix.decbuf =
1646: xmalloc(s->round * s->mix.nch * sizeof(adata_t));
1647: }
1648: if (s->rate != d->rate) {
1649: s->mix.resampbuf =
1650: xmalloc(d->round * s->mix.nch * sizeof(adata_t));
1651: }
1652: }
1653:
1654: if (s->mode & MODE_RECMASK) {
1655: s->sub.bpf = s->par.bps * s->sub.nch;
1656: abuf_init(&s->sub.buf, s->appbufsz * s->sub.bpf);
1657:
1658: s->sub.encbuf = NULL;
1659: s->sub.resampbuf = NULL;
1660: if (s->rate != d->rate) {
1661: s->sub.resampbuf =
1662: xmalloc(d->round * s->sub.nch * sizeof(adata_t));
1663: }
1664: if (!aparams_native(&s->par)) {
1665: s->sub.encbuf =
1666: xmalloc(s->round * s->sub.nch * sizeof(adata_t));
1667: }
1668: }
1669:
1670: slot_initconv(s);
1.35 ratchov 1671:
1672: #ifdef DEBUG
1673: if (log_level >= 3) {
1674: slot_log(s);
1675: log_puts(": allocated ");
1676: log_putu(s->appbufsz);
1677: log_puts("/");
1678: log_putu(SLOT_BUFSZ(s));
1679: log_puts(" fr buffers\n");
1680: }
1681: #endif
1682: }
1683:
1684: /*
1685: * free buffers & conversion chain
1686: */
1687: void
1688: slot_freebufs(struct slot *s)
1689: {
1690: if (s->mode & MODE_RECMASK) {
1691: abuf_done(&s->sub.buf);
1692: if (s->sub.encbuf)
1693: xfree(s->sub.encbuf);
1694: if (s->sub.resampbuf)
1695: xfree(s->sub.resampbuf);
1696: }
1697:
1698: if (s->mode & MODE_PLAY) {
1699: abuf_done(&s->mix.buf);
1700: if (s->mix.decbuf)
1701: xfree(s->mix.decbuf);
1702: if (s->mix.resampbuf)
1703: xfree(s->mix.resampbuf);
1704: }
1705: }
1706:
1.1 ratchov 1707: /*
1708: * allocate a new slot and register the given call-backs
1709: */
1710: struct slot *
1.89 ratchov 1711: slot_new(struct opt *opt, unsigned int id, char *who,
1.37 ratchov 1712: struct slotops *ops, void *arg, int mode)
1.1 ratchov 1713: {
1714: char *p;
1715: char name[SLOT_NAMEMAX];
1.52 ratchov 1716: unsigned int i, ser, bestser, bestidx;
1717: struct slot *unit[DEV_NSLOT];
1.1 ratchov 1718: struct slot *s;
1719:
1720: /*
1.27 ratchov 1721: * create a ``valid'' control name (lowcase, remove [^a-z], truncate)
1.1 ratchov 1722: */
1723: for (i = 0, p = who; ; p++) {
1724: if (i == SLOT_NAMEMAX - 1 || *p == '\0') {
1725: name[i] = '\0';
1726: break;
1727: } else if (*p >= 'A' && *p <= 'Z') {
1728: name[i++] = *p + 'a' - 'A';
1729: } else if (*p >= 'a' && *p <= 'z')
1730: name[i++] = *p;
1731: }
1732: if (i == 0)
1733: strlcpy(name, "noname", SLOT_NAMEMAX);
1734:
1735: /*
1.52 ratchov 1736: * build a unit-to-slot map for this name
1.1 ratchov 1737: */
1.52 ratchov 1738: for (i = 0; i < DEV_NSLOT; i++)
1739: unit[i] = NULL;
1.84 ratchov 1740: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.1 ratchov 1741: if (strcmp(s->name, name) == 0)
1.52 ratchov 1742: unit[s->unit] = s;
1.1 ratchov 1743: }
1744:
1745: /*
1.54 ratchov 1746: * find the free slot with the least unit number and same id
1747: */
1748: for (i = 0; i < DEV_NSLOT; i++) {
1749: s = unit[i];
1750: if (s != NULL && s->ops == NULL && s->id == id)
1751: goto found;
1752: }
1753:
1754: /*
1.52 ratchov 1755: * find the free slot with the least unit number
1.1 ratchov 1756: */
1.52 ratchov 1757: for (i = 0; i < DEV_NSLOT; i++) {
1758: s = unit[i];
1.54 ratchov 1759: if (s != NULL && s->ops == NULL) {
1760: s->id = id;
1.1 ratchov 1761: goto found;
1.54 ratchov 1762: }
1.1 ratchov 1763: }
1764:
1765: /*
1.18 ratchov 1766: * couldn't find a matching slot, pick oldest free slot
1.1 ratchov 1767: * and set its name/unit
1768: */
1769: bestser = 0;
1770: bestidx = DEV_NSLOT;
1.84 ratchov 1771: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.1 ratchov 1772: if (s->ops != NULL)
1773: continue;
1.84 ratchov 1774: ser = slot_serial - s->serial;
1.1 ratchov 1775: if (ser > bestser) {
1776: bestser = ser;
1777: bestidx = i;
1778: }
1779: }
1.98 ! ratchov 1780:
! 1781: if (bestidx == DEV_NSLOT) {
! 1782: if (log_level >= 1) {
! 1783: log_puts(name);
! 1784: log_puts(": out of sub-device slots\n");
! 1785: }
! 1786: return NULL;
1.1 ratchov 1787: }
1.53 ratchov 1788:
1.98 ! ratchov 1789: s = slot_array + bestidx;
! 1790: s->vol = MIDI_MAXCTL;
! 1791: strlcpy(s->name, name, SLOT_NAMEMAX);
! 1792: s->serial = slot_serial++;
! 1793: for (i = 0; unit[i] != NULL; i++)
! 1794: ; /* nothing */
! 1795: s->unit = i;
! 1796: s->id = id;
1.1 ratchov 1797:
1798: found:
1.37 ratchov 1799: if ((mode & MODE_REC) && (opt->mode & MODE_MON)) {
1800: mode |= MODE_MON;
1801: mode &= ~MODE_REC;
1802: }
1803: if ((mode & opt->mode) != mode) {
1804: if (log_level >= 1) {
1805: slot_log(s);
1806: log_puts(": requested mode not allowed\n");
1807: }
1.89 ratchov 1808: return NULL;
1.37 ratchov 1809: }
1.89 ratchov 1810: if (!dev_ref(opt->dev))
1.1 ratchov 1811: return NULL;
1.89 ratchov 1812: if ((mode & opt->dev->mode) != mode) {
1.1 ratchov 1813: if (log_level >= 1) {
1814: slot_log(s);
1815: log_puts(": requested mode not supported\n");
1816: }
1817: }
1.37 ratchov 1818: s->opt = opt;
1.31 ratchov 1819: s->ops = ops;
1820: s->arg = arg;
1821: s->pstate = SLOT_INIT;
1.1 ratchov 1822: s->mode = mode;
1.6 ratchov 1823: aparams_init(&s->par);
1.41 ratchov 1824: if (s->mode & MODE_PLAY)
1.42 ratchov 1825: s->mix.nch = s->opt->pmax - s->opt->pmin + 1;
1.41 ratchov 1826: if (s->mode & MODE_RECMASK)
1.42 ratchov 1827: s->sub.nch = s->opt->rmax - s->opt->rmin + 1;
1.94 ratchov 1828: s->xrun = s->opt->mtc != NULL ? XRUN_SYNC : XRUN_IGNORE;
1.89 ratchov 1829: s->appbufsz = s->opt->dev->bufsz;
1830: s->round = s->opt->dev->round;
1831: s->rate = s->opt->dev->rate;
1832: dev_label(s->opt->dev, s - slot_array);
1833: dev_midi_slotdesc(s->opt->dev, s);
1834: dev_midi_vol(s->opt->dev, s);
1.43 ratchov 1835: #ifdef DEBUG
1836: if (log_level >= 3) {
1837: slot_log(s);
1838: log_puts(": using ");
1.89 ratchov 1839: dev_log(s->opt->dev);
1.43 ratchov 1840: log_puts(".");
1.89 ratchov 1841: log_puts(s->opt->name);
1.43 ratchov 1842: log_puts(", mode = ");
1843: log_putx(mode);
1844: log_puts("\n");
1845: }
1846: #endif
1.1 ratchov 1847: return s;
1848: }
1849:
1850: /*
1851: * release the given slot
1852: */
1853: void
1854: slot_del(struct slot *s)
1855: {
1856: s->arg = s;
1857: s->ops = &zomb_slotops;
1858: switch (s->pstate) {
1859: case SLOT_INIT:
1860: s->ops = NULL;
1861: break;
1862: case SLOT_START:
1863: case SLOT_READY:
1864: case SLOT_RUN:
1865: case SLOT_STOP:
1.82 ratchov 1866: slot_stop(s, 0);
1.1 ratchov 1867: break;
1868: }
1.89 ratchov 1869: dev_unref(s->opt->dev);
1.1 ratchov 1870: }
1871:
1872: /*
1873: * change the slot play volume; called either by the slot or by MIDI
1874: */
1875: void
1876: slot_setvol(struct slot *s, unsigned int vol)
1877: {
1878: #ifdef DEBUG
1879: if (log_level >= 3) {
1880: slot_log(s);
1881: log_puts(": setting volume ");
1882: log_putu(vol);
1883: log_puts("\n");
1884: }
1885: #endif
1886: s->vol = vol;
1887: s->mix.vol = MIDI_TO_ADATA(s->vol);
1888: }
1889:
1890: /*
1891: * attach the slot to the device (ie start playing & recording
1892: */
1893: void
1894: slot_attach(struct slot *s)
1895: {
1.89 ratchov 1896: struct dev *d = s->opt->dev;
1.12 ratchov 1897: long long pos;
1.1 ratchov 1898:
1899: /*
1900: * start the device if not started
1901: */
1902: dev_wakeup(d);
1.23 ratchov 1903:
1.1 ratchov 1904: /*
1.12 ratchov 1905: * adjust initial clock
1906: */
1.79 ratchov 1907: pos = s->delta_rem +
1908: (long long)s->delta * d->round +
1909: (long long)d->delta * s->round;
1910: s->delta = pos / (int)d->round;
1.12 ratchov 1911: s->delta_rem = pos % d->round;
1.79 ratchov 1912: if (s->delta_rem < 0) {
1913: s->delta_rem += d->round;
1914: s->delta--;
1915: }
1.12 ratchov 1916:
1.1 ratchov 1917: #ifdef DEBUG
1.17 ratchov 1918: if (log_level >= 2) {
1.1 ratchov 1919: slot_log(s);
1920: log_puts(": attached at ");
1.79 ratchov 1921: log_puti(s->delta);
1922: log_puts(" + ");
1923: log_puti(s->delta_rem);
1924: log_puts("/");
1925: log_puti(s->round);
1.1 ratchov 1926: log_puts("\n");
1927: }
1928: #endif
1929:
1930: /*
1931: * We dont check whether the device is dying,
1932: * because dev_xxx() functions are supposed to
1933: * work (i.e., not to crash)
1934: */
1.91 edd 1935:
1.1 ratchov 1936: s->next = d->slot_list;
1937: d->slot_list = s;
1938: if (s->mode & MODE_PLAY) {
1939: s->mix.vol = MIDI_TO_ADATA(s->vol);
1940: dev_mix_adjvol(d);
1941: }
1942: }
1943:
1944: /*
1945: * if MMC is enabled, and try to attach all slots synchronously, else
1946: * simply attach the slot
1947: */
1948: void
1949: slot_ready(struct slot *s)
1950: {
1.3 ratchov 1951: /*
1952: * device may be disconnected, and if so we're called from
1953: * slot->ops->exit() on a closed device
1.23 ratchov 1954: */
1.89 ratchov 1955: if (s->opt->dev->pstate == DEV_CFG)
1.3 ratchov 1956: return;
1.94 ratchov 1957: if (s->opt->mtc == NULL) {
1.1 ratchov 1958: slot_attach(s);
1.79 ratchov 1959: s->pstate = SLOT_RUN;
1960: } else
1.94 ratchov 1961: mtc_trigger(s->opt->mtc);
1.1 ratchov 1962: }
1963:
1964: /*
1965: * setup buffers & conversion layers, prepare the slot to receive data
1966: * (for playback) or start (recording).
1967: */
1968: void
1969: slot_start(struct slot *s)
1970: {
1.89 ratchov 1971: struct dev *d = s->opt->dev;
1.1 ratchov 1972: #ifdef DEBUG
1973: if (s->pstate != SLOT_INIT) {
1974: slot_log(s);
1975: log_puts(": slot_start: wrong state\n");
1976: panic();
1977: }
1978: if (s->mode & MODE_PLAY) {
1979: if (log_level >= 3) {
1980: slot_log(s);
1981: log_puts(": playing ");
1982: aparams_log(&s->par);
1983: log_puts(" -> ");
1.81 ratchov 1984: aparams_log(&d->par);
1.1 ratchov 1985: log_puts("\n");
1986: }
1987: }
1988: if (s->mode & MODE_RECMASK) {
1989: if (log_level >= 3) {
1990: slot_log(s);
1991: log_puts(": recording ");
1992: aparams_log(&s->par);
1993: log_puts(" <- ");
1.81 ratchov 1994: aparams_log(&d->par);
1.1 ratchov 1995: log_puts("\n");
1.35 ratchov 1996: }
1.1 ratchov 1997: }
1998: #endif
1.35 ratchov 1999: slot_allocbufs(s);
1.47 ratchov 2000:
2001: if (s->mode & MODE_RECMASK) {
2002: /*
2003: * N-th recorded block is the N-th played block
2004: */
1.81 ratchov 2005: s->sub.prime = -dev_getpos(d) / d->round;
1.47 ratchov 2006: }
2007: s->skip = 0;
2008:
1.79 ratchov 2009: /*
2010: * get the current position, the origin is when the first sample
2011: * played and/or recorded
2012: */
1.81 ratchov 2013: s->delta = dev_getpos(d) * (int)s->round / (int)d->round;
1.79 ratchov 2014: s->delta_rem = 0;
2015:
1.1 ratchov 2016: if (s->mode & MODE_PLAY) {
2017: s->pstate = SLOT_START;
2018: } else {
2019: s->pstate = SLOT_READY;
2020: slot_ready(s);
2021: }
2022: }
2023:
2024: /*
2025: * stop playback and recording, and free conversion layers
2026: */
2027: void
2028: slot_detach(struct slot *s)
2029: {
2030: struct slot **ps;
1.89 ratchov 2031: struct dev *d = s->opt->dev;
1.79 ratchov 2032: long long pos;
1.1 ratchov 2033:
1.81 ratchov 2034: for (ps = &d->slot_list; *ps != s; ps = &(*ps)->next) {
1.1 ratchov 2035: #ifdef DEBUG
1.28 ratchov 2036: if (*ps == NULL) {
1.1 ratchov 2037: slot_log(s);
2038: log_puts(": can't detach, not on list\n");
2039: panic();
2040: }
2041: #endif
1.23 ratchov 2042: }
1.1 ratchov 2043: *ps = s->next;
1.79 ratchov 2044:
2045: /*
2046: * adjust clock, go back d->delta ticks so that slot_attach()
2047: * could be called with the resulting state
2048: */
2049: pos = s->delta_rem +
2050: (long long)s->delta * d->round -
2051: (long long)d->delta * s->round;
2052: s->delta = pos / (int)d->round;
2053: s->delta_rem = pos % d->round;
2054: if (s->delta_rem < 0) {
2055: s->delta_rem += d->round;
2056: s->delta--;
2057: }
2058:
2059: #ifdef DEBUG
2060: if (log_level >= 2) {
2061: slot_log(s);
2062: log_puts(": detached at ");
2063: log_puti(s->delta);
2064: log_puts(" + ");
2065: log_puti(s->delta_rem);
2066: log_puts("/");
2067: log_puti(d->round);
2068: log_puts("\n");
2069: }
2070: #endif
1.35 ratchov 2071: if (s->mode & MODE_PLAY)
1.81 ratchov 2072: dev_mix_adjvol(d);
1.1 ratchov 2073: }
2074:
2075: /*
2076: * put the slot in stopping state (draining play buffers) or
2077: * stop & detach if no data to drain.
2078: */
2079: void
1.82 ratchov 2080: slot_stop(struct slot *s, int drain)
1.1 ratchov 2081: {
2082: #ifdef DEBUG
2083: if (log_level >= 3) {
2084: slot_log(s);
2085: log_puts(": stopping\n");
2086: }
2087: #endif
2088: if (s->pstate == SLOT_START) {
1.33 ratchov 2089: /*
2090: * If in rec-only mode, we're already in the READY or
2091: * RUN states. We're here because the play buffer was
2092: * not full enough, try to start so it's drained.
2093: */
2094: s->pstate = SLOT_READY;
2095: slot_ready(s);
1.1 ratchov 2096: }
1.34 ratchov 2097:
2098: if (s->pstate == SLOT_RUN) {
1.82 ratchov 2099: if ((s->mode & MODE_PLAY) && drain) {
1.34 ratchov 2100: /*
2101: * Don't detach, dev_cycle() will do it for us
2102: * when the buffer is drained.
2103: */
2104: s->pstate = SLOT_STOP;
2105: return;
2106: }
1.82 ratchov 2107: slot_detach(s);
2108: } else if (s->pstate == SLOT_STOP) {
1.34 ratchov 2109: slot_detach(s);
2110: } else {
1.1 ratchov 2111: #ifdef DEBUG
2112: if (log_level >= 3) {
2113: slot_log(s);
2114: log_puts(": not drained (blocked by mmc)\n");
2115: }
2116: #endif
2117: }
1.35 ratchov 2118:
1.34 ratchov 2119: s->pstate = SLOT_INIT;
2120: s->ops->eof(s->arg);
1.35 ratchov 2121: slot_freebufs(s);
1.1 ratchov 2122: }
2123:
1.12 ratchov 2124: void
2125: slot_skip_update(struct slot *s)
2126: {
2127: int skip;
2128:
2129: skip = slot_skip(s);
2130: while (skip > 0) {
2131: #ifdef DEBUG
2132: if (log_level >= 4) {
2133: slot_log(s);
2134: log_puts(": catching skipped block\n");
2135: }
2136: #endif
2137: if (s->mode & MODE_RECMASK)
2138: s->ops->flush(s->arg);
2139: if (s->mode & MODE_PLAY)
2140: s->ops->fill(s->arg);
2141: skip--;
2142: }
2143: }
2144:
1.1 ratchov 2145: /*
2146: * notify the slot that we just wrote in the play buffer, must be called
2147: * after each write
2148: */
2149: void
2150: slot_write(struct slot *s)
2151: {
2152: if (s->pstate == SLOT_START && s->mix.buf.used == s->mix.buf.len) {
2153: #ifdef DEBUG
2154: if (log_level >= 4) {
2155: slot_log(s);
2156: log_puts(": switching to READY state\n");
2157: }
2158: #endif
2159: s->pstate = SLOT_READY;
2160: slot_ready(s);
2161: }
1.12 ratchov 2162: slot_skip_update(s);
1.1 ratchov 2163: }
2164:
2165: /*
2166: * notify the slot that we freed some space in the rec buffer
2167: */
2168: void
2169: slot_read(struct slot *s)
2170: {
1.12 ratchov 2171: slot_skip_update(s);
1.64 ratchov 2172: }
2173:
2174: /*
2175: * allocate at control slot
2176: */
2177: struct ctlslot *
1.88 ratchov 2178: ctlslot_new(struct opt *o, struct ctlops *ops, void *arg)
1.64 ratchov 2179: {
2180: struct ctlslot *s;
2181: struct ctl *c;
2182: int i;
2183:
2184: i = 0;
2185: for (;;) {
2186: if (i == DEV_NCTLSLOT)
2187: return NULL;
1.85 ratchov 2188: s = ctlslot_array + i;
1.64 ratchov 2189: if (s->ops == NULL)
2190: break;
2191: i++;
2192: }
1.88 ratchov 2193: s->opt = o;
1.87 ratchov 2194: s->self = 1 << i;
1.88 ratchov 2195: if (!dev_ref(o->dev))
1.64 ratchov 2196: return NULL;
2197: s->ops = ops;
2198: s->arg = arg;
1.92 ratchov 2199: for (c = ctl_list; c != NULL; c = c->next) {
2200: if (!ctlslot_visible(s, c))
2201: continue;
1.87 ratchov 2202: c->refs_mask |= s->self;
1.92 ratchov 2203: }
1.64 ratchov 2204: return s;
2205: }
2206:
2207: /*
2208: * free control slot
2209: */
2210: void
2211: ctlslot_del(struct ctlslot *s)
2212: {
2213: struct ctl *c, **pc;
2214:
1.92 ratchov 2215: pc = &ctl_list;
1.64 ratchov 2216: while ((c = *pc) != NULL) {
1.87 ratchov 2217: c->refs_mask &= ~s->self;
1.64 ratchov 2218: if (c->refs_mask == 0) {
2219: *pc = c->next;
2220: xfree(c);
2221: } else
2222: pc = &c->next;
2223: }
2224: s->ops = NULL;
1.88 ratchov 2225: dev_unref(s->opt->dev);
1.64 ratchov 2226: }
2227:
1.92 ratchov 2228: int
2229: ctlslot_visible(struct ctlslot *s, struct ctl *c)
2230: {
2231: if (s->opt == NULL)
2232: return 1;
2233: switch (c->scope) {
2234: case CTL_HW:
2235: case CTL_DEV_MASTER:
2236: case CTL_DEV_ALT:
2237: return (s->opt->dev == c->u.any.arg0);
2238: case CTL_SLOT_LEVEL:
2239: return (s->opt->dev == c->u.slot_level.slot->opt->dev);
2240: default:
2241: return 0;
2242: }
2243: }
2244:
2245: struct ctl *
2246: ctlslot_lookup(struct ctlslot *s, int addr)
2247: {
2248: struct ctl *c;
2249:
2250: c = ctl_list;
2251: while (1) {
2252: if (c == NULL)
2253: return NULL;
2254: if (c->type != CTL_NONE && c->addr == addr)
2255: break;
2256: c = c->next;
2257: }
2258: if (!ctlslot_visible(s, c))
2259: return NULL;
2260: return c;
2261: }
2262:
1.64 ratchov 2263: void
2264: ctl_node_log(struct ctl_node *c)
2265: {
2266: log_puts(c->name);
2267: if (c->unit >= 0)
2268: log_putu(c->unit);
2269: }
2270:
2271: void
2272: ctl_log(struct ctl *c)
2273: {
2274: if (c->group[0] != 0) {
2275: log_puts(c->group);
2276: log_puts("/");
2277: }
2278: ctl_node_log(&c->node0);
2279: log_puts(".");
2280: log_puts(c->func);
2281: log_puts("=");
2282: switch (c->type) {
1.67 ratchov 2283: case CTL_NONE:
2284: log_puts("none");
2285: break;
1.64 ratchov 2286: case CTL_NUM:
2287: case CTL_SW:
2288: log_putu(c->curval);
2289: break;
2290: case CTL_VEC:
2291: case CTL_LIST:
1.74 ratchov 2292: case CTL_SEL:
1.64 ratchov 2293: ctl_node_log(&c->node1);
2294: log_puts(":");
2295: log_putu(c->curval);
2296: }
2297: log_puts(" at ");
2298: log_putu(c->addr);
1.92 ratchov 2299: log_puts(" -> ");
2300: switch (c->scope) {
2301: case CTL_HW:
2302: log_puts("hw:");
2303: log_puts(c->u.hw.dev->name);
2304: log_puts("/");
2305: log_putu(c->u.hw.addr);
2306: break;
2307: case CTL_DEV_MASTER:
2308: log_puts("dev_master:");
2309: log_puts(c->u.dev_master.dev->name);
2310: break;
2311: case CTL_DEV_ALT:
2312: log_puts("dev_alt:");
2313: log_puts(c->u.dev_alt.dev->name);
2314: log_putu(c->u.dev_alt.idx);
2315: break;
2316: case CTL_SLOT_LEVEL:
2317: log_puts("slot_level:");
2318: log_puts(c->u.slot_level.slot->name);
2319: log_putu(c->u.slot_level.slot->unit);
2320: break;
2321: default:
2322: log_puts("unknown");
2323: }
2324: }
2325:
2326: int
2327: ctl_setval(struct ctl *c, int val)
2328: {
2329: if (c->curval == val) {
2330: if (log_level >= 3) {
2331: ctl_log(c);
2332: log_puts(": already set\n");
2333: }
2334: return 1;
2335: }
2336: if (val < 0 || val > c->maxval) {
2337: if (log_level >= 3) {
2338: log_putu(val);
2339: log_puts(": ctl val out of bounds\n");
2340: }
2341: return 0;
2342: }
2343:
2344: switch (c->scope) {
2345: case CTL_HW:
2346: if (log_level >= 3) {
2347: ctl_log(c);
2348: log_puts(": marked as dirty\n");
2349: }
2350: c->curval = val;
2351: c->dirty = 1;
2352: return dev_ref(c->u.hw.dev);
2353: case CTL_DEV_MASTER:
2354: if (!c->u.dev_master.dev->master_enabled)
2355: return 1;
2356: dev_master(c->u.dev_master.dev, val);
2357: dev_midi_master(c->u.dev_master.dev);
2358: c->val_mask = ~0U;
2359: c->curval = val;
2360: return 1;
2361: case CTL_DEV_ALT:
2362: dev_setalt (c->u.dev_alt.dev, c->u.dev_alt.idx);
2363: return 1;
2364: case CTL_SLOT_LEVEL:
2365: slot_setvol(c->u.slot_level.slot, val);
2366: // XXX change dev_midi_vol() into slot_midi_vol()
2367: dev_midi_vol(c->u.slot_level.slot->opt->dev, c->u.slot_level.slot);
2368: c->val_mask = ~0U;
2369: c->curval = val;
2370: return 1;
2371: default:
2372: if (log_level >= 2) {
2373: ctl_log(c);
2374: log_puts(": not writable\n");
2375: }
2376: return 1;
2377: }
1.64 ratchov 2378: }
2379:
2380: /*
2381: * add a ctl
2382: */
2383: struct ctl *
1.92 ratchov 2384: ctl_new(int scope, void *arg0, void *arg1,
2385: int type, char *gstr,
2386: char *str0, int unit0, char *func,
2387: char *str1, int unit1, int maxval, int val)
1.64 ratchov 2388: {
2389: struct ctl *c, **pc;
1.92 ratchov 2390: struct ctlslot *s;
2391: int addr;
1.64 ratchov 2392: int i;
2393:
1.92 ratchov 2394: /*
2395: * find the smallest unused addr number and
2396: * the last position in the list
2397: */
2398: addr = 0;
2399: for (pc = &ctl_list; (c = *pc) != NULL; pc = &c->next) {
2400: if (c->addr > addr)
2401: addr = c->addr;
2402: }
2403: addr++;
2404:
1.64 ratchov 2405: c = xmalloc(sizeof(struct ctl));
2406: c->type = type;
2407: strlcpy(c->func, func, CTL_NAMEMAX);
2408: strlcpy(c->group, gstr, CTL_NAMEMAX);
2409: strlcpy(c->node0.name, str0, CTL_NAMEMAX);
2410: c->node0.unit = unit0;
1.74 ratchov 2411: if (c->type == CTL_VEC || c->type == CTL_LIST || c->type == CTL_SEL) {
1.64 ratchov 2412: strlcpy(c->node1.name, str1, CTL_NAMEMAX);
2413: c->node1.unit = unit1;
2414: } else
2415: memset(&c->node1, 0, sizeof(struct ctl_node));
1.92 ratchov 2416: c->scope = scope;
2417: c->u.any.arg0 = arg0;
2418: switch (scope) {
2419: case CTL_HW:
2420: c->u.hw.addr = *(unsigned int *)arg1;
2421: break;
2422: case CTL_DEV_ALT:
2423: c->u.dev_alt.idx = *(unsigned int *)arg1;
2424: break;
2425: default:
2426: c->u.any.arg1 = NULL;
2427: }
1.64 ratchov 2428: c->addr = addr;
2429: c->maxval = maxval;
2430: c->val_mask = ~0;
2431: c->desc_mask = ~0;
2432: c->curval = val;
2433: c->dirty = 0;
1.92 ratchov 2434: c->refs_mask = CTL_DEVMASK;
2435: for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) {
2436: if (s->ops == NULL)
2437: continue;
2438: if (ctlslot_visible(s, c))
1.64 ratchov 2439: c->refs_mask |= 1 << i;
2440: }
1.92 ratchov 2441: c->next = *pc;
1.64 ratchov 2442: *pc = c;
2443: #ifdef DEBUG
1.92 ratchov 2444: if (log_level >= 2) {
1.64 ratchov 2445: ctl_log(c);
1.92 ratchov 2446: log_puts(": added\n");
1.64 ratchov 2447: }
2448: #endif
2449: return c;
2450: }
2451:
2452: void
1.92 ratchov 2453: ctl_update(struct ctl *c)
2454: {
2455: struct ctlslot *s;
2456: unsigned int refs_mask;
2457: int i;
2458:
2459: for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) {
2460: if (s->ops == NULL)
2461: continue;
2462: refs_mask = ctlslot_visible(s, c) ? s->self : 0;
2463:
2464: /* nothing to do if no visibility change */
2465: if (((c->refs_mask & s->self) ^ refs_mask) == 0)
2466: continue;
2467: /* if control becomes visble */
2468: if (refs_mask)
2469: c->refs_mask |= s->self;
2470: /* if control is hidden */
2471: c->desc_mask |= s->self;
2472: }
2473: }
2474:
2475: int
2476: ctl_match(struct ctl *c, int scope, void *arg0, void *arg1)
2477: {
2478: if (c->type == CTL_NONE || c->scope != scope || c->u.any.arg0 != arg0)
2479: return 0;
2480: if (arg0 != NULL && c->u.any.arg0 != arg0)
2481: return 0;
2482: switch (scope) {
2483: case CTL_HW:
2484: if (arg1 != NULL && c->u.hw.addr != *(unsigned int *)arg1)
2485: return 0;
2486: break;
2487: case CTL_DEV_ALT:
2488: if (arg1 != NULL && c->u.dev_alt.idx != *(unsigned int *)arg1)
2489: return 0;
2490: break;
2491: }
2492: return 1;
2493: }
2494:
2495: struct ctl *
2496: ctl_find(int scope, void *arg0, void *arg1)
2497: {
2498: struct ctl *c;
2499:
2500: for (c = ctl_list; c != NULL; c = c->next) {
2501: if (ctl_match(c, scope, arg0, arg1))
2502: return c;
2503: }
2504: return NULL;
2505: }
2506:
2507: int
2508: ctl_onval(int scope, void *arg0, void *arg1, int val)
2509: {
2510: struct ctl *c;
2511:
2512: c = ctl_find(scope, arg0, arg1);
2513: if (c == NULL)
2514: return 0;
2515: c->curval = val;
2516: c->val_mask = ~0U;
2517: return 1;
2518: }
2519:
2520: void
2521: ctl_del(int scope, void *arg0, void *arg1)
1.64 ratchov 2522: {
2523: struct ctl *c, **pc;
2524:
1.92 ratchov 2525: pc = &ctl_list;
1.64 ratchov 2526: for (;;) {
2527: c = *pc;
2528: if (c == NULL)
2529: return;
1.92 ratchov 2530: if (ctl_match(c, scope, arg0, arg1)) {
1.64 ratchov 2531: #ifdef DEBUG
1.92 ratchov 2532: if (log_level >= 2) {
2533: ctl_log(c);
2534: log_puts(": removed\n");
2535: }
1.64 ratchov 2536: #endif
1.92 ratchov 2537: c->refs_mask &= ~CTL_DEVMASK;
2538: if (c->refs_mask == 0) {
2539: *pc = c->next;
2540: xfree(c);
2541: continue;
2542: }
2543: c->type = CTL_NONE;
2544: c->desc_mask = ~0;
2545: }
2546: pc = &c->next;
1.68 ratchov 2547: }
1.65 ratchov 2548: }
2549:
2550: void
2551: dev_ctlsync(struct dev *d)
2552: {
1.70 ratchov 2553: struct ctl *c;
1.65 ratchov 2554: struct ctlslot *s;
1.70 ratchov 2555: int found, i;
2556:
2557: found = 0;
1.92 ratchov 2558: for (c = ctl_list; c != NULL; c = c->next) {
2559: if (c->scope == CTL_HW &&
2560: c->u.hw.dev == d &&
1.70 ratchov 2561: c->type == CTL_NUM &&
1.92 ratchov 2562: strcmp(c->group, d->name) == 0 &&
1.70 ratchov 2563: strcmp(c->node0.name, "output") == 0 &&
2564: strcmp(c->func, "level") == 0)
2565: found = 1;
2566: }
2567:
2568: if (d->master_enabled && found) {
2569: if (log_level >= 2) {
2570: dev_log(d);
2571: log_puts(": software master level control disabled\n");
2572: }
2573: d->master_enabled = 0;
1.92 ratchov 2574: ctl_del(CTL_DEV_MASTER, d, NULL);
1.70 ratchov 2575: } else if (!d->master_enabled && !found) {
2576: if (log_level >= 2) {
2577: dev_log(d);
2578: log_puts(": software master level control enabled\n");
2579: }
2580: d->master_enabled = 1;
1.92 ratchov 2581: ctl_new(CTL_DEV_MASTER, d, NULL,
2582: CTL_NUM, d->name, "output", -1, "level",
2583: NULL, -1, 127, d->master);
1.70 ratchov 2584: }
1.65 ratchov 2585:
1.95 ratchov 2586: for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) {
2587: if (s->ops == NULL)
2588: continue;
2589: if (s->opt->dev == d)
1.65 ratchov 2590: s->ops->sync(s->arg);
2591: }
1.64 ratchov 2592: }
2593:
2594: void
2595: dev_label(struct dev *d, int i)
2596: {
2597: struct ctl *c;
2598: char name[CTL_NAMEMAX];
2599:
1.84 ratchov 2600: slot_ctlname(&slot_array[i], name, CTL_NAMEMAX);
1.69 ratchov 2601:
1.92 ratchov 2602: c = ctl_list;
1.64 ratchov 2603: for (;;) {
1.69 ratchov 2604: if (c == NULL) {
1.92 ratchov 2605: ctl_new(CTL_SLOT_LEVEL, slot_array + i, NULL,
2606: CTL_NUM, "app", name, -1, "level",
1.84 ratchov 2607: NULL, -1, 127, slot_array[i].vol);
1.64 ratchov 2608: return;
1.69 ratchov 2609: }
1.92 ratchov 2610: if (ctl_match(c, CTL_SLOT_LEVEL, slot_array + i, NULL))
1.64 ratchov 2611: break;
2612: c = c->next;
2613: }
2614: if (strcmp(c->node0.name, name) == 0)
2615: return;
2616: strlcpy(c->node0.name, name, CTL_NAMEMAX);
2617: c->desc_mask = ~0;
1.1 ratchov 2618: }