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