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