Annotation of src/usr.bin/sndiod/dev.c, Revision 1.99
1.99 ! ratchov 1: /* $OpenBSD: dev.c,v 1.98 2021/03/10 08:21:27 ratchov Exp $ */
1.1 ratchov 2: /*
3: * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #include <stdio.h>
18: #include <string.h>
19:
20: #include "abuf.h"
21: #include "defs.h"
22: #include "dev.h"
23: #include "dsp.h"
24: #include "siofile.h"
25: #include "midi.h"
1.36 ratchov 26: #include "opt.h"
1.1 ratchov 27: #include "sysex.h"
28: #include "utils.h"
29:
1.14 ratchov 30: void zomb_onmove(void *);
1.25 ratchov 31: void zomb_onvol(void *);
1.1 ratchov 32: void zomb_fill(void *);
33: void zomb_flush(void *);
34: void zomb_eof(void *);
35: void zomb_exit(void *);
36:
1.7 ratchov 37: void dev_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.99 ! ratchov 1716: char ctl_name[CTL_NAMEMAX];
1.52 ratchov 1717: unsigned int i, ser, bestser, bestidx;
1718: struct slot *unit[DEV_NSLOT];
1.1 ratchov 1719: struct slot *s;
1720:
1721: /*
1.27 ratchov 1722: * create a ``valid'' control name (lowcase, remove [^a-z], truncate)
1.1 ratchov 1723: */
1724: for (i = 0, p = who; ; p++) {
1725: if (i == SLOT_NAMEMAX - 1 || *p == '\0') {
1726: name[i] = '\0';
1727: break;
1728: } else if (*p >= 'A' && *p <= 'Z') {
1729: name[i++] = *p + 'a' - 'A';
1730: } else if (*p >= 'a' && *p <= 'z')
1731: name[i++] = *p;
1732: }
1733: if (i == 0)
1734: strlcpy(name, "noname", SLOT_NAMEMAX);
1735:
1736: /*
1.52 ratchov 1737: * build a unit-to-slot map for this name
1.1 ratchov 1738: */
1.52 ratchov 1739: for (i = 0; i < DEV_NSLOT; i++)
1740: unit[i] = NULL;
1.84 ratchov 1741: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.1 ratchov 1742: if (strcmp(s->name, name) == 0)
1.52 ratchov 1743: unit[s->unit] = s;
1.1 ratchov 1744: }
1745:
1746: /*
1.54 ratchov 1747: * find the free slot with the least unit number and same id
1748: */
1749: for (i = 0; i < DEV_NSLOT; i++) {
1750: s = unit[i];
1751: if (s != NULL && s->ops == NULL && s->id == id)
1752: goto found;
1753: }
1754:
1755: /*
1.52 ratchov 1756: * find the free slot with the least unit number
1.1 ratchov 1757: */
1.52 ratchov 1758: for (i = 0; i < DEV_NSLOT; i++) {
1759: s = unit[i];
1.54 ratchov 1760: if (s != NULL && s->ops == NULL) {
1761: s->id = id;
1.1 ratchov 1762: goto found;
1.54 ratchov 1763: }
1.1 ratchov 1764: }
1765:
1766: /*
1.18 ratchov 1767: * couldn't find a matching slot, pick oldest free slot
1.1 ratchov 1768: * and set its name/unit
1769: */
1770: bestser = 0;
1771: bestidx = DEV_NSLOT;
1.84 ratchov 1772: for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
1.1 ratchov 1773: if (s->ops != NULL)
1774: continue;
1.84 ratchov 1775: ser = slot_serial - s->serial;
1.1 ratchov 1776: if (ser > bestser) {
1777: bestser = ser;
1778: bestidx = i;
1779: }
1780: }
1.98 ratchov 1781:
1782: if (bestidx == DEV_NSLOT) {
1783: if (log_level >= 1) {
1784: log_puts(name);
1785: log_puts(": out of sub-device slots\n");
1786: }
1787: return NULL;
1.1 ratchov 1788: }
1.53 ratchov 1789:
1.98 ratchov 1790: s = slot_array + bestidx;
1.99 ! ratchov 1791: ctl_del(CTL_SLOT_LEVEL, s, NULL);
1.98 ratchov 1792: s->vol = MIDI_MAXCTL;
1793: strlcpy(s->name, name, SLOT_NAMEMAX);
1794: s->serial = slot_serial++;
1795: for (i = 0; unit[i] != NULL; i++)
1796: ; /* nothing */
1797: s->unit = i;
1798: s->id = id;
1.99 ! ratchov 1799: s->opt = opt;
! 1800: slot_ctlname(s, ctl_name, CTL_NAMEMAX);
! 1801: ctl_new(CTL_SLOT_LEVEL, s, NULL,
! 1802: CTL_NUM, "app", ctl_name, -1, "level",
! 1803: NULL, -1, 127, s->vol);
1.1 ratchov 1804:
1805: found:
1.37 ratchov 1806: if ((mode & MODE_REC) && (opt->mode & MODE_MON)) {
1807: mode |= MODE_MON;
1808: mode &= ~MODE_REC;
1809: }
1810: if ((mode & opt->mode) != mode) {
1811: if (log_level >= 1) {
1812: slot_log(s);
1813: log_puts(": requested mode not allowed\n");
1814: }
1.89 ratchov 1815: return NULL;
1.37 ratchov 1816: }
1.89 ratchov 1817: if (!dev_ref(opt->dev))
1.1 ratchov 1818: return NULL;
1.89 ratchov 1819: if ((mode & opt->dev->mode) != mode) {
1.1 ratchov 1820: if (log_level >= 1) {
1821: slot_log(s);
1822: log_puts(": requested mode not supported\n");
1823: }
1824: }
1.37 ratchov 1825: s->opt = opt;
1.31 ratchov 1826: s->ops = ops;
1827: s->arg = arg;
1828: s->pstate = SLOT_INIT;
1.1 ratchov 1829: s->mode = mode;
1.6 ratchov 1830: aparams_init(&s->par);
1.41 ratchov 1831: if (s->mode & MODE_PLAY)
1.42 ratchov 1832: s->mix.nch = s->opt->pmax - s->opt->pmin + 1;
1.41 ratchov 1833: if (s->mode & MODE_RECMASK)
1.42 ratchov 1834: s->sub.nch = s->opt->rmax - s->opt->rmin + 1;
1.94 ratchov 1835: s->xrun = s->opt->mtc != NULL ? XRUN_SYNC : XRUN_IGNORE;
1.89 ratchov 1836: s->appbufsz = s->opt->dev->bufsz;
1837: s->round = s->opt->dev->round;
1838: s->rate = s->opt->dev->rate;
1839: dev_midi_slotdesc(s->opt->dev, s);
1840: dev_midi_vol(s->opt->dev, s);
1.43 ratchov 1841: #ifdef DEBUG
1842: if (log_level >= 3) {
1843: slot_log(s);
1844: log_puts(": using ");
1.89 ratchov 1845: dev_log(s->opt->dev);
1.43 ratchov 1846: log_puts(".");
1.89 ratchov 1847: log_puts(s->opt->name);
1.43 ratchov 1848: log_puts(", mode = ");
1849: log_putx(mode);
1850: log_puts("\n");
1851: }
1852: #endif
1.1 ratchov 1853: return s;
1854: }
1855:
1856: /*
1857: * release the given slot
1858: */
1859: void
1860: slot_del(struct slot *s)
1861: {
1862: s->arg = s;
1863: s->ops = &zomb_slotops;
1864: switch (s->pstate) {
1865: case SLOT_INIT:
1866: s->ops = NULL;
1867: break;
1868: case SLOT_START:
1869: case SLOT_READY:
1870: case SLOT_RUN:
1871: case SLOT_STOP:
1.82 ratchov 1872: slot_stop(s, 0);
1.1 ratchov 1873: break;
1874: }
1.89 ratchov 1875: dev_unref(s->opt->dev);
1.1 ratchov 1876: }
1877:
1878: /*
1879: * change the slot play volume; called either by the slot or by MIDI
1880: */
1881: void
1882: slot_setvol(struct slot *s, unsigned int vol)
1883: {
1884: #ifdef DEBUG
1885: if (log_level >= 3) {
1886: slot_log(s);
1887: log_puts(": setting volume ");
1888: log_putu(vol);
1889: log_puts("\n");
1890: }
1891: #endif
1892: s->vol = vol;
1893: s->mix.vol = MIDI_TO_ADATA(s->vol);
1894: }
1895:
1896: /*
1897: * attach the slot to the device (ie start playing & recording
1898: */
1899: void
1900: slot_attach(struct slot *s)
1901: {
1.89 ratchov 1902: struct dev *d = s->opt->dev;
1.12 ratchov 1903: long long pos;
1.1 ratchov 1904:
1905: /*
1906: * start the device if not started
1907: */
1908: dev_wakeup(d);
1.23 ratchov 1909:
1.1 ratchov 1910: /*
1.12 ratchov 1911: * adjust initial clock
1912: */
1.79 ratchov 1913: pos = s->delta_rem +
1914: (long long)s->delta * d->round +
1915: (long long)d->delta * s->round;
1916: s->delta = pos / (int)d->round;
1.12 ratchov 1917: s->delta_rem = pos % d->round;
1.79 ratchov 1918: if (s->delta_rem < 0) {
1919: s->delta_rem += d->round;
1920: s->delta--;
1921: }
1.12 ratchov 1922:
1.1 ratchov 1923: #ifdef DEBUG
1.17 ratchov 1924: if (log_level >= 2) {
1.1 ratchov 1925: slot_log(s);
1926: log_puts(": attached at ");
1.79 ratchov 1927: log_puti(s->delta);
1928: log_puts(" + ");
1929: log_puti(s->delta_rem);
1930: log_puts("/");
1931: log_puti(s->round);
1.1 ratchov 1932: log_puts("\n");
1933: }
1934: #endif
1935:
1936: /*
1937: * We dont check whether the device is dying,
1938: * because dev_xxx() functions are supposed to
1939: * work (i.e., not to crash)
1940: */
1.91 edd 1941:
1.1 ratchov 1942: s->next = d->slot_list;
1943: d->slot_list = s;
1944: if (s->mode & MODE_PLAY) {
1945: s->mix.vol = MIDI_TO_ADATA(s->vol);
1946: dev_mix_adjvol(d);
1947: }
1948: }
1949:
1950: /*
1951: * if MMC is enabled, and try to attach all slots synchronously, else
1952: * simply attach the slot
1953: */
1954: void
1955: slot_ready(struct slot *s)
1956: {
1.3 ratchov 1957: /*
1958: * device may be disconnected, and if so we're called from
1959: * slot->ops->exit() on a closed device
1.23 ratchov 1960: */
1.89 ratchov 1961: if (s->opt->dev->pstate == DEV_CFG)
1.3 ratchov 1962: return;
1.94 ratchov 1963: if (s->opt->mtc == NULL) {
1.1 ratchov 1964: slot_attach(s);
1.79 ratchov 1965: s->pstate = SLOT_RUN;
1966: } else
1.94 ratchov 1967: mtc_trigger(s->opt->mtc);
1.1 ratchov 1968: }
1969:
1970: /*
1971: * setup buffers & conversion layers, prepare the slot to receive data
1972: * (for playback) or start (recording).
1973: */
1974: void
1975: slot_start(struct slot *s)
1976: {
1.89 ratchov 1977: struct dev *d = s->opt->dev;
1.1 ratchov 1978: #ifdef DEBUG
1979: if (s->pstate != SLOT_INIT) {
1980: slot_log(s);
1981: log_puts(": slot_start: wrong state\n");
1982: panic();
1983: }
1984: if (s->mode & MODE_PLAY) {
1985: if (log_level >= 3) {
1986: slot_log(s);
1987: log_puts(": playing ");
1988: aparams_log(&s->par);
1989: log_puts(" -> ");
1.81 ratchov 1990: aparams_log(&d->par);
1.1 ratchov 1991: log_puts("\n");
1992: }
1993: }
1994: if (s->mode & MODE_RECMASK) {
1995: if (log_level >= 3) {
1996: slot_log(s);
1997: log_puts(": recording ");
1998: aparams_log(&s->par);
1999: log_puts(" <- ");
1.81 ratchov 2000: aparams_log(&d->par);
1.1 ratchov 2001: log_puts("\n");
1.35 ratchov 2002: }
1.1 ratchov 2003: }
2004: #endif
1.35 ratchov 2005: slot_allocbufs(s);
1.47 ratchov 2006:
2007: if (s->mode & MODE_RECMASK) {
2008: /*
2009: * N-th recorded block is the N-th played block
2010: */
1.81 ratchov 2011: s->sub.prime = -dev_getpos(d) / d->round;
1.47 ratchov 2012: }
2013: s->skip = 0;
2014:
1.79 ratchov 2015: /*
2016: * get the current position, the origin is when the first sample
2017: * played and/or recorded
2018: */
1.81 ratchov 2019: s->delta = dev_getpos(d) * (int)s->round / (int)d->round;
1.79 ratchov 2020: s->delta_rem = 0;
2021:
1.1 ratchov 2022: if (s->mode & MODE_PLAY) {
2023: s->pstate = SLOT_START;
2024: } else {
2025: s->pstate = SLOT_READY;
2026: slot_ready(s);
2027: }
2028: }
2029:
2030: /*
2031: * stop playback and recording, and free conversion layers
2032: */
2033: void
2034: slot_detach(struct slot *s)
2035: {
2036: struct slot **ps;
1.89 ratchov 2037: struct dev *d = s->opt->dev;
1.79 ratchov 2038: long long pos;
1.1 ratchov 2039:
1.81 ratchov 2040: for (ps = &d->slot_list; *ps != s; ps = &(*ps)->next) {
1.1 ratchov 2041: #ifdef DEBUG
1.28 ratchov 2042: if (*ps == NULL) {
1.1 ratchov 2043: slot_log(s);
2044: log_puts(": can't detach, not on list\n");
2045: panic();
2046: }
2047: #endif
1.23 ratchov 2048: }
1.1 ratchov 2049: *ps = s->next;
1.79 ratchov 2050:
2051: /*
2052: * adjust clock, go back d->delta ticks so that slot_attach()
2053: * could be called with the resulting state
2054: */
2055: pos = s->delta_rem +
2056: (long long)s->delta * d->round -
2057: (long long)d->delta * s->round;
2058: s->delta = pos / (int)d->round;
2059: s->delta_rem = pos % d->round;
2060: if (s->delta_rem < 0) {
2061: s->delta_rem += d->round;
2062: s->delta--;
2063: }
2064:
2065: #ifdef DEBUG
2066: if (log_level >= 2) {
2067: slot_log(s);
2068: log_puts(": detached at ");
2069: log_puti(s->delta);
2070: log_puts(" + ");
2071: log_puti(s->delta_rem);
2072: log_puts("/");
2073: log_puti(d->round);
2074: log_puts("\n");
2075: }
2076: #endif
1.35 ratchov 2077: if (s->mode & MODE_PLAY)
1.81 ratchov 2078: dev_mix_adjvol(d);
1.1 ratchov 2079: }
2080:
2081: /*
2082: * put the slot in stopping state (draining play buffers) or
2083: * stop & detach if no data to drain.
2084: */
2085: void
1.82 ratchov 2086: slot_stop(struct slot *s, int drain)
1.1 ratchov 2087: {
2088: #ifdef DEBUG
2089: if (log_level >= 3) {
2090: slot_log(s);
2091: log_puts(": stopping\n");
2092: }
2093: #endif
2094: if (s->pstate == SLOT_START) {
1.33 ratchov 2095: /*
2096: * If in rec-only mode, we're already in the READY or
2097: * RUN states. We're here because the play buffer was
2098: * not full enough, try to start so it's drained.
2099: */
2100: s->pstate = SLOT_READY;
2101: slot_ready(s);
1.1 ratchov 2102: }
1.34 ratchov 2103:
2104: if (s->pstate == SLOT_RUN) {
1.82 ratchov 2105: if ((s->mode & MODE_PLAY) && drain) {
1.34 ratchov 2106: /*
2107: * Don't detach, dev_cycle() will do it for us
2108: * when the buffer is drained.
2109: */
2110: s->pstate = SLOT_STOP;
2111: return;
2112: }
1.82 ratchov 2113: slot_detach(s);
2114: } else if (s->pstate == SLOT_STOP) {
1.34 ratchov 2115: slot_detach(s);
2116: } else {
1.1 ratchov 2117: #ifdef DEBUG
2118: if (log_level >= 3) {
2119: slot_log(s);
2120: log_puts(": not drained (blocked by mmc)\n");
2121: }
2122: #endif
2123: }
1.35 ratchov 2124:
1.34 ratchov 2125: s->pstate = SLOT_INIT;
2126: s->ops->eof(s->arg);
1.35 ratchov 2127: slot_freebufs(s);
1.1 ratchov 2128: }
2129:
1.12 ratchov 2130: void
2131: slot_skip_update(struct slot *s)
2132: {
2133: int skip;
2134:
2135: skip = slot_skip(s);
2136: while (skip > 0) {
2137: #ifdef DEBUG
2138: if (log_level >= 4) {
2139: slot_log(s);
2140: log_puts(": catching skipped block\n");
2141: }
2142: #endif
2143: if (s->mode & MODE_RECMASK)
2144: s->ops->flush(s->arg);
2145: if (s->mode & MODE_PLAY)
2146: s->ops->fill(s->arg);
2147: skip--;
2148: }
2149: }
2150:
1.1 ratchov 2151: /*
2152: * notify the slot that we just wrote in the play buffer, must be called
2153: * after each write
2154: */
2155: void
2156: slot_write(struct slot *s)
2157: {
2158: if (s->pstate == SLOT_START && s->mix.buf.used == s->mix.buf.len) {
2159: #ifdef DEBUG
2160: if (log_level >= 4) {
2161: slot_log(s);
2162: log_puts(": switching to READY state\n");
2163: }
2164: #endif
2165: s->pstate = SLOT_READY;
2166: slot_ready(s);
2167: }
1.12 ratchov 2168: slot_skip_update(s);
1.1 ratchov 2169: }
2170:
2171: /*
2172: * notify the slot that we freed some space in the rec buffer
2173: */
2174: void
2175: slot_read(struct slot *s)
2176: {
1.12 ratchov 2177: slot_skip_update(s);
1.64 ratchov 2178: }
2179:
2180: /*
2181: * allocate at control slot
2182: */
2183: struct ctlslot *
1.88 ratchov 2184: ctlslot_new(struct opt *o, struct ctlops *ops, void *arg)
1.64 ratchov 2185: {
2186: struct ctlslot *s;
2187: struct ctl *c;
2188: int i;
2189:
2190: i = 0;
2191: for (;;) {
2192: if (i == DEV_NCTLSLOT)
2193: return NULL;
1.85 ratchov 2194: s = ctlslot_array + i;
1.64 ratchov 2195: if (s->ops == NULL)
2196: break;
2197: i++;
2198: }
1.88 ratchov 2199: s->opt = o;
1.87 ratchov 2200: s->self = 1 << i;
1.88 ratchov 2201: if (!dev_ref(o->dev))
1.64 ratchov 2202: return NULL;
2203: s->ops = ops;
2204: s->arg = arg;
1.92 ratchov 2205: for (c = ctl_list; c != NULL; c = c->next) {
2206: if (!ctlslot_visible(s, c))
2207: continue;
1.87 ratchov 2208: c->refs_mask |= s->self;
1.92 ratchov 2209: }
1.64 ratchov 2210: return s;
2211: }
2212:
2213: /*
2214: * free control slot
2215: */
2216: void
2217: ctlslot_del(struct ctlslot *s)
2218: {
2219: struct ctl *c, **pc;
2220:
1.92 ratchov 2221: pc = &ctl_list;
1.64 ratchov 2222: while ((c = *pc) != NULL) {
1.87 ratchov 2223: c->refs_mask &= ~s->self;
1.64 ratchov 2224: if (c->refs_mask == 0) {
2225: *pc = c->next;
2226: xfree(c);
2227: } else
2228: pc = &c->next;
2229: }
2230: s->ops = NULL;
1.88 ratchov 2231: dev_unref(s->opt->dev);
1.64 ratchov 2232: }
2233:
1.92 ratchov 2234: int
2235: ctlslot_visible(struct ctlslot *s, struct ctl *c)
2236: {
2237: if (s->opt == NULL)
2238: return 1;
2239: switch (c->scope) {
2240: case CTL_HW:
2241: case CTL_DEV_MASTER:
2242: case CTL_DEV_ALT:
2243: return (s->opt->dev == c->u.any.arg0);
2244: case CTL_SLOT_LEVEL:
2245: return (s->opt->dev == c->u.slot_level.slot->opt->dev);
2246: default:
2247: return 0;
2248: }
2249: }
2250:
2251: struct ctl *
2252: ctlslot_lookup(struct ctlslot *s, int addr)
2253: {
2254: struct ctl *c;
2255:
2256: c = ctl_list;
2257: while (1) {
2258: if (c == NULL)
2259: return NULL;
2260: if (c->type != CTL_NONE && c->addr == addr)
2261: break;
2262: c = c->next;
2263: }
2264: if (!ctlslot_visible(s, c))
2265: return NULL;
2266: return c;
2267: }
2268:
1.64 ratchov 2269: void
2270: ctl_node_log(struct ctl_node *c)
2271: {
2272: log_puts(c->name);
2273: if (c->unit >= 0)
2274: log_putu(c->unit);
2275: }
2276:
2277: void
2278: ctl_log(struct ctl *c)
2279: {
2280: if (c->group[0] != 0) {
2281: log_puts(c->group);
2282: log_puts("/");
2283: }
2284: ctl_node_log(&c->node0);
2285: log_puts(".");
2286: log_puts(c->func);
2287: log_puts("=");
2288: switch (c->type) {
1.67 ratchov 2289: case CTL_NONE:
2290: log_puts("none");
2291: break;
1.64 ratchov 2292: case CTL_NUM:
2293: case CTL_SW:
2294: log_putu(c->curval);
2295: break;
2296: case CTL_VEC:
2297: case CTL_LIST:
1.74 ratchov 2298: case CTL_SEL:
1.64 ratchov 2299: ctl_node_log(&c->node1);
2300: log_puts(":");
2301: log_putu(c->curval);
2302: }
2303: log_puts(" at ");
2304: log_putu(c->addr);
1.92 ratchov 2305: log_puts(" -> ");
2306: switch (c->scope) {
2307: case CTL_HW:
2308: log_puts("hw:");
2309: log_puts(c->u.hw.dev->name);
2310: log_puts("/");
2311: log_putu(c->u.hw.addr);
2312: break;
2313: case CTL_DEV_MASTER:
2314: log_puts("dev_master:");
2315: log_puts(c->u.dev_master.dev->name);
2316: break;
2317: case CTL_DEV_ALT:
2318: log_puts("dev_alt:");
2319: log_puts(c->u.dev_alt.dev->name);
2320: log_putu(c->u.dev_alt.idx);
2321: break;
2322: case CTL_SLOT_LEVEL:
2323: log_puts("slot_level:");
2324: log_puts(c->u.slot_level.slot->name);
2325: log_putu(c->u.slot_level.slot->unit);
2326: break;
2327: default:
2328: log_puts("unknown");
2329: }
2330: }
2331:
2332: int
2333: ctl_setval(struct ctl *c, int val)
2334: {
2335: if (c->curval == val) {
2336: if (log_level >= 3) {
2337: ctl_log(c);
2338: log_puts(": already set\n");
2339: }
2340: return 1;
2341: }
2342: if (val < 0 || val > c->maxval) {
2343: if (log_level >= 3) {
2344: log_putu(val);
2345: log_puts(": ctl val out of bounds\n");
2346: }
2347: return 0;
2348: }
2349:
2350: switch (c->scope) {
2351: case CTL_HW:
2352: if (log_level >= 3) {
2353: ctl_log(c);
2354: log_puts(": marked as dirty\n");
2355: }
2356: c->curval = val;
2357: c->dirty = 1;
2358: return dev_ref(c->u.hw.dev);
2359: case CTL_DEV_MASTER:
2360: if (!c->u.dev_master.dev->master_enabled)
2361: return 1;
2362: dev_master(c->u.dev_master.dev, val);
2363: dev_midi_master(c->u.dev_master.dev);
2364: c->val_mask = ~0U;
2365: c->curval = val;
2366: return 1;
2367: case CTL_DEV_ALT:
2368: dev_setalt (c->u.dev_alt.dev, c->u.dev_alt.idx);
2369: return 1;
2370: case CTL_SLOT_LEVEL:
2371: slot_setvol(c->u.slot_level.slot, val);
2372: // XXX change dev_midi_vol() into slot_midi_vol()
2373: dev_midi_vol(c->u.slot_level.slot->opt->dev, c->u.slot_level.slot);
2374: c->val_mask = ~0U;
2375: c->curval = val;
2376: return 1;
2377: default:
2378: if (log_level >= 2) {
2379: ctl_log(c);
2380: log_puts(": not writable\n");
2381: }
2382: return 1;
2383: }
1.64 ratchov 2384: }
2385:
2386: /*
2387: * add a ctl
2388: */
2389: struct ctl *
1.92 ratchov 2390: ctl_new(int scope, void *arg0, void *arg1,
2391: int type, char *gstr,
2392: char *str0, int unit0, char *func,
2393: char *str1, int unit1, int maxval, int val)
1.64 ratchov 2394: {
2395: struct ctl *c, **pc;
1.92 ratchov 2396: struct ctlslot *s;
2397: int addr;
1.64 ratchov 2398: int i;
2399:
1.92 ratchov 2400: /*
2401: * find the smallest unused addr number and
2402: * the last position in the list
2403: */
2404: addr = 0;
2405: for (pc = &ctl_list; (c = *pc) != NULL; pc = &c->next) {
2406: if (c->addr > addr)
2407: addr = c->addr;
2408: }
2409: addr++;
2410:
1.64 ratchov 2411: c = xmalloc(sizeof(struct ctl));
2412: c->type = type;
2413: strlcpy(c->func, func, CTL_NAMEMAX);
2414: strlcpy(c->group, gstr, CTL_NAMEMAX);
2415: strlcpy(c->node0.name, str0, CTL_NAMEMAX);
2416: c->node0.unit = unit0;
1.74 ratchov 2417: if (c->type == CTL_VEC || c->type == CTL_LIST || c->type == CTL_SEL) {
1.64 ratchov 2418: strlcpy(c->node1.name, str1, CTL_NAMEMAX);
2419: c->node1.unit = unit1;
2420: } else
2421: memset(&c->node1, 0, sizeof(struct ctl_node));
1.92 ratchov 2422: c->scope = scope;
2423: c->u.any.arg0 = arg0;
2424: switch (scope) {
2425: case CTL_HW:
2426: c->u.hw.addr = *(unsigned int *)arg1;
2427: break;
2428: case CTL_DEV_ALT:
2429: c->u.dev_alt.idx = *(unsigned int *)arg1;
2430: break;
2431: default:
2432: c->u.any.arg1 = NULL;
2433: }
1.64 ratchov 2434: c->addr = addr;
2435: c->maxval = maxval;
2436: c->val_mask = ~0;
2437: c->desc_mask = ~0;
2438: c->curval = val;
2439: c->dirty = 0;
1.92 ratchov 2440: c->refs_mask = CTL_DEVMASK;
2441: for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) {
2442: if (s->ops == NULL)
2443: continue;
2444: if (ctlslot_visible(s, c))
1.64 ratchov 2445: c->refs_mask |= 1 << i;
2446: }
1.92 ratchov 2447: c->next = *pc;
1.64 ratchov 2448: *pc = c;
2449: #ifdef DEBUG
1.92 ratchov 2450: if (log_level >= 2) {
1.64 ratchov 2451: ctl_log(c);
1.92 ratchov 2452: log_puts(": added\n");
1.64 ratchov 2453: }
2454: #endif
2455: return c;
2456: }
2457:
2458: void
1.92 ratchov 2459: ctl_update(struct ctl *c)
2460: {
2461: struct ctlslot *s;
2462: unsigned int refs_mask;
2463: int i;
2464:
2465: for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) {
2466: if (s->ops == NULL)
2467: continue;
2468: refs_mask = ctlslot_visible(s, c) ? s->self : 0;
2469:
2470: /* nothing to do if no visibility change */
2471: if (((c->refs_mask & s->self) ^ refs_mask) == 0)
2472: continue;
2473: /* if control becomes visble */
2474: if (refs_mask)
2475: c->refs_mask |= s->self;
2476: /* if control is hidden */
2477: c->desc_mask |= s->self;
2478: }
2479: }
2480:
2481: int
2482: ctl_match(struct ctl *c, int scope, void *arg0, void *arg1)
2483: {
2484: if (c->type == CTL_NONE || c->scope != scope || c->u.any.arg0 != arg0)
2485: return 0;
2486: if (arg0 != NULL && c->u.any.arg0 != arg0)
2487: return 0;
2488: switch (scope) {
2489: case CTL_HW:
2490: if (arg1 != NULL && c->u.hw.addr != *(unsigned int *)arg1)
2491: return 0;
2492: break;
2493: case CTL_DEV_ALT:
2494: if (arg1 != NULL && c->u.dev_alt.idx != *(unsigned int *)arg1)
2495: return 0;
2496: break;
2497: }
2498: return 1;
2499: }
2500:
2501: struct ctl *
2502: ctl_find(int scope, void *arg0, void *arg1)
2503: {
2504: struct ctl *c;
2505:
2506: for (c = ctl_list; c != NULL; c = c->next) {
2507: if (ctl_match(c, scope, arg0, arg1))
2508: return c;
2509: }
2510: return NULL;
2511: }
2512:
2513: int
2514: ctl_onval(int scope, void *arg0, void *arg1, int val)
2515: {
2516: struct ctl *c;
2517:
2518: c = ctl_find(scope, arg0, arg1);
2519: if (c == NULL)
2520: return 0;
2521: c->curval = val;
2522: c->val_mask = ~0U;
2523: return 1;
2524: }
2525:
2526: void
2527: ctl_del(int scope, void *arg0, void *arg1)
1.64 ratchov 2528: {
2529: struct ctl *c, **pc;
2530:
1.92 ratchov 2531: pc = &ctl_list;
1.64 ratchov 2532: for (;;) {
2533: c = *pc;
2534: if (c == NULL)
2535: return;
1.92 ratchov 2536: if (ctl_match(c, scope, arg0, arg1)) {
1.64 ratchov 2537: #ifdef DEBUG
1.92 ratchov 2538: if (log_level >= 2) {
2539: ctl_log(c);
2540: log_puts(": removed\n");
2541: }
1.64 ratchov 2542: #endif
1.92 ratchov 2543: c->refs_mask &= ~CTL_DEVMASK;
2544: if (c->refs_mask == 0) {
2545: *pc = c->next;
2546: xfree(c);
2547: continue;
2548: }
2549: c->type = CTL_NONE;
2550: c->desc_mask = ~0;
2551: }
2552: pc = &c->next;
1.68 ratchov 2553: }
1.65 ratchov 2554: }
2555:
2556: void
2557: dev_ctlsync(struct dev *d)
2558: {
1.70 ratchov 2559: struct ctl *c;
1.65 ratchov 2560: struct ctlslot *s;
1.70 ratchov 2561: int found, i;
2562:
2563: found = 0;
1.92 ratchov 2564: for (c = ctl_list; c != NULL; c = c->next) {
2565: if (c->scope == CTL_HW &&
2566: c->u.hw.dev == d &&
1.70 ratchov 2567: c->type == CTL_NUM &&
1.92 ratchov 2568: strcmp(c->group, d->name) == 0 &&
1.70 ratchov 2569: strcmp(c->node0.name, "output") == 0 &&
2570: strcmp(c->func, "level") == 0)
2571: found = 1;
2572: }
2573:
2574: if (d->master_enabled && found) {
2575: if (log_level >= 2) {
2576: dev_log(d);
2577: log_puts(": software master level control disabled\n");
2578: }
2579: d->master_enabled = 0;
1.92 ratchov 2580: ctl_del(CTL_DEV_MASTER, d, NULL);
1.70 ratchov 2581: } else if (!d->master_enabled && !found) {
2582: if (log_level >= 2) {
2583: dev_log(d);
2584: log_puts(": software master level control enabled\n");
2585: }
2586: d->master_enabled = 1;
1.92 ratchov 2587: ctl_new(CTL_DEV_MASTER, d, NULL,
2588: CTL_NUM, d->name, "output", -1, "level",
2589: NULL, -1, 127, d->master);
1.70 ratchov 2590: }
1.65 ratchov 2591:
1.95 ratchov 2592: for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) {
2593: if (s->ops == NULL)
2594: continue;
2595: if (s->opt->dev == d)
1.65 ratchov 2596: s->ops->sync(s->arg);
2597: }
1.64 ratchov 2598: }
2599: