Bug Summary

File:src/usr.bin/sndiod/dev.c
Warning:line 2496, column 3
Null pointer passed as 2nd argument to string copy function

Annotated Source Code

Press '?' to see keyboard shortcuts

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