Bug Summary

File:src/usr.bin/sndiod/dev.c
Warning:line 574, column 11
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dev.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -D DEBUG -I /usr/src/usr.bin/sndiod/../../lib/libsndio -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/sndiod/dev.c
1/* $OpenBSD: dev.c,v 1.103 2021/11/01 14:43:24 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)(s->mix.weight) * (int)(s->mix.vol)) >> (16
- 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
25.1
'i' is not equal to NULL
!= NULL((void*)0); i = i->next) {
26
Loop condition is true. Entering loop body
556 if (!(i->mode & MODE_PLAY0x01))
27
Taking false branch
557 continue;
558 icmax = i->opt->pmin + i->mix.nch - 1;
559 weight = ADATA_UNIT(1 << (16 - 1));
560 if (d->autovol) {
28
Assuming field 'autovol' is not equal to 0
29
Taking true branch
561 /*
562 * count the number of inputs that have
563 * overlapping channel sets
564 */
565 n = 0;
30
The value 0 is assigned to 'n'
566 for (j = d->slot_list; j
30.1
'j' is not equal to NULL
!= NULL((void*)0)
; j = j->next) {
31
Loop condition is true. Entering loop body
34
Assuming 'j' is equal to NULL
35
Loop condition is false. Execution continues on line 574
567 if (!(j->mode & MODE_PLAY0x01))
32
Taking false branch
568 continue;
569 jcmax = j->opt->pmin + j->mix.nch - 1;
570 if (i->opt->pmin <= jcmax &&
33
Assuming 'jcmax' is < field 'pmin'
571 icmax >= j->opt->pmin)
572 n++;
573 }
574 weight /= n;
36
Division by zero
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)(weight) * (int)((aparams_ctltovol[d->master] <<
(16 - 16)))) >> (16 - 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 << (16 - 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) && (mtc_array[0].dev != d ||
684 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 /*
748 * skip cycles for XRUN_SYNC correction
749 */
750 slot_skip(s);
751 if (s->skip < 0) {
752 s->skip++;
753 ps = &s->next;
754 continue;
755 }
756
757#ifdef DEBUG1
758 if (s->pstate == SLOT_STOP4 && !(s->mode & MODE_PLAY0x01)) {
759 slot_log(s);
760 log_puts(": rec-only slots can't be drained\n");
761 panic();
762 }
763#endif
764 /*
765 * check if stopped stream finished draining
766 */
767 if (s->pstate == SLOT_STOP4 &&
768 s->mix.buf.used < s->round * s->mix.bpf) {
769 /*
770 * partial blocks are zero-filled by socket
771 * layer, so s->mix.buf.used == 0 and we can
772 * destroy the buffer
773 */
774 *ps = s->next;
775 s->pstate = SLOT_INIT0;
776 s->ops->eof(s->arg);
777 slot_freebufs(s);
778 dev_mix_adjvol(d);
779#ifdef DEBUG1
780 if (log_level >= 3) {
781 slot_log(s);
782 log_puts(": drained\n");
783 }
784#endif
785 continue;
786 }
787
788 /*
789 * check for xruns
790 */
791 if (((s->mode & MODE_PLAY0x01) &&
792 s->mix.buf.used < s->round * s->mix.bpf) ||
793 ((s->mode & MODE_RECMASK(0x02 | 0x10)) &&
794 s->sub.buf.len - s->sub.buf.used <
795 s->round * s->sub.bpf)) {
796
797#ifdef DEBUG1
798 if (log_level >= 3) {
799 slot_log(s);
800 log_puts(": xrun, pause cycle\n");
801 }
802#endif
803 if (s->xrun == XRUN_IGNORE0) {
804 s->delta -= s->round;
805 ps = &s->next;
806 } else if (s->xrun == XRUN_SYNC1) {
807 s->skip++;
808 ps = &s->next;
809 } else if (s->xrun == XRUN_ERROR2) {
810 s->ops->exit(s->arg);
811 *ps = s->next;
812 } else {
813#ifdef DEBUG1
814 slot_log(s);
815 log_puts(": bad xrun mode\n");
816 panic();
817#endif
818 }
819 continue;
820 }
821 if ((s->mode & MODE_RECMASK(0x02 | 0x10)) && !(s->pstate == SLOT_STOP4)) {
822 if (s->sub.prime == 0) {
823 dev_sub_bcopy(d, s);
824 s->ops->flush(s->arg);
825 } else {
826#ifdef DEBUG1
827 if (log_level >= 3) {
828 slot_log(s);
829 log_puts(": prime = ");
830 log_puti(s->sub.prime);
831 log_puts("\n");
832 }
833#endif
834 s->sub.prime--;
835 }
836 }
837 if (s->mode & MODE_PLAY0x01) {
838 dev_mix_badd(d, s);
839 if (s->pstate != SLOT_STOP4)
840 s->ops->fill(s->arg);
841 }
842 ps = &s->next;
843 }
844 if ((d->mode & MODE_PLAY0x01) && d->encbuf) {
845 enc_do(&d->enc, (unsigned char *)DEV_PBUF(d)((d)->pbuf + (d)->poffs * (d)->pchan),
846 d->encbuf, d->round);
847 }
848}
849
850/*
851 * called at every clock tick by the device
852 */
853void
854dev_onmove(struct dev *d, int delta)
855{
856 long long pos;
857 struct slot *s, *snext;
858
859 d->delta += delta;
860
861 for (s = d->slot_list; s != NULL((void*)0); s = snext) {
862 /*
863 * s->ops->onmove() may remove the slot
864 */
865 snext = s->next;
866 pos = s->delta_rem +
867 (long long)s->delta * d->round +
868 (long long)delta * s->round;
869 s->delta = pos / (int)d->round;
870 s->delta_rem = pos % d->round;
871 if (s->delta_rem < 0) {
872 s->delta_rem += d->round;
873 s->delta--;
874 }
875 if (s->delta >= 0)
876 s->ops->onmove(s->arg);
877 }
878
879 if (mtc_array[0].dev == d && mtc_array[0].tstate == MTC_RUN3)
880 mtc_midi_qfr(&mtc_array[0], delta);
881}
882
883void
884dev_master(struct dev *d, unsigned int master)
885{
886 struct ctl *c;
887 unsigned int v;
888
889 if (log_level >= 2) {
890 dev_log(d);
891 log_puts(": master volume set to ");
892 log_putu(master);
893 log_puts("\n");
894 }
895 if (d->master_enabled) {
896 d->master = master;
897 if (d->mode & MODE_PLAY0x01)
898 dev_mix_adjvol(d);
899 } else {
900 for (c = ctl_list; c != NULL((void*)0); c = c->next) {
901 if (c->scope != CTL_HW0 || c->u.hw.dev != d)
902 continue;
903 if (c->type != CTL_NUM2 ||
904 strcmp(c->group, d->name) != 0 ||
905 strcmp(c->node0.name, "output") != 0 ||
906 strcmp(c->func, "level") != 0)
907 continue;
908 v = (master * c->maxval + 64) / 127;
909 ctl_setval(c, v);
910 }
911 }
912}
913
914/*
915 * Create a sndio device
916 */
917struct dev *
918dev_new(char *path, struct aparams *par,
919 unsigned int mode, unsigned int bufsz, unsigned int round,
920 unsigned int rate, unsigned int hold, unsigned int autovol)
921{
922 struct dev *d, **pd;
923
924 if (dev_sndnum == DEV_NMAX16) {
925 if (log_level >= 1)
926 log_puts("too many devices\n");
927 return NULL((void*)0);
928 }
929 d = xmalloc(sizeof(struct dev));
930 d->path = path;
931 d->num = dev_sndnum++;
932
933 d->reqpar = *par;
934 d->reqmode = mode;
935 d->reqpchan = d->reqrchan = 0;
936 d->reqbufsz = bufsz;
937 d->reqround = round;
938 d->reqrate = rate;
939 d->hold = hold;
940 d->autovol = autovol;
941 d->refcnt = 0;
942 d->pstate = DEV_CFG0;
943 d->slot_list = NULL((void*)0);
944 d->master = MIDI_MAXCTL127;
945 d->master_enabled = 0;
946 d->alt_next = d;
947 snprintf(d->name, CTL_NAMEMAX16, "%u", d->num);
948 for (pd = &dev_list; *pd != NULL((void*)0); pd = &(*pd)->next)
949 ;
950 d->next = *pd;
951 *pd = d;
952 return d;
953}
954
955/*
956 * adjust device parameters and mode
957 */
958void
959dev_adjpar(struct dev *d, int mode,
960 int pmax, int rmax)
961{
962 d->reqmode |= mode & MODE_AUDIOMASK(0x01 | 0x02 | 0x10);
963 if (mode & MODE_PLAY0x01) {
964 if (d->reqpchan < pmax + 1)
965 d->reqpchan = pmax + 1;
966 }
967 if (mode & MODE_REC0x02) {
968 if (d->reqrchan < rmax + 1)
969 d->reqrchan = rmax + 1;
970 }
971}
972
973/*
974 * Open the device with the dev_reqxxx capabilities. Setup a mixer, demuxer,
975 * monitor, midi control, and any necessary conversions.
976 *
977 * Note that record and play buffers are always allocated, even if the
978 * underlying device doesn't support both modes.
979 */
980int
981dev_allocbufs(struct dev *d)
982{
983 /*
984 * Create record buffer.
985 */
986
987 /* Create device <-> demuxer buffer */
988 d->rbuf = xmalloc(d->round * d->rchan * sizeof(adata_t));
989
990 /* Insert a converter, if needed. */
991 if (!aparams_native(&d->par)) {
992 dec_init(&d->dec, &d->par, d->rchan);
993 d->decbuf = xmalloc(d->round * d->rchan * d->par.bps);
994 } else
995 d->decbuf = NULL((void*)0);
996
997 /*
998 * Create play buffer
999 */
1000
1001 /* Create device <-> mixer buffer */
1002 d->poffs = 0;
1003 d->psize = d->bufsz + d->round;
1004 d->pbuf = xmalloc(d->psize * d->pchan * sizeof(adata_t));
1005 d->mode |= MODE_MON0x10;
1006
1007 /* Append a converter, if needed. */
1008 if (!aparams_native(&d->par)) {
1009 enc_init(&d->enc, &d->par, d->pchan);
1010 d->encbuf = xmalloc(d->round * d->pchan * d->par.bps);
1011 } else
1012 d->encbuf = NULL((void*)0);
1013
1014 /*
1015 * Initially fill the record buffer with zeroed samples. This ensures
1016 * that when a client records from a play-only device the client just
1017 * gets silence.
1018 */
1019 memset(d->rbuf, 0, d->round * d->rchan * sizeof(adata_t));
1020
1021 if (log_level >= 2) {
1022 dev_log(d);
1023 log_puts(": ");
1024 log_putu(d->rate);
1025 log_puts("Hz, ");
1026 aparams_log(&d->par);
1027 if (d->mode & MODE_PLAY0x01) {
1028 log_puts(", play 0:");
1029 log_puti(d->pchan - 1);
1030 }
1031 if (d->mode & MODE_REC0x02) {
1032 log_puts(", rec 0:");
1033 log_puti(d->rchan - 1);
1034 }
1035 log_puts(", ");
1036 log_putu(d->bufsz / d->round);
1037 log_puts(" blocks of ");
1038 log_putu(d->round);
1039 log_puts(" frames");
1040 if (d == mtc_array[0].dev)
1041 log_puts(", mtc");
1042 log_puts("\n");
1043 }
1044 return 1;
1045}
1046
1047/*
1048 * Reset parameters and open the device.
1049 */
1050int
1051dev_open(struct dev *d)
1052{
1053 d->mode = d->reqmode;
1054 d->round = d->reqround;
1055 d->bufsz = d->reqbufsz;
1056 d->rate = d->reqrate;
1057 d->pchan = d->reqpchan;
1058 d->rchan = d->reqrchan;
1059 d->par = d->reqpar;
1060 if (d->pchan == 0)
1061 d->pchan = 2;
1062 if (d->rchan == 0)
1063 d->rchan = 2;
1064 if (!dev_sio_open(d)) {
1065 if (log_level >= 1) {
1066 dev_log(d);
1067 log_puts(": failed to open audio device\n");
1068 }
1069 return 0;
1070 }
1071 if (!dev_allocbufs(d))
1072 return 0;
1073
1074 d->pstate = DEV_INIT1;
1075 return 1;
1076}
1077
1078/*
1079 * Force all slots to exit and close device, called after an error
1080 */
1081void
1082dev_abort(struct dev *d)
1083{
1084 int i;
1085 struct slot *s;
1086 struct ctlslot *c;
1087 struct opt *o;
1088
1089 for (i = 0, s = slot_array; i < DEV_NSLOT8; i++, s++) {
1090 if (s->opt == NULL((void*)0) || s->opt->dev != d)
1091 continue;
1092 if (s->ops) {
1093 s->ops->exit(s->arg);
1094 s->ops = NULL((void*)0);
1095 }
1096 }
1097 d->slot_list = NULL((void*)0);
1098
1099 for (o = opt_list; o != NULL((void*)0); o = o->next) {
1100 if (o->dev != d)
1101 continue;
1102 for (c = ctlslot_array, i = 0; i < DEV_NCTLSLOT8; i++, c++) {
1103 if (c->ops == NULL((void*)0))
1104 continue;
1105 if (c->opt == o) {
1106 c->ops->exit(s->arg);
1107 c->ops = NULL((void*)0);
1108 }
1109 }
1110
1111 midi_abort(o->midi);
1112 }
1113
1114 if (d->pstate != DEV_CFG0)
1115 dev_close(d);
1116}
1117
1118/*
1119 * force the device to go in DEV_CFG state, the caller is supposed to
1120 * ensure buffers are drained
1121 */
1122void
1123dev_freebufs(struct dev *d)
1124{
1125#ifdef DEBUG1
1126 if (log_level >= 3) {
1127 dev_log(d);
1128 log_puts(": closing\n");
1129 }
1130#endif
1131 if (d->mode & MODE_PLAY0x01) {
1132 if (d->encbuf != NULL((void*)0))
1133 xfree(d->encbuf);
1134 xfree(d->pbuf);
1135 }
1136 if (d->mode & MODE_REC0x02) {
1137 if (d->decbuf != NULL((void*)0))
1138 xfree(d->decbuf);
1139 xfree(d->rbuf);
1140 }
1141}
1142
1143/*
1144 * Close the device and exit all slots
1145 */
1146void
1147dev_close(struct dev *d)
1148{
1149 d->pstate = DEV_CFG0;
1150 dev_sio_close(d);
1151 dev_freebufs(d);
1152
1153 if (d->master_enabled) {
1154 d->master_enabled = 0;
1155 ctl_del(CTL_DEV_MASTER1, d, NULL((void*)0));
1156 }
1157}
1158
1159int
1160dev_ref(struct dev *d)
1161{
1162#ifdef DEBUG1
1163 if (log_level >= 3) {
1164 dev_log(d);
1165 log_puts(": device requested\n");
1166 }
1167#endif
1168 if (d->pstate == DEV_CFG0 && !dev_open(d))
1169 return 0;
1170 d->refcnt++;
1171 return 1;
1172}
1173
1174void
1175dev_unref(struct dev *d)
1176{
1177#ifdef DEBUG1
1178 if (log_level >= 3) {
1179 dev_log(d);
1180 log_puts(": device released\n");
1181 }
1182#endif
1183 d->refcnt--;
1184 if (d->refcnt == 0 && d->pstate == DEV_INIT1)
1185 dev_close(d);
1186}
1187
1188/*
1189 * initialize the device with the current parameters
1190 */
1191int
1192dev_init(struct dev *d)
1193{
1194 if ((d->reqmode & MODE_AUDIOMASK(0x01 | 0x02 | 0x10)) == 0) {
1195#ifdef DEBUG1
1196 dev_log(d);
1197 log_puts(": has no streams\n");
1198#endif
1199 return 0;
1200 }
1201 if (d->hold && !dev_ref(d))
1202 return 0;
1203 return 1;
1204}
1205
1206/*
1207 * Unless the device is already in process of closing, request it to close
1208 */
1209void
1210dev_done(struct dev *d)
1211{
1212#ifdef DEBUG1
1213 if (log_level >= 3) {
1214 dev_log(d);
1215 log_puts(": draining\n");
1216 }
1217#endif
1218 if (mtc_array[0].dev == d && mtc_array[0].tstate != MTC_STOP1)
1219 mtc_stop(&mtc_array[0]);
1220 if (d->hold)
1221 dev_unref(d);
1222}
1223
1224struct dev *
1225dev_bynum(int num)
1226{
1227 struct dev *d;
1228
1229 for (d = dev_list; d != NULL((void*)0); d = d->next) {
1230 if (d->num == num)
1231 return d;
1232 }
1233 return NULL((void*)0);
1234}
1235
1236/*
1237 * Free the device
1238 */
1239void
1240dev_del(struct dev *d)
1241{
1242 struct dev **p;
1243
1244#ifdef DEBUG1
1245 if (log_level >= 3) {
1246 dev_log(d);
1247 log_puts(": deleting\n");
1248 }
1249#endif
1250 if (d->pstate != DEV_CFG0)
1251 dev_close(d);
1252 for (p = &dev_list; *p != d; p = &(*p)->next) {
1253#ifdef DEBUG1
1254 if (*p == NULL((void*)0)) {
1255 dev_log(d);
1256 log_puts(": device to delete not on the list\n");
1257 panic();
1258 }
1259#endif
1260 }
1261 *p = d->next;
1262 xfree(d);
1263}
1264
1265unsigned int
1266dev_roundof(struct dev *d, unsigned int newrate)
1267{
1268 return (d->round * newrate + d->rate / 2) / d->rate;
1269}
1270
1271/*
1272 * If the device is paused, then resume it.
1273 */
1274void
1275dev_wakeup(struct dev *d)
1276{
1277 if (d->pstate == DEV_INIT1) {
15
Assuming field 'pstate' is not equal to DEV_INIT
16
Taking false branch
1278 if (log_level >= 2) {
1279 dev_log(d);
1280 log_puts(": device started\n");
1281 }
1282 if (d->mode & MODE_PLAY0x01) {
1283 d->prime = d->bufsz;
1284 } else {
1285 d->prime = 0;
1286 }
1287 d->poffs = 0;
1288
1289 /*
1290 * empty cycles don't increment delta, so it's ok to
1291 * start at 0
1292 **/
1293 d->delta = 0;
1294
1295 d->pstate = DEV_RUN2;
1296 dev_sio_start(d);
1297 }
1298}
17
Returning without writing to 'd->autovol', which participates in a condition later
1299
1300/*
1301 * Return true if both of the given devices can run the same
1302 * clients
1303 */
1304int
1305dev_iscompat(struct dev *o, struct dev *n)
1306{
1307 if (((long long)o->round * n->rate != (long long)n->round * o->rate) ||
1308 ((long long)o->bufsz * n->rate != (long long)n->bufsz * o->rate)) {
1309 if (log_level >= 1) {
1310 log_puts(n->name);
1311 log_puts(": not compatible with ");
1312 log_puts(o->name);
1313 log_puts("\n");
1314 }
1315 return 0;
1316 }
1317 return 1;
1318}
1319
1320/*
1321 * Close the device, but attempt to migrate everything to a new sndio
1322 * device.
1323 */
1324struct dev *
1325dev_migrate(struct dev *odev)
1326{
1327 struct dev *ndev;
1328 struct opt *o;
1329 struct slot *s;
1330 int i;
1331
1332 /* not opened */
1333 if (odev->pstate == DEV_CFG0)
1334 return odev;
1335
1336 ndev = odev;
1337 while (1) {
1338 /* try next one, circulating through the list */
1339 ndev = ndev->alt_next;
1340 if (ndev == odev) {
1341 if (log_level >= 1) {
1342 dev_log(odev);
1343 log_puts(": no fall-back device found\n");
1344 }
1345 return NULL((void*)0);
1346 }
1347
1348
1349 if (!dev_ref(ndev))
1350 continue;
1351
1352 /* check if new parameters are compatible with old ones */
1353 if (!dev_iscompat(odev, ndev)) {
1354 dev_unref(ndev);
1355 continue;
1356 }
1357
1358 /* found it!*/
1359 break;
1360 }
1361
1362 if (log_level >= 1) {
1363 dev_log(odev);
1364 log_puts(": switching to ");
1365 dev_log(ndev);
1366 log_puts("\n");
1367 }
1368
1369 if (mtc_array[0].dev == odev)
1370 mtc_setdev(&mtc_array[0], ndev);
1371
1372 /* move opts to new device (also moves clients using the opts) */
1373 for (o = opt_list; o != NULL((void*)0); o = o->next) {
1374 if (o->dev != odev)
1375 continue;
1376 if (strcmp(o->name, o->dev->name) == 0)
1377 continue;
1378 opt_setdev(o, ndev);
1379 }
1380
1381 /* terminate remaining clients */
1382 for (i = 0, s = slot_array; i < DEV_NSLOT8; i++, s++) {
1383 if (s->opt == NULL((void*)0) || s->opt->dev != odev)
1384 continue;
1385 if (s->ops != NULL((void*)0)) {
1386 s->ops->exit(s);
1387 s->ops = NULL((void*)0);
1388 }
1389 }
1390
1391 /* slots and/or MMC hold refs, drop ours */
1392 dev_unref(ndev);
1393
1394 return ndev;
1395}
1396
1397/*
1398 * check that all clients controlled by MMC are ready to start, if so,
1399 * attach them all at the same position
1400 */
1401void
1402mtc_trigger(struct mtc *mtc)
1403{
1404 int i;
1405 struct slot *s;
1406
1407 if (mtc->tstate != MTC_START2) {
1408 if (log_level >= 2) {
1409 dev_log(mtc->dev);
1410 log_puts(": not started by mmc yet, waiting...\n");
1411 }
1412 return;
1413 }
1414
1415 for (i = 0, s = slot_array; i < DEV_NSLOT8; i++, s++) {
1416 if (s->opt == NULL((void*)0) || s->opt->mtc != mtc)
1417 continue;
1418 if (s->pstate != SLOT_READY2) {
1419#ifdef DEBUG1
1420 if (log_level >= 3) {
1421 slot_log(s);
1422 log_puts(": not ready, start delayed\n");
1423 }
1424#endif
1425 return;
1426 }
1427 }
1428 if (!dev_ref(mtc->dev))
1429 return;
1430
1431 for (i = 0, s = slot_array; i < DEV_NSLOT8; i++, s++) {
1432 if (s->opt == NULL((void*)0) || s->opt->mtc != mtc)
1433 continue;
1434 slot_attach(s);
1435 s->pstate = SLOT_RUN3;
1436 }
1437 mtc->tstate = MTC_RUN3;
1438 mtc_midi_full(mtc);
1439 dev_wakeup(mtc->dev);
1440}
1441
1442/*
1443 * start all slots simultaneously
1444 */
1445void
1446mtc_start(struct mtc *mtc)
1447{
1448 if (mtc->tstate == MTC_STOP1) {
1449 mtc->tstate = MTC_START2;
1450 mtc_trigger(mtc);
1451#ifdef DEBUG1
1452 } else {
1453 if (log_level >= 3) {
1454 dev_log(mtc->dev);
1455 log_puts(": ignoring mmc start\n");
1456 }
1457#endif
1458 }
1459}
1460
1461/*
1462 * stop all slots simultaneously
1463 */
1464void
1465mtc_stop(struct mtc *mtc)
1466{
1467 switch (mtc->tstate) {
1468 case MTC_START2:
1469 mtc->tstate = MTC_STOP1;
1470 return;
1471 case MTC_RUN3:
1472 mtc->tstate = MTC_STOP1;
1473 dev_unref(mtc->dev);
1474 break;
1475 default:
1476#ifdef DEBUG1
1477 if (log_level >= 3) {
1478 dev_log(mtc->dev);
1479 log_puts(": ignored mmc stop\n");
1480 }
1481#endif
1482 return;
1483 }
1484}
1485
1486/*
1487 * relocate all slots simultaneously
1488 */
1489void
1490mtc_loc(struct mtc *mtc, unsigned int origin)
1491{
1492 if (log_level >= 2) {
1493 dev_log(mtc->dev);
1494 log_puts(": relocated to ");
1495 log_putu(origin);
1496 log_puts("\n");
1497 }
1498 if (mtc->tstate == MTC_RUN3)
1499 mtc_stop(mtc);
1500 mtc->origin = origin;
1501 if (mtc->tstate == MTC_RUN3)
1502 mtc_start(mtc);
1503}
1504
1505/*
1506 * set MMC device
1507 */
1508void
1509mtc_setdev(struct mtc *mtc, struct dev *d)
1510{
1511 struct opt *o;
1512
1513 if (mtc->dev == d)
1514 return;
1515
1516 if (log_level >= 2) {
1517 dev_log(d);
1518 log_puts(": set to be MIDI clock source\n");
1519 }
1520
1521 /* adjust clock and ref counter, if needed */
1522 if (mtc->tstate == MTC_RUN3) {
1523 mtc->delta -= mtc->dev->delta;
1524 dev_unref(mtc->dev);
1525 }
1526
1527 mtc->dev = d;
1528
1529 if (mtc->tstate == MTC_RUN3) {
1530 mtc->delta += mtc->dev->delta;
1531 dev_ref(mtc->dev);
1532 dev_wakeup(mtc->dev);
1533 }
1534
1535 /* move in once anything using MMC */
1536 for (o = opt_list; o != NULL((void*)0); o = o->next) {
1537 if (o->mtc == mtc)
1538 opt_setdev(o, mtc->dev);
1539 }
1540}
1541
1542/*
1543 * allocate buffers & conversion chain
1544 */
1545void
1546slot_initconv(struct slot *s)
1547{
1548 unsigned int dev_nch;
1549 struct dev *d = s->opt->dev;
1550
1551 if (s->mode & MODE_PLAY0x01) {
1552 cmap_init(&s->mix.cmap,
1553 s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1554 s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
1555 0, d->pchan - 1,
1556 s->opt->pmin, s->opt->pmax);
1557 s->mix.decbuf = NULL((void*)0);
1558 s->mix.resampbuf = NULL((void*)0);
1559 if (!aparams_native(&s->par)) {
1560 dec_init(&s->mix.dec, &s->par, s->mix.nch);
1561 s->mix.decbuf =
1562 xmalloc(s->round * s->mix.nch * sizeof(adata_t));
1563 }
1564 if (s->rate != d->rate) {
1565 resamp_init(&s->mix.resamp, s->round, d->round,
1566 s->mix.nch);
1567 s->mix.resampbuf =
1568 xmalloc(d->round * s->mix.nch * sizeof(adata_t));
1569 }
1570 s->mix.join = 1;
1571 s->mix.expand = 1;
1572 if (s->opt->dup && s->mix.cmap.nch > 0) {
1573 dev_nch = d->pchan < (s->opt->pmax + 1) ?
1574 d->pchan - s->opt->pmin :
1575 s->opt->pmax - s->opt->pmin + 1;
1576 if (dev_nch > s->mix.nch)
1577 s->mix.expand = dev_nch / s->mix.nch;
1578 else if (s->mix.nch > dev_nch)
1579 s->mix.join = s->mix.nch / dev_nch;
1580 }
1581 }
1582
1583 if (s->mode & MODE_RECMASK(0x02 | 0x10)) {
1584 unsigned int outchan = (s->opt->mode & MODE_MON0x10) ?
1585 d->pchan : d->rchan;
1586
1587 s->sub.encbuf = NULL((void*)0);
1588 s->sub.resampbuf = NULL((void*)0);
1589 cmap_init(&s->sub.cmap,
1590 0, outchan - 1,
1591 s->opt->rmin, s->opt->rmax,
1592 s->opt->rmin, s->opt->rmin + s->sub.nch - 1,
1593 s->opt->rmin, s->opt->rmin + s->sub.nch - 1);
1594 if (s->rate != d->rate) {
1595 resamp_init(&s->sub.resamp, d->round, s->round,
1596 s->sub.nch);
1597 s->sub.resampbuf =
1598 xmalloc(d->round * s->sub.nch * sizeof(adata_t));
1599 }
1600 if (!aparams_native(&s->par)) {
1601 enc_init(&s->sub.enc, &s->par, s->sub.nch);
1602 s->sub.encbuf =
1603 xmalloc(s->round * s->sub.nch * sizeof(adata_t));
1604 }
1605 s->sub.join = 1;
1606 s->sub.expand = 1;
1607 if (s->opt->dup && s->sub.cmap.nch > 0) {
1608 dev_nch = outchan < (s->opt->rmax + 1) ?
1609 outchan - s->opt->rmin :
1610 s->opt->rmax - s->opt->rmin + 1;
1611 if (dev_nch > s->sub.nch)
1612 s->sub.join = dev_nch / s->sub.nch;
1613 else if (s->sub.nch > dev_nch)
1614 s->sub.expand = s->sub.nch / dev_nch;
1615 }
1616
1617 /*
1618 * cmap_copy() doesn't write samples in all channels,
1619 * for instance when mono->stereo conversion is
1620 * disabled. So we have to prefill cmap_copy() output
1621 * with silence.
1622 */
1623 if (s->sub.resampbuf) {
1624 memset(s->sub.resampbuf, 0,
1625 d->round * s->sub.nch * sizeof(adata_t));
1626 } else if (s->sub.encbuf) {
1627 memset(s->sub.encbuf, 0,
1628 s->round * s->sub.nch * sizeof(adata_t));
1629 } else {
1630 memset(s->sub.buf.data, 0,
1631 s->appbufsz * s->sub.nch * sizeof(adata_t));
1632 }
1633 }
1634}
1635
1636/*
1637 * allocate buffers & conversion chain
1638 */
1639void
1640slot_allocbufs(struct slot *s)
1641{
1642 if (s->mode & MODE_PLAY0x01) {
1643 s->mix.bpf = s->par.bps * s->mix.nch;
1644 abuf_init(&s->mix.buf, s->appbufsz * s->mix.bpf);
1645 }
1646
1647 if (s->mode & MODE_RECMASK(0x02 | 0x10)) {
1648 s->sub.bpf = s->par.bps * s->sub.nch;
1649 abuf_init(&s->sub.buf, s->appbufsz * s->sub.bpf);
1650 }
1651
1652#ifdef DEBUG1
1653 if (log_level >= 3) {
1654 slot_log(s);
1655 log_puts(": allocated ");
1656 log_putu(s->appbufsz);
1657 log_puts("/");
1658 log_putu(SLOT_BUFSZ(s)((s)->appbufsz + (s)->opt->dev->bufsz / (s)->opt
->dev->round * (s)->round)
);
1659 log_puts(" fr buffers\n");
1660 }
1661#endif
1662}
1663
1664/*
1665 * free buffers & conversion chain
1666 */
1667void
1668slot_freebufs(struct slot *s)
1669{
1670 if (s->mode & MODE_RECMASK(0x02 | 0x10)) {
1671 abuf_done(&s->sub.buf);
1672 }
1673
1674 if (s->mode & MODE_PLAY0x01) {
1675 abuf_done(&s->mix.buf);
1676 }
1677}
1678
1679/*
1680 * allocate a new slot and register the given call-backs
1681 */
1682struct slot *
1683slot_new(struct opt *opt, unsigned int id, char *who,
1684 struct slotops *ops, void *arg, int mode)
1685{
1686 char *p;
1687 char name[SLOT_NAMEMAX8];
1688 char ctl_name[CTL_NAMEMAX16];
1689 unsigned int i, ser, bestser, bestidx;
1690 struct slot *unit[DEV_NSLOT8];
1691 struct slot *s;
1692
1693 /*
1694 * create a ``valid'' control name (lowcase, remove [^a-z], truncate)
1695 */
1696 for (i = 0, p = who; ; p++) {
1697 if (i == SLOT_NAMEMAX8 - 1 || *p == '\0') {
1698 name[i] = '\0';
1699 break;
1700 } else if (*p >= 'A' && *p <= 'Z') {
1701 name[i++] = *p + 'a' - 'A';
1702 } else if (*p >= 'a' && *p <= 'z')
1703 name[i++] = *p;
1704 }
1705 if (i == 0)
1706 strlcpy(name, "noname", SLOT_NAMEMAX8);
1707
1708 /*
1709 * build a unit-to-slot map for this name
1710 */
1711 for (i = 0; i < DEV_NSLOT8; i++)
1712 unit[i] = NULL((void*)0);
1713 for (i = 0, s = slot_array; i < DEV_NSLOT8; i++, s++) {
1714 if (strcmp(s->name, name) == 0)
1715 unit[s->unit] = s;
1716 }
1717
1718 /*
1719 * find the free slot with the least unit number and same id
1720 */
1721 for (i = 0; i < DEV_NSLOT8; i++) {
1722 s = unit[i];
1723 if (s != NULL((void*)0) && s->ops == NULL((void*)0) && s->id == id)
1724 goto found;
1725 }
1726
1727 /*
1728 * find the free slot with the least unit number
1729 */
1730 for (i = 0; i < DEV_NSLOT8; i++) {
1731 s = unit[i];
1732 if (s != NULL((void*)0) && s->ops == NULL((void*)0)) {
1733 s->id = id;
1734 goto found;
1735 }
1736 }
1737
1738 /*
1739 * couldn't find a matching slot, pick oldest free slot
1740 * and set its name/unit
1741 */
1742 bestser = 0;
1743 bestidx = DEV_NSLOT8;
1744 for (i = 0, s = slot_array; i < DEV_NSLOT8; i++, s++) {
1745 if (s->ops != NULL((void*)0))
1746 continue;
1747 ser = slot_serial - s->serial;
1748 if (ser > bestser) {
1749 bestser = ser;
1750 bestidx = i;
1751 }
1752 }
1753
1754 if (bestidx == DEV_NSLOT8) {
1755 if (log_level >= 1) {
1756 log_puts(name);
1757 log_puts(": out of sub-device slots\n");
1758 }
1759 return NULL((void*)0);
1760 }
1761
1762 s = slot_array + bestidx;
1763 ctl_del(CTL_SLOT_LEVEL3, s, NULL((void*)0));
1764 s->vol = MIDI_MAXCTL127;
1765 strlcpy(s->name, name, SLOT_NAMEMAX8);
1766 s->serial = slot_serial++;
1767 for (i = 0; unit[i] != NULL((void*)0); i++)
1768 ; /* nothing */
1769 s->unit = i;
1770 s->id = id;
1771 s->opt = opt;
1772 slot_ctlname(s, ctl_name, CTL_NAMEMAX16);
1773 ctl_new(CTL_SLOT_LEVEL3, s, NULL((void*)0),
1774 CTL_NUM2, "app", ctl_name, -1, "level",
1775 NULL((void*)0), -1, 127, s->vol);
1776
1777found:
1778 /* open device, this may change opt's device */
1779 if (!opt_ref(s->opt))
1780 return NULL((void*)0);
1781 s->opt = opt;
1782 s->ops = ops;
1783 s->arg = arg;
1784 s->pstate = SLOT_INIT0;
1785 s->mode = mode;
1786 aparams_init(&s->par);
1787 if (s->mode & MODE_PLAY0x01)
1788 s->mix.nch = s->opt->pmax - s->opt->pmin + 1;
1789 if (s->mode & MODE_RECMASK(0x02 | 0x10))
1790 s->sub.nch = s->opt->rmax - s->opt->rmin + 1;
1791 s->xrun = s->opt->mtc != NULL((void*)0) ? XRUN_SYNC1 : XRUN_IGNORE0;
1792 s->appbufsz = s->opt->dev->bufsz;
1793 s->round = s->opt->dev->round;
1794 s->rate = s->opt->dev->rate;
1795 dev_midi_slotdesc(s->opt->dev, s);
1796 dev_midi_vol(s->opt->dev, s);
1797#ifdef DEBUG1
1798 if (log_level >= 3) {
1799 slot_log(s);
1800 log_puts(": using ");
1801 log_puts(s->opt->name);
1802 log_puts(", mode = ");
1803 log_putx(mode);
1804 log_puts("\n");
1805 }
1806#endif
1807 return s;
1808}
1809
1810/*
1811 * release the given slot
1812 */
1813void
1814slot_del(struct slot *s)
1815{
1816 s->arg = s;
1817 s->ops = &zomb_slotops;
1818 switch (s->pstate) {
1819 case SLOT_INIT0:
1820 s->ops = NULL((void*)0);
1821 break;
1822 case SLOT_START1:
1823 case SLOT_READY2:
1824 case SLOT_RUN3:
1825 case SLOT_STOP4:
1826 slot_stop(s, 0);
1827 break;
1828 }
1829 opt_unref(s->opt);
1830}
1831
1832/*
1833 * change the slot play volume; called either by the slot or by MIDI
1834 */
1835void
1836slot_setvol(struct slot *s, unsigned int vol)
1837{
1838#ifdef DEBUG1
1839 if (log_level >= 3) {
1840 slot_log(s);
1841 log_puts(": setting volume ");
1842 log_putu(vol);
1843 log_puts("\n");
1844 }
1845#endif
1846 s->vol = vol;
1847 s->mix.vol = MIDI_TO_ADATA(s->vol)(aparams_ctltovol[s->vol] << (16 - 16));
1848}
1849
1850/*
1851 * set device for this slot
1852 */
1853void
1854slot_setopt(struct slot *s, struct opt *o)
1855{
1856 struct opt *t;
1857 struct dev *odev, *ndev;
1858 struct ctl *c;
1859
1860 if (s->opt == NULL((void*)0) || s->opt == o)
1861 return;
1862
1863 if (log_level >= 2) {
1864 slot_log(s);
1865 log_puts(": moving to opt ");
1866 log_puts(o->name);
1867 log_puts("\n");
1868 }
1869
1870 odev = s->opt->dev;
1871 if (s->ops != NULL((void*)0)) {
1872 ndev = opt_ref(o);
1873 if (ndev == NULL((void*)0))
1874 return;
1875
1876 if (!dev_iscompat(odev, ndev)) {
1877 opt_unref(o);
1878 return;
1879 }
1880 }
1881
1882 if (s->pstate == SLOT_RUN3 || s->pstate == SLOT_STOP4)
1883 slot_detach(s);
1884
1885 t = s->opt;
1886 s->opt = o;
1887
1888 c = ctl_find(CTL_SLOT_LEVEL3, s, NULL((void*)0));
1889 ctl_update(c);
1890
1891 if (o->dev != t->dev) {
1892 dev_midi_slotdesc(odev, s);
1893 dev_midi_slotdesc(ndev, s);
1894 dev_midi_vol(ndev, s);
1895 }
1896
1897 if (s->pstate == SLOT_RUN3 || s->pstate == SLOT_STOP4)
1898 slot_attach(s);
1899
1900 if (s->ops != NULL((void*)0)) {
1901 opt_unref(t);
1902 return;
1903 }
1904}
1905
1906/*
1907 * attach the slot to the device (ie start playing & recording
1908 */
1909void
1910slot_attach(struct slot *s)
1911{
1912 struct dev *d = s->opt->dev;
1913 long long pos;
1914
1915 if (((s->mode & MODE_PLAY0x01) && !(s->opt->mode & MODE_PLAY0x01)) ||
12
Assuming the condition is false
1916 ((s->mode & MODE_RECMASK(0x02 | 0x10)) && !(s->opt->mode & MODE_RECMASK(0x02 | 0x10)))) {
13
Assuming the condition is false
1917 if (log_level >= 1) {
1918 slot_log(s);
1919 log_puts(" at ");
1920 log_puts(s->opt->name);
1921 log_puts(": mode not allowed on this sub-device\n");
1922 }
1923 }
1924
1925 /*
1926 * setup converions layer
1927 */
1928 slot_initconv(s);
1929
1930 /*
1931 * start the device if not started
1932 */
1933 dev_wakeup(d);
14
Calling 'dev_wakeup'
18
Returning from 'dev_wakeup'
1934
1935 /*
1936 * adjust initial clock
1937 */
1938 pos = s->delta_rem +
1939 (long long)s->delta * d->round +
1940 (long long)d->delta * s->round;
1941 s->delta = pos / (int)d->round;
1942 s->delta_rem = pos % d->round;
1943 if (s->delta_rem < 0) {
19
Assuming field 'delta_rem' is >= 0
20
Taking false branch
1944 s->delta_rem += d->round;
1945 s->delta--;
1946 }
1947
1948#ifdef DEBUG1
1949 if (log_level >= 2) {
21
Assuming 'log_level' is >= 2
22
Taking true branch
1950 slot_log(s);
1951 log_puts(": attached at ");
1952 log_puti(s->delta);
1953 log_puts(" + ");
1954 log_puti(s->delta_rem);
1955 log_puts("/");
1956 log_puti(s->round);
1957 log_puts("\n");
1958 }
1959#endif
1960
1961 /*
1962 * We dont check whether the device is dying,
1963 * because dev_xxx() functions are supposed to
1964 * work (i.e., not to crash)
1965 */
1966
1967 s->next = d->slot_list;
1968 d->slot_list = s;
1969 if (s->mode & MODE_PLAY0x01) {
23
Assuming the condition is true
24
Taking true branch
1970 s->mix.vol = MIDI_TO_ADATA(s->vol)(aparams_ctltovol[s->vol] << (16 - 16));
1971 dev_mix_adjvol(d);
25
Calling 'dev_mix_adjvol'
1972 }
1973}
1974
1975/*
1976 * if MMC is enabled, and try to attach all slots synchronously, else
1977 * simply attach the slot
1978 */
1979void
1980slot_ready(struct slot *s)
1981{
1982 /*
1983 * device may be disconnected, and if so we're called from
1984 * slot->ops->exit() on a closed device
1985 */
1986 if (s->opt->dev->pstate == DEV_CFG0)
7
Assuming field 'pstate' is not equal to DEV_CFG
8
Taking false branch
1987 return;
1988 if (s->opt->mtc == NULL((void*)0)) {
9
Assuming field 'mtc' is equal to NULL
10
Taking true branch
1989 slot_attach(s);
11
Calling 'slot_attach'
1990 s->pstate = SLOT_RUN3;
1991 } else
1992 mtc_trigger(s->opt->mtc);
1993}
1994
1995/*
1996 * setup buffers & conversion layers, prepare the slot to receive data
1997 * (for playback) or start (recording).
1998 */
1999void
2000slot_start(struct slot *s)
2001{
2002 struct dev *d = s->opt->dev;
2003#ifdef DEBUG1
2004 if (s->pstate != SLOT_INIT0) {
2005 slot_log(s);
2006 log_puts(": slot_start: wrong state\n");
2007 panic();
2008 }
2009 if (s->mode & MODE_PLAY0x01) {
2010 if (log_level >= 3) {
2011 slot_log(s);
2012 log_puts(": playing ");
2013 aparams_log(&s->par);
2014 log_puts(" -> ");
2015 aparams_log(&d->par);
2016 log_puts("\n");
2017 }
2018 }
2019 if (s->mode & MODE_RECMASK(0x02 | 0x10)) {
2020 if (log_level >= 3) {
2021 slot_log(s);
2022 log_puts(": recording ");
2023 aparams_log(&s->par);
2024 log_puts(" <- ");
2025 aparams_log(&d->par);
2026 log_puts("\n");
2027 }
2028 }
2029#endif
2030 slot_allocbufs(s);
2031
2032 if (s->mode & MODE_RECMASK(0x02 | 0x10)) {
2033 /*
2034 * N-th recorded block is the N-th played block
2035 */
2036 s->sub.prime = d->bufsz / d->round;
2037 }
2038 s->skip = 0;
2039
2040 /*
2041 * get the current position, the origin is when the first sample
2042 * played and/or recorded
2043 */
2044 s->delta = -(long long)d->bufsz * s->round / d->round;
2045 s->delta_rem = 0;
2046
2047 if (s->mode & MODE_PLAY0x01) {
2048 s->pstate = SLOT_START1;
2049 } else {
2050 s->pstate = SLOT_READY2;
2051 slot_ready(s);
2052 }
2053}
2054
2055/*
2056 * stop playback and recording, and free conversion layers
2057 */
2058void
2059slot_detach(struct slot *s)
2060{
2061 struct slot **ps;
2062 struct dev *d = s->opt->dev;
2063 long long pos;
2064
2065 for (ps = &d->slot_list; *ps != s; ps = &(*ps)->next) {
2066#ifdef DEBUG1
2067 if (*ps == NULL((void*)0)) {
2068 slot_log(s);
2069 log_puts(": can't detach, not on list\n");
2070 panic();
2071 }
2072#endif
2073 }
2074 *ps = s->next;
2075
2076 /*
2077 * adjust clock, go back d->delta ticks so that slot_attach()
2078 * could be called with the resulting state
2079 */
2080 pos = s->delta_rem +
2081 (long long)s->delta * d->round -
2082 (long long)d->delta * s->round;
2083 s->delta = pos / (int)d->round;
2084 s->delta_rem = pos % d->round;
2085 if (s->delta_rem < 0) {
2086 s->delta_rem += d->round;
2087 s->delta--;
2088 }
2089
2090#ifdef DEBUG1
2091 if (log_level >= 2) {
2092 slot_log(s);
2093 log_puts(": detached at ");
2094 log_puti(s->delta);
2095 log_puts(" + ");
2096 log_puti(s->delta_rem);
2097 log_puts("/");
2098 log_puti(d->round);
2099 log_puts("\n");
2100 }
2101#endif
2102 if (s->mode & MODE_PLAY0x01)
2103 dev_mix_adjvol(d);
2104
2105 if (s->mode & MODE_RECMASK(0x02 | 0x10)) {
2106 if (s->sub.encbuf) {
2107 xfree(s->sub.encbuf);
2108 s->sub.encbuf = NULL((void*)0);
2109 }
2110 if (s->sub.resampbuf) {
2111 xfree(s->sub.resampbuf);
2112 s->sub.resampbuf = NULL((void*)0);
2113 }
2114 }
2115
2116 if (s->mode & MODE_PLAY0x01) {
2117 if (s->mix.decbuf) {
2118 xfree(s->mix.decbuf);
2119 s->mix.decbuf = NULL((void*)0);
2120 }
2121 if (s->mix.resampbuf) {
2122 xfree(s->mix.resampbuf);
2123 s->mix.resampbuf = NULL((void*)0);
2124 }
2125 }
2126}
2127
2128/*
2129 * put the slot in stopping state (draining play buffers) or
2130 * stop & detach if no data to drain.
2131 */
2132void
2133slot_stop(struct slot *s, int drain)
2134{
2135#ifdef DEBUG1
2136 if (log_level >= 3) {
2137 slot_log(s);
2138 log_puts(": stopping\n");
2139 }
2140#endif
2141 if (s->pstate == SLOT_START1) {
2142 /*
2143 * If in rec-only mode, we're already in the READY or
2144 * RUN states. We're here because the play buffer was
2145 * not full enough, try to start so it's drained.
2146 */
2147 s->pstate = SLOT_READY2;
2148 slot_ready(s);
2149 }
2150
2151 if (s->pstate == SLOT_RUN3) {
2152 if ((s->mode & MODE_PLAY0x01) && drain) {
2153 /*
2154 * Don't detach, dev_cycle() will do it for us
2155 * when the buffer is drained.
2156 */
2157 s->pstate = SLOT_STOP4;
2158 return;
2159 }
2160 slot_detach(s);
2161 } else if (s->pstate == SLOT_STOP4) {
2162 slot_detach(s);
2163 } else {
2164#ifdef DEBUG1
2165 if (log_level >= 3) {
2166 slot_log(s);
2167 log_puts(": not drained (blocked by mmc)\n");
2168 }
2169#endif
2170 }
2171
2172 s->pstate = SLOT_INIT0;
2173 s->ops->eof(s->arg);
2174 slot_freebufs(s);
2175}
2176
2177void
2178slot_skip_update(struct slot *s)
2179{
2180 int skip;
2181
2182 skip = slot_skip(s);
2183 while (skip > 0) {
2184#ifdef DEBUG1
2185 if (log_level >= 4) {
2186 slot_log(s);
2187 log_puts(": catching skipped block\n");
2188 }
2189#endif
2190 if (s->mode & MODE_RECMASK(0x02 | 0x10))
2191 s->ops->flush(s->arg);
2192 if (s->mode & MODE_PLAY0x01)
2193 s->ops->fill(s->arg);
2194 skip--;
2195 }
2196}
2197
2198/*
2199 * notify the slot that we just wrote in the play buffer, must be called
2200 * after each write
2201 */
2202void
2203slot_write(struct slot *s)
2204{
2205 if (s->pstate == SLOT_START1 && s->mix.buf.used == s->mix.buf.len) {
1
Assuming field 'pstate' is equal to SLOT_START
2
Assuming field 'used' is equal to field 'len'
3
Taking true branch
2206#ifdef DEBUG1
2207 if (log_level >= 4) {
4
Assuming 'log_level' is < 4
5
Taking false branch
2208 slot_log(s);
2209 log_puts(": switching to READY state\n");
2210 }
2211#endif
2212 s->pstate = SLOT_READY2;
2213 slot_ready(s);
6
Calling 'slot_ready'
2214 }
2215 slot_skip_update(s);
2216}
2217
2218/*
2219 * notify the slot that we freed some space in the rec buffer
2220 */
2221void
2222slot_read(struct slot *s)
2223{
2224 slot_skip_update(s);
2225}
2226
2227/*
2228 * allocate at control slot
2229 */
2230struct ctlslot *
2231ctlslot_new(struct opt *o, struct ctlops *ops, void *arg)
2232{
2233 struct ctlslot *s;
2234 struct ctl *c;
2235 int i;
2236
2237 i = 0;
2238 for (;;) {
2239 if (i == DEV_NCTLSLOT8)
2240 return NULL((void*)0);
2241 s = ctlslot_array + i;
2242 if (s->ops == NULL((void*)0))
2243 break;
2244 i++;
2245 }
2246 s->opt = o;
2247 s->self = 1 << i;
2248 if (!opt_ref(o))
2249 return NULL((void*)0);
2250 s->ops = ops;
2251 s->arg = arg;
2252 for (c = ctl_list; c != NULL((void*)0); c = c->next) {
2253 if (!ctlslot_visible(s, c))
2254 continue;
2255 c->refs_mask |= s->self;
2256 }
2257 return s;
2258}
2259
2260/*
2261 * free control slot
2262 */
2263void
2264ctlslot_del(struct ctlslot *s)
2265{
2266 struct ctl *c, **pc;
2267
2268 pc = &ctl_list;
2269 while ((c = *pc) != NULL((void*)0)) {
2270 c->refs_mask &= ~s->self;
2271 if (c->refs_mask == 0) {
2272 *pc = c->next;
2273 xfree(c);
2274 } else
2275 pc = &c->next;
2276 }
2277 s->ops = NULL((void*)0);
2278 opt_unref(s->opt);
2279}
2280
2281int
2282ctlslot_visible(struct ctlslot *s, struct ctl *c)
2283{
2284 if (s->opt == NULL((void*)0))
2285 return 1;
2286 switch (c->scope) {
2287 case CTL_HW0:
2288 case CTL_DEV_MASTER1:
2289 return (s->opt->dev == c->u.any.arg0);
2290 case CTL_OPT_DEV2:
2291 return (s->opt == c->u.any.arg0);
2292 case CTL_SLOT_LEVEL3:
2293 return (s->opt->dev == c->u.slot_level.slot->opt->dev);
2294 default:
2295 return 0;
2296 }
2297}
2298
2299struct ctl *
2300ctlslot_lookup(struct ctlslot *s, int addr)
2301{
2302 struct ctl *c;
2303
2304 c = ctl_list;
2305 while (1) {
2306 if (c == NULL((void*)0))
2307 return NULL((void*)0);
2308 if (c->type != CTL_NONE0 && c->addr == addr)
2309 break;
2310 c = c->next;
2311 }
2312 if (!ctlslot_visible(s, c))
2313 return NULL((void*)0);
2314 return c;
2315}
2316
2317void
2318ctlslot_update(struct ctlslot *s)
2319{
2320 struct ctl *c;
2321 unsigned int refs_mask;
2322
2323 for (c = ctl_list; c != NULL((void*)0); c = c->next) {
2324 if (c->type == CTL_NONE0)
2325 continue;
2326 refs_mask = ctlslot_visible(s, c) ? s->self : 0;
2327
2328 /* nothing to do if no visibility change */
2329 if (((c->refs_mask & s->self) ^ refs_mask) == 0)
2330 continue;
2331 /* if control becomes visble */
2332 if (refs_mask)
2333 c->refs_mask |= s->self;
2334 /* if control is hidden */
2335 c->desc_mask |= s->self;
2336 }
2337}
2338
2339void
2340ctl_node_log(struct ctl_node *c)
2341{
2342 log_puts(c->name);
2343 if (c->unit >= 0)
2344 log_putu(c->unit);
2345}
2346
2347void
2348ctl_log(struct ctl *c)
2349{
2350 if (c->group[0] != 0) {
2351 log_puts(c->group);
2352 log_puts("/");
2353 }
2354 ctl_node_log(&c->node0);
2355 log_puts(".");
2356 log_puts(c->func);
2357 log_puts("=");
2358 switch (c->type) {
2359 case CTL_NONE0:
2360 log_puts("none");
2361 break;
2362 case CTL_NUM2:
2363 case CTL_SW3:
2364 log_putu(c->curval);
2365 break;
2366 case CTL_VEC4:
2367 case CTL_LIST5:
2368 case CTL_SEL6:
2369 ctl_node_log(&c->node1);
2370 log_puts(":");
2371 log_putu(c->curval);
2372 }
2373 log_puts(" at ");
2374 log_putu(c->addr);
2375 log_puts(" -> ");
2376 switch (c->scope) {
2377 case CTL_HW0:
2378 log_puts("hw:");
2379 log_puts(c->u.hw.dev->name);
2380 log_puts("/");
2381 log_putu(c->u.hw.addr);
2382 break;
2383 case CTL_DEV_MASTER1:
2384 log_puts("dev_master:");
2385 log_puts(c->u.dev_master.dev->name);
2386 break;
2387 case CTL_SLOT_LEVEL3:
2388 log_puts("slot_level:");
2389 log_puts(c->u.slot_level.slot->name);
2390 log_putu(c->u.slot_level.slot->unit);
2391 break;
2392 case CTL_OPT_DEV2:
2393 log_puts("opt_dev:");
2394 log_puts(c->u.opt_dev.opt->name);
2395 log_puts("/");
2396 log_puts(c->u.opt_dev.dev->name);
2397 break;
2398 default:
2399 log_puts("unknown");
2400 }
2401}
2402
2403int
2404ctl_setval(struct ctl *c, int val)
2405{
2406 if (c->curval == val) {
2407 if (log_level >= 3) {
2408 ctl_log(c);
2409 log_puts(": already set\n");
2410 }
2411 return 1;
2412 }
2413 if (val < 0 || val > c->maxval) {
2414 if (log_level >= 3) {
2415 log_putu(val);
2416 log_puts(": ctl val out of bounds\n");
2417 }
2418 return 0;
2419 }
2420
2421 switch (c->scope) {
2422 case CTL_HW0:
2423 if (log_level >= 3) {
2424 ctl_log(c);
2425 log_puts(": marked as dirty\n");
2426 }
2427 c->curval = val;
2428 c->dirty = 1;
2429 return dev_ref(c->u.hw.dev);
2430 case CTL_DEV_MASTER1:
2431 if (!c->u.dev_master.dev->master_enabled)
2432 return 1;
2433 dev_master(c->u.dev_master.dev, val);
2434 dev_midi_master(c->u.dev_master.dev);
2435 c->val_mask = ~0U;
2436 c->curval = val;
2437 return 1;
2438 case CTL_SLOT_LEVEL3:
2439 slot_setvol(c->u.slot_level.slot, val);
2440 // XXX change dev_midi_vol() into slot_midi_vol()
2441 dev_midi_vol(c->u.slot_level.slot->opt->dev, c->u.slot_level.slot);
2442 c->val_mask = ~0U;
2443 c->curval = val;
2444 return 1;
2445 case CTL_OPT_DEV2:
2446 c->u.opt_dev.opt->alt_first = c->u.opt_dev.dev;
2447 opt_setdev(c->u.opt_dev.opt, c->u.opt_dev.dev);
2448 return 1;
2449 default:
2450 if (log_level >= 2) {
2451 ctl_log(c);
2452 log_puts(": not writable\n");
2453 }
2454 return 1;
2455 }
2456}
2457
2458/*
2459 * add a ctl
2460 */
2461struct ctl *
2462ctl_new(int scope, void *arg0, void *arg1,
2463 int type, char *gstr,
2464 char *str0, int unit0, char *func,
2465 char *str1, int unit1, int maxval, int val)
2466{
2467 struct ctl *c, **pc;
2468 struct ctlslot *s;
2469 int addr;
2470 int i;
2471
2472 /*
2473 * find the smallest unused addr number and
2474 * the last position in the list
2475 */
2476 addr = 0;
2477 for (pc = &ctl_list; (c = *pc) != NULL((void*)0); pc = &c->next) {
2478 if (c->addr > addr)
2479 addr = c->addr;
2480 }
2481 addr++;
2482
2483 c = xmalloc(sizeof(struct ctl));
2484 c->type = type;
2485 strlcpy(c->func, func, CTL_NAMEMAX16);
2486 strlcpy(c->group, gstr, CTL_NAMEMAX16);
2487 strlcpy(c->node0.name, str0, CTL_NAMEMAX16);
2488 c->node0.unit = unit0;
2489 if (c->type == CTL_VEC4 || c->type == CTL_LIST5 || c->type == CTL_SEL6) {
2490 strlcpy(c->node1.name, str1, CTL_NAMEMAX16);
2491 c->node1.unit = unit1;
2492 } else
2493 memset(&c->node1, 0, sizeof(struct ctl_node));
2494 c->scope = scope;
2495 c->u.any.arg0 = arg0;
2496 switch (scope) {
2497 case CTL_HW0:
2498 c->u.hw.addr = *(unsigned int *)arg1;
2499 break;
2500 case CTL_OPT_DEV2:
2501 c->u.any.arg1 = arg1;
2502 break;
2503 default:
2504 c->u.any.arg1 = NULL((void*)0);
2505 }
2506 c->addr = addr;
2507 c->maxval = maxval;
2508 c->val_mask = ~0;
2509 c->desc_mask = ~0;
2510 c->curval = val;
2511 c->dirty = 0;
2512 c->refs_mask = CTL_DEVMASK(1 << 31);
2513 for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT8; i++, s++) {
2514 if (s->ops == NULL((void*)0))
2515 continue;
2516 if (ctlslot_visible(s, c))
2517 c->refs_mask |= 1 << i;
2518 }
2519 c->next = *pc;
2520 *pc = c;
2521#ifdef DEBUG1
2522 if (log_level >= 2) {
2523 ctl_log(c);
2524 log_puts(": added\n");
2525 }
2526#endif
2527 return c;
2528}
2529
2530void
2531ctl_update(struct ctl *c)
2532{
2533 struct ctlslot *s;
2534 unsigned int refs_mask;
2535 int i;
2536
2537 for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT8; i++, s++) {
2538 if (s->ops == NULL((void*)0))
2539 continue;
2540 refs_mask = ctlslot_visible(s, c) ? s->self : 0;
2541
2542 /* nothing to do if no visibility change */
2543 if (((c->refs_mask & s->self) ^ refs_mask) == 0)
2544 continue;
2545 /* if control becomes visble */
2546 if (refs_mask)
2547 c->refs_mask |= s->self;
2548 /* if control is hidden */
2549 c->desc_mask |= s->self;
2550 }
2551}
2552
2553int
2554ctl_match(struct ctl *c, int scope, void *arg0, void *arg1)
2555{
2556 if (c->type == CTL_NONE0 || c->scope != scope || c->u.any.arg0 != arg0)
2557 return 0;
2558 if (arg0 != NULL((void*)0) && c->u.any.arg0 != arg0)
2559 return 0;
2560 switch (scope) {
2561 case CTL_HW0:
2562 if (arg1 != NULL((void*)0) && c->u.hw.addr != *(unsigned int *)arg1)
2563 return 0;
2564 break;
2565 case CTL_OPT_DEV2:
2566 if (arg1 != NULL((void*)0) && c->u.any.arg1 != arg1)
2567 return 0;
2568 break;
2569 }
2570 return 1;
2571}
2572
2573struct ctl *
2574ctl_find(int scope, void *arg0, void *arg1)
2575{
2576 struct ctl *c;
2577
2578 for (c = ctl_list; c != NULL((void*)0); c = c->next) {
2579 if (ctl_match(c, scope, arg0, arg1))
2580 return c;
2581 }
2582 return NULL((void*)0);
2583}
2584
2585int
2586ctl_onval(int scope, void *arg0, void *arg1, int val)
2587{
2588 struct ctl *c;
2589
2590 c = ctl_find(scope, arg0, arg1);
2591 if (c == NULL((void*)0))
2592 return 0;
2593 c->curval = val;
2594 c->val_mask = ~0U;
2595 return 1;
2596}
2597
2598void
2599ctl_del(int scope, void *arg0, void *arg1)
2600{
2601 struct ctl *c, **pc;
2602
2603 pc = &ctl_list;
2604 for (;;) {
2605 c = *pc;
2606 if (c == NULL((void*)0))
2607 return;
2608 if (ctl_match(c, scope, arg0, arg1)) {
2609#ifdef DEBUG1
2610 if (log_level >= 2) {
2611 ctl_log(c);
2612 log_puts(": removed\n");
2613 }
2614#endif
2615 c->refs_mask &= ~CTL_DEVMASK(1 << 31);
2616 if (c->refs_mask == 0) {
2617 *pc = c->next;
2618 xfree(c);
2619 continue;
2620 }
2621 c->type = CTL_NONE0;
2622 c->desc_mask = ~0;
2623 }
2624 pc = &c->next;
2625 }
2626}
2627
2628void
2629dev_ctlsync(struct dev *d)
2630{
2631 struct ctl *c;
2632 struct ctlslot *s;
2633 int found, i;
2634
2635 found = 0;
2636 for (c = ctl_list; c != NULL((void*)0); c = c->next) {
2637 if (c->scope == CTL_HW0 &&
2638 c->u.hw.dev == d &&
2639 c->type == CTL_NUM2 &&
2640 strcmp(c->group, d->name) == 0 &&
2641 strcmp(c->node0.name, "output") == 0 &&
2642 strcmp(c->func, "level") == 0)
2643 found = 1;
2644 }
2645
2646 if (d->master_enabled && found) {
2647 if (log_level >= 2) {
2648 dev_log(d);
2649 log_puts(": software master level control disabled\n");
2650 }
2651 d->master_enabled = 0;
2652 ctl_del(CTL_DEV_MASTER1, d, NULL((void*)0));
2653 } else if (!d->master_enabled && !found) {
2654 if (log_level >= 2) {
2655 dev_log(d);
2656 log_puts(": software master level control enabled\n");
2657 }
2658 d->master_enabled = 1;
2659 ctl_new(CTL_DEV_MASTER1, d, NULL((void*)0),
2660 CTL_NUM2, d->name, "output", -1, "level",
2661 NULL((void*)0), -1, 127, d->master);
2662 }
2663
2664 for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT8; i++, s++) {
2665 if (s->ops == NULL((void*)0))
2666 continue;
2667 if (s->opt->dev == d)
2668 s->ops->sync(s->arg);
2669 }
2670}