1 /* 2 * Copyright (c) 2008-2014 Alexandre Ratchov <alex@caoua.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <err.h> 18 #include <errno.h> 19 #include <limits.h> 20 #include <poll.h> 21 #include <signal.h> 22 #include <sndio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 #include "abuf.h" 27 #include "afile.h" 28 #include "dsp.h" 29 #include "sysex.h" 30 #include "utils.h" 31 32 /* 33 * masks to extract command and channel of status byte 34 */ 35 #define MIDI_CMDMASK 0xf0 36 #define MIDI_CHANMASK 0x0f 37 38 /* 39 * MIDI status bytes of voice messages 40 */ 41 #define MIDI_NOFF 0x80 /* note off */ 42 #define MIDI_NON 0x90 /* note on */ 43 #define MIDI_KAT 0xa0 /* key after touch */ 44 #define MIDI_CTL 0xb0 /* controller */ 45 #define MIDI_PC 0xc0 /* program change */ 46 #define MIDI_CAT 0xd0 /* channel after touch */ 47 #define MIDI_BEND 0xe0 /* pitch bend */ 48 #define MIDI_ACK 0xfe /* active sensing message */ 49 50 /* 51 * MIDI controller numbers 52 */ 53 #define MIDI_CTL_VOL 7 54 55 /* 56 * Max coarse value 57 */ 58 #define MIDI_MAXCTL 127 59 60 /* 61 * MIDI status bytes for sysex 62 */ 63 #define MIDI_SX_START 0xf0 64 #define MIDI_SX_STOP 0xf7 65 66 /* 67 * audio device defaults 68 */ 69 #define DEFAULT_RATE 48000 70 #define DEFAULT_BUFSZ_MS 200 71 72 struct slot { 73 struct slot *next; /* next on the play/rec list */ 74 int vol; /* dynamic range */ 75 int volctl; /* volume in the 0..127 range */ 76 struct abuf buf; /* file i/o buffer */ 77 int bpf; /* bytes per frame */ 78 int imin, imax, omin, omax; /* channel mapping ranges */ 79 struct cmap cmap; /* channel mapper state */ 80 struct resamp resamp; /* resampler state */ 81 struct conv conv; /* format encoder state */ 82 int join; /* channel join factor */ 83 int expand; /* channel expand factor */ 84 void *resampbuf, *convbuf; /* conversion tmp buffers */ 85 int dup; /* compat with legacy -j option */ 86 int round; /* slot-side block size */ 87 int mode; /* MODE_{PLAY,REC} */ 88 #define SLOT_CFG 0 /* buffers not allocated yet */ 89 #define SLOT_INIT 1 /* not trying to do anything */ 90 #define SLOT_RUN 2 /* playing/recording */ 91 #define SLOT_STOP 3 /* draining (play only) */ 92 int pstate; /* one of above */ 93 long long skip; /* frames to skip at the beginning */ 94 long long pos; /* start position (at device rate) */ 95 struct afile afile; /* file desc & friends */ 96 }; 97 98 /* 99 * device properties 100 */ 101 unsigned int dev_mode; /* bitmap of SIO_{PLAY,REC} */ 102 unsigned int dev_bufsz; /* device buffer size */ 103 unsigned int dev_round; /* device block size */ 104 int dev_rate; /* device sample rate (Hz) */ 105 unsigned int dev_pchan, dev_rchan; /* play & rec channels count */ 106 adata_t *dev_pbuf, *dev_rbuf; /* play & rec buffers */ 107 struct aparams dev_par; /* device sample format */ 108 struct conv dev_enc, dev_dec; /* format conversions */ 109 unsigned char *dev_encbuf, *dev_decbuf; /* buf for format conversions */ 110 long long dev_pos; /* last MMC position in frames */ 111 #define DEV_STOP 0 /* stopped */ 112 #define DEV_START 1 /* started */ 113 unsigned int dev_pstate; /* one of above */ 114 char *dev_name; /* device sndio(7) name */ 115 char *dev_port; /* control port sndio(7) name */ 116 struct sio_hdl *dev_sh; /* device handle */ 117 struct mio_hdl *dev_mh; /* MIDI control port handle */ 118 unsigned int dev_volctl = MIDI_MAXCTL; /* master volume */ 119 120 /* 121 * MIDI parser state 122 */ 123 #define MIDI_MSGMAX 32 /* max size of MIDI msg */ 124 unsigned char dev_msg[MIDI_MSGMAX]; /* parsed input message */ 125 unsigned int dev_mst; /* input MIDI running status */ 126 unsigned int dev_mused; /* bytes used in ``msg'' */ 127 unsigned int dev_midx; /* current ``msg'' size */ 128 unsigned int dev_mlen; /* expected ``msg'' length */ 129 unsigned int dev_prime; /* blocks to write to start */ 130 131 unsigned int log_level = 1; 132 volatile sig_atomic_t quit_flag = 0; 133 struct slot *slot_list = NULL; 134 135 /* 136 * length of voice and common MIDI messages (status byte included) 137 */ 138 const unsigned int voice_len[] = { 3, 3, 3, 3, 2, 2, 3 }; 139 const unsigned int common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 }; 140 141 char usagestr[] = "usage: aucat [-dn] [-b size] " 142 "[-c channels] [-e enc] [-f device] [-g position]\n\t" 143 "[-h fmt] [-i file] [-m min:max/min:max] [-o file] [-p position]\n\t" 144 "[-q port] [-r rate] [-v volume]\n"; 145 146 static void * 147 allocbuf(int nfr, int nch, int bps) 148 { 149 size_t fsize; 150 151 if (nch < 0 || nch > NCHAN_MAX || bps < 0 || bps > 4) { 152 log_puts("allocbuf: bogus channels or bytes per sample count\n"); 153 panic(); 154 } 155 fsize = nch * bps; 156 return reallocarray(NULL, nfr, fsize); 157 } 158 159 static void 160 slot_log(struct slot *s) 161 { 162 #ifdef DEBUG 163 static char *pstates[] = { 164 "cfg", "ini", "run", "stp" 165 }; 166 #endif 167 log_puts(s->afile.path); 168 #ifdef DEBUG 169 if (log_level >= 3) { 170 log_puts(",pst="); 171 log_puts(pstates[s->pstate]); 172 } 173 #endif 174 } 175 176 static void 177 slot_flush(struct slot *s) 178 { 179 int count, n; 180 unsigned char *data; 181 182 for (;;) { 183 data = abuf_rgetblk(&s->buf, &count); 184 if (count == 0) 185 break; 186 n = afile_write(&s->afile, data, count); 187 if (n == 0) { 188 slot_log(s); 189 log_puts(": can't write, disabled\n"); 190 s->pstate = SLOT_INIT; 191 return; 192 } 193 abuf_rdiscard(&s->buf, n); 194 } 195 } 196 197 static void 198 slot_fill(struct slot *s) 199 { 200 int count, n; 201 unsigned char *data; 202 203 for (;;) { 204 data = abuf_wgetblk(&s->buf, &count); 205 if (count == 0) 206 break; 207 n = afile_read(&s->afile, data, count); 208 if (n == 0) { 209 #ifdef DEBUG 210 if (log_level >= 3) { 211 slot_log(s); 212 log_puts(": eof reached, stopping\n"); 213 } 214 #endif 215 s->pstate = SLOT_STOP; 216 break; 217 } 218 abuf_wcommit(&s->buf, n); 219 } 220 } 221 222 static int 223 slot_new(char *path, int mode, struct aparams *par, int hdr, 224 int imin, int imax, int omin, int omax, int nch, 225 int rate, int dup, int vol, long long pos) 226 { 227 struct slot *s, **ps; 228 229 s = xmalloc(sizeof(struct slot)); 230 if (!afile_open(&s->afile, path, hdr, 231 mode == SIO_PLAY ? AFILE_FREAD : AFILE_FWRITE, 232 par, rate, nch)) { 233 xfree(s); 234 return 0; 235 } 236 s->imin = (imin != -1) ? imin : 0; 237 s->imax = (imax != -1) ? imax : s->imin + s->afile.nch - 1; 238 s->omin = (omin != -1) ? omin : 0; 239 s->omax = (omax != -1) ? omax : s->omin + s->afile.nch - 1; 240 s->dup = dup; 241 s->vol = MIDI_TO_ADATA(vol); 242 s->mode = mode; 243 s->pstate = SLOT_CFG; 244 s->pos = pos; 245 if (log_level >= 2) { 246 slot_log(s); 247 log_puts(": "); 248 log_puts(s->mode == SIO_PLAY ? "play" : "rec"); 249 log_puts(", "); 250 log_putu(s->afile.nch); 251 log_puts("ch ("); 252 log_putu(s->imin); 253 log_puts(":"); 254 log_putu(s->imax); 255 log_puts("/"); 256 log_putu(s->omin); 257 log_puts(":"); 258 log_putu(s->omax); 259 log_puts("), "); 260 log_putu(s->afile.rate); 261 log_puts("Hz, "); 262 switch (s->afile.fmt) { 263 case AFILE_FMT_PCM: 264 aparams_log(&s->afile.par); 265 break; 266 case AFILE_FMT_ULAW: 267 log_puts("ulaw"); 268 break; 269 case AFILE_FMT_ALAW: 270 log_puts("alaw"); 271 break; 272 case AFILE_FMT_FLOAT: 273 log_puts("f32le"); 274 break; 275 } 276 if (s->mode == SIO_PLAY && s->afile.endpos >= 0) { 277 log_puts(", bytes "); 278 log_puti(s->afile.startpos); 279 log_puts(".."); 280 log_puti(s->afile.endpos); 281 } 282 if (s->mode == SIO_PLAY) { 283 log_puts(", vol "); 284 log_puti(s->vol); 285 } 286 log_puts("\n"); 287 } 288 for (ps = &slot_list; *ps != NULL; ps = &(*ps)->next) 289 ; 290 s->next = NULL; 291 *ps = s; 292 return 1; 293 } 294 295 static void 296 slot_init(struct slot *s) 297 { 298 unsigned int inch, onch, bufsz; 299 300 #ifdef DEBUG 301 if (s->pstate != SLOT_CFG) { 302 slot_log(s); 303 log_puts(": slot_init: wrong state\n"); 304 panic(); 305 } 306 #endif 307 s->bpf = s->afile.par.bps * s->afile.nch; 308 s->round = ((long long)dev_round * s->afile.rate + 309 dev_rate - 1) / dev_rate; 310 311 bufsz = s->round * (dev_bufsz / dev_round); 312 bufsz -= bufsz % s->round; 313 if (bufsz == 0) 314 bufsz = s->round; 315 abuf_init(&s->buf, bufsz * s->bpf); 316 #ifdef DEBUG 317 if (log_level >= 3) { 318 slot_log(s); 319 log_puts(": allocated "); 320 log_putu(bufsz); 321 log_puts(" frame buffer\n"); 322 } 323 #endif 324 325 s->convbuf = NULL; 326 s->resampbuf = NULL; 327 s->join = 1; 328 s->expand = 1; 329 inch = s->imax - s->imin + 1; 330 onch = s->omax - s->omin + 1; 331 if (s->dup) { 332 /* compat with legacy -j option */ 333 if (s->mode == SIO_PLAY) 334 onch = dev_pchan; 335 else 336 inch = dev_rchan; 337 } 338 if (onch > inch) 339 s->expand = onch / inch; 340 else if (onch < inch) 341 s->join = inch / onch; 342 if (s->mode & SIO_PLAY) { 343 cmap_init(&s->cmap, 344 0, s->afile.nch - 1, s->imin, s->imax, 345 0, dev_pchan - 1, s->omin, s->omax); 346 if (s->afile.fmt != AFILE_FMT_PCM || 347 !aparams_native(&s->afile.par)) { 348 dec_init(&s->conv, &s->afile.par, s->afile.nch); 349 s->convbuf = allocbuf(s->round, s->afile.nch, sizeof(adata_t)); 350 } 351 if (s->afile.rate != dev_rate) { 352 resamp_init(&s->resamp, s->afile.rate, dev_rate, 353 s->afile.nch); 354 s->resampbuf = allocbuf(dev_round, s->afile.nch, sizeof(adata_t)); 355 } 356 } 357 if (s->mode & SIO_REC) { 358 cmap_init(&s->cmap, 359 0, dev_rchan - 1, s->imin, s->imax, 360 0, s->afile.nch - 1, s->omin, s->omax); 361 if (s->afile.rate != dev_rate) { 362 resamp_init(&s->resamp, dev_rate, s->afile.rate, 363 s->afile.nch); 364 s->resampbuf = allocbuf(dev_round, s->afile.nch, sizeof(adata_t)); 365 } 366 if (!aparams_native(&s->afile.par)) { 367 enc_init(&s->conv, &s->afile.par, s->afile.nch); 368 s->convbuf = allocbuf(s->round, s->afile.nch, sizeof(adata_t)); 369 } 370 371 /* 372 * cmap_copy() doesn't write samples in all channels, 373 * for instance when mono->stereo conversion is 374 * disabled. So we have to prefill cmap_copy() output 375 * with silence. 376 */ 377 if (s->resampbuf) { 378 memset(s->resampbuf, 0, 379 dev_round * s->afile.nch * sizeof(adata_t)); 380 } else if (s->convbuf) { 381 memset(s->convbuf, 0, 382 s->round * s->afile.nch * sizeof(adata_t)); 383 } else { 384 memset(s->buf.data, 0, 385 bufsz * s->afile.nch * sizeof(adata_t)); 386 } 387 } 388 s->pstate = SLOT_INIT; 389 #ifdef DEBUG 390 if (log_level >= 3) { 391 slot_log(s); 392 log_puts(": chain initialized\n"); 393 } 394 #endif 395 } 396 397 static void 398 slot_start(struct slot *s, long long pos) 399 { 400 #ifdef DEBUG 401 if (s->pstate != SLOT_INIT) { 402 slot_log(s); 403 log_puts(": slot_start: wrong state\n"); 404 panic(); 405 } 406 #endif 407 pos -= s->pos; 408 if (pos < 0) { 409 s->skip = -pos; 410 pos = 0; 411 } else 412 s->skip = 0; 413 414 /* 415 * convert pos to slot sample rate 416 * 417 * At this stage, we could adjust s->resamp.diff to get 418 * sub-frame accuracy. 419 */ 420 pos = pos * s->afile.rate / dev_rate; 421 422 if (!afile_seek(&s->afile, pos * s->bpf)) { 423 s->pstate = SLOT_INIT; 424 return; 425 } 426 s->pstate = SLOT_RUN; 427 if (s->mode & SIO_PLAY) 428 slot_fill(s); 429 #ifdef DEBUG 430 if (log_level >= 2) { 431 slot_log(s); 432 log_puts(": started\n"); 433 } 434 #endif 435 } 436 437 static void 438 slot_stop(struct slot *s) 439 { 440 if (s->pstate == SLOT_INIT) 441 return; 442 if (s->mode & SIO_REC) 443 slot_flush(s); 444 if (s->mode & SIO_PLAY) 445 s->buf.used = s->buf.start = 0; 446 s->pstate = SLOT_INIT; 447 #ifdef DEBUG 448 if (log_level >= 2) { 449 slot_log(s); 450 log_puts(": stopped\n"); 451 } 452 #endif 453 } 454 455 static void 456 slot_del(struct slot *s) 457 { 458 struct slot **ps; 459 460 if (s->pstate != SLOT_CFG) { 461 slot_stop(s); 462 afile_close(&s->afile); 463 #ifdef DEBUG 464 if (log_level >= 3) { 465 slot_log(s); 466 log_puts(": closed\n"); 467 } 468 #endif 469 abuf_done(&s->buf); 470 if (s->resampbuf) 471 xfree(s->resampbuf); 472 if (s->convbuf) 473 xfree(s->convbuf); 474 } 475 for (ps = &slot_list; *ps != s; ps = &(*ps)->next) 476 ; /* nothing */ 477 *ps = s->next; 478 xfree(s); 479 } 480 481 static void 482 slot_getcnt(struct slot *s, int *icnt, int *ocnt) 483 { 484 int cnt; 485 486 if (s->resampbuf) 487 resamp_getcnt(&s->resamp, icnt, ocnt); 488 else { 489 cnt = (*icnt < *ocnt) ? *icnt : *ocnt; 490 *icnt = cnt; 491 *ocnt = cnt; 492 } 493 } 494 495 static void 496 play_filt_resamp(struct slot *s, void *res_in, void *out, int icnt, int ocnt) 497 { 498 int i, offs, vol, inch, onch; 499 void *in; 500 501 if (s->resampbuf) { 502 resamp_do(&s->resamp, res_in, s->resampbuf, icnt, ocnt); 503 in = s->resampbuf; 504 } else 505 in = res_in; 506 507 inch = s->imax - s->imin + 1; 508 onch = s->omax - s->omin + 1; 509 vol = s->vol / s->join; /* XXX */ 510 cmap_add(&s->cmap, in, out, vol, ocnt); 511 512 offs = 0; 513 for (i = s->join - 1; i > 0; i--) { 514 offs += onch; 515 if (offs + s->cmap.nch > s->afile.nch) 516 break; 517 cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, ocnt); 518 } 519 520 offs = 0; 521 for (i = s->expand - 1; i > 0; i--) { 522 offs += inch; 523 if (offs + s->cmap.nch > dev_pchan) 524 break; 525 cmap_add(&s->cmap, in, (adata_t *)out + offs, vol, ocnt); 526 } 527 } 528 529 static void 530 play_filt_dec(struct slot *s, void *in, void *out, int icnt, int ocnt) 531 { 532 void *tmp; 533 534 tmp = s->convbuf; 535 if (tmp) { 536 switch (s->afile.fmt) { 537 case AFILE_FMT_PCM: 538 dec_do(&s->conv, in, tmp, icnt); 539 break; 540 case AFILE_FMT_ULAW: 541 dec_do_ulaw(&s->conv, in, tmp, icnt, 0); 542 break; 543 case AFILE_FMT_ALAW: 544 dec_do_ulaw(&s->conv, in, tmp, icnt, 1); 545 break; 546 case AFILE_FMT_FLOAT: 547 dec_do_float(&s->conv, in, tmp, icnt); 548 break; 549 } 550 } else 551 tmp = in; 552 play_filt_resamp(s, tmp, out, icnt, ocnt); 553 } 554 555 /* 556 * Mix as many as possible frames (but not more than a block) from the 557 * slot buffer to the given location. Return the number of frames mixed 558 * in the output buffer 559 */ 560 static int 561 slot_mix_badd(struct slot *s, adata_t *odata) 562 { 563 adata_t *idata; 564 int len, icnt, ocnt, otodo, odone; 565 566 odone = 0; 567 otodo = dev_round; 568 if (s->skip > 0) { 569 ocnt = otodo; 570 if (ocnt > s->skip) 571 ocnt = s->skip; 572 s->skip -= ocnt; 573 odata += dev_pchan * ocnt; 574 otodo -= ocnt; 575 odone += ocnt; 576 } 577 while (otodo > 0) { 578 idata = (adata_t *)abuf_rgetblk(&s->buf, &len); 579 icnt = len / s->bpf; 580 if (icnt > s->round) 581 icnt = s->round; 582 ocnt = otodo; 583 slot_getcnt(s, &icnt, &ocnt); 584 if (icnt == 0) 585 break; 586 play_filt_dec(s, idata, odata, icnt, ocnt); 587 abuf_rdiscard(&s->buf, icnt * s->bpf); 588 otodo -= ocnt; 589 odone += ocnt; 590 odata += ocnt * dev_pchan; 591 } 592 return odone; 593 } 594 595 static void 596 rec_filt_resamp(struct slot *s, void *in, void *res_out, int icnt, int ocnt) 597 { 598 int i, vol, offs, inch, onch; 599 void *out = res_out; 600 601 out = (s->resampbuf) ? s->resampbuf : res_out; 602 603 inch = s->imax - s->imin + 1; 604 onch = s->omax - s->omin + 1; 605 vol = ADATA_UNIT / s->join; 606 cmap_copy(&s->cmap, in, out, vol, icnt); 607 608 offs = 0; 609 for (i = s->join - 1; i > 0; i--) { 610 offs += onch; 611 if (offs + s->cmap.nch > dev_rchan) 612 break; 613 cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, icnt); 614 } 615 offs = 0; 616 for (i = s->expand - 1; i > 0; i--) { 617 offs += inch; 618 if (offs + s->cmap.nch > s->afile.nch) 619 break; 620 cmap_copy(&s->cmap, in, (adata_t *)out + offs, vol, icnt); 621 } 622 if (s->resampbuf) 623 resamp_do(&s->resamp, s->resampbuf, res_out, icnt, ocnt); 624 else 625 ocnt = icnt; 626 } 627 628 static void 629 rec_filt_enc(struct slot *s, void *in, void *out, int icnt, int ocnt) 630 { 631 void *tmp; 632 633 tmp = s->convbuf; 634 rec_filt_resamp(s, in, tmp ? tmp : out, icnt, ocnt); 635 if (tmp) 636 enc_do(&s->conv, tmp, out, ocnt); 637 } 638 639 /* 640 * Copy "todo" frames from the given buffer to the slot buffer, 641 * but not more than a block. 642 */ 643 static void 644 slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo) 645 { 646 adata_t *odata; 647 int len, icnt, ocnt; 648 649 if (s->skip > 0) { 650 icnt = itodo; 651 if (icnt > s->skip) 652 icnt = s->skip; 653 s->skip -= icnt; 654 idata += dev_rchan * icnt; 655 itodo -= icnt; 656 } 657 658 while (itodo > 0) { 659 odata = (adata_t *)abuf_wgetblk(&s->buf, &len); 660 ocnt = len / s->bpf; 661 if (ocnt > s->round) 662 ocnt = s->round; 663 icnt = itodo; 664 slot_getcnt(s, &icnt, &ocnt); 665 if (ocnt == 0) 666 break; 667 rec_filt_enc(s, idata, odata, icnt, ocnt); 668 abuf_wcommit(&s->buf, ocnt * s->bpf); 669 itodo -= icnt; 670 idata += icnt * dev_rchan; 671 } 672 } 673 674 static int 675 dev_open(char *dev, int mode, int bufsz, char *port) 676 { 677 int rate, pmax, rmax; 678 struct sio_par par; 679 char encstr[ENCMAX]; 680 struct slot *s; 681 682 if (port) { 683 dev_port = port; 684 dev_mh = mio_open(dev_port, MIO_IN, 0); 685 if (dev_mh == NULL) { 686 log_puts(port); 687 log_puts(": couldn't open midi port\n"); 688 return 0; 689 } 690 } else 691 dev_mh = NULL; 692 693 dev_name = dev; 694 dev_sh = sio_open(dev, mode, 0); 695 if (dev_sh == NULL) { 696 log_puts(dev_name); 697 log_puts(": couldn't open audio device\n"); 698 return 0; 699 } 700 701 rate = pmax = rmax = 0; 702 for (s = slot_list; s != NULL; s = s->next) { 703 if (s->afile.rate > rate) 704 rate = s->afile.rate; 705 if (s->mode == SIO_PLAY) { 706 if (s->omax > pmax) 707 pmax = s->omax; 708 } 709 if (s->mode == SIO_REC) { 710 if (s->imax > rmax) 711 rmax = s->imax; 712 } 713 } 714 sio_initpar(&par); 715 par.bits = ADATA_BITS; 716 par.bps = sizeof(adata_t); 717 par.msb = 0; 718 par.le = SIO_LE_NATIVE; 719 par.rate = rate; 720 if (mode & SIO_PLAY) 721 par.pchan = pmax + 1; 722 if (mode & SIO_REC) 723 par.rchan = rmax + 1; 724 par.appbufsz = bufsz > 0 ? bufsz : rate * DEFAULT_BUFSZ_MS / 1000; 725 if (!sio_setpar(dev_sh, &par) || !sio_getpar(dev_sh, &par)) { 726 log_puts(dev_name); 727 log_puts(": couldn't set audio params\n"); 728 return 0; 729 } 730 dev_par.bits = par.bits; 731 dev_par.bps = par.bps; 732 dev_par.sig = par.sig; 733 dev_par.le = par.le; 734 dev_par.msb = par.msb; 735 dev_mode = mode; 736 dev_rate = par.rate; 737 dev_bufsz = par.bufsz; 738 dev_round = par.round; 739 if (mode & SIO_PLAY) { 740 dev_pchan = par.pchan; 741 dev_pbuf = allocbuf(dev_round, dev_pchan, sizeof(adata_t)); 742 } 743 if (mode & SIO_REC) { 744 dev_rchan = par.rchan; 745 dev_rbuf = allocbuf(dev_round, dev_rchan, sizeof(adata_t)); 746 } 747 if (!aparams_native(&dev_par)) { 748 if (mode & SIO_PLAY) { 749 dev_encbuf = allocbuf(dev_round, dev_pchan, dev_par.bps); 750 enc_init(&dev_enc, &dev_par, dev_pchan); 751 } 752 if (mode & SIO_REC) { 753 dev_decbuf = allocbuf(dev_round, dev_rchan, dev_par.bps); 754 dec_init(&dev_dec, &dev_par, dev_rchan); 755 } 756 } 757 dev_pstate = DEV_STOP; 758 if (log_level >= 2) { 759 log_puts(dev_name); 760 log_puts(": "); 761 log_putu(dev_rate); 762 log_puts("Hz, "); 763 aparams_enctostr(&dev_par, encstr); 764 log_puts(encstr); 765 if (dev_mode & SIO_PLAY) { 766 log_puts(", play 0:"); 767 log_puti(dev_pchan - 1); 768 } 769 if (dev_mode & SIO_REC) { 770 log_puts(", rec 0:"); 771 log_puti(dev_rchan - 1); 772 } 773 log_puts(", "); 774 log_putu(dev_bufsz / dev_round); 775 log_puts(" blocks of "); 776 log_putu(dev_round); 777 log_puts(" frames\n"); 778 } 779 return 1; 780 } 781 782 static void 783 dev_close(void) 784 { 785 sio_close(dev_sh); 786 if (dev_mh) 787 mio_close(dev_mh); 788 if (dev_mode & SIO_PLAY) 789 xfree(dev_pbuf); 790 if (dev_mode & SIO_REC) 791 xfree(dev_rbuf); 792 } 793 794 static void 795 dev_master(int val) 796 { 797 struct slot *s; 798 int mastervol, slotvol; 799 800 mastervol = MIDI_TO_ADATA(dev_volctl); 801 for (s = slot_list; s != NULL; s = s->next) { 802 slotvol = MIDI_TO_ADATA(val); 803 s->vol = ADATA_MUL(mastervol, slotvol); 804 } 805 #ifdef DEBUG 806 if (log_level >= 3) { 807 log_puts("master volume set to "); 808 log_putu(val); 809 log_puts("\n"); 810 } 811 #endif 812 } 813 814 static void 815 dev_slotvol(int midich, int val) 816 { 817 struct slot *s; 818 int mastervol, slotvol; 819 820 for (s = slot_list; s != NULL; s = s->next) { 821 if (midich == 0) { 822 mastervol = MIDI_TO_ADATA(dev_volctl); 823 slotvol = MIDI_TO_ADATA(val); 824 s->vol = ADATA_MUL(mastervol, slotvol); 825 #ifdef DEBUG 826 if (log_level >= 3) { 827 slot_log(s); 828 log_puts(": volume set to "); 829 log_putu(val); 830 log_puts("\n"); 831 } 832 #endif 833 break; 834 } 835 midich--; 836 } 837 } 838 839 /* 840 * start all slots simultaneously 841 */ 842 static void 843 dev_mmcstart(void) 844 { 845 struct slot *s; 846 847 if (dev_pstate == DEV_STOP) { 848 dev_pstate = DEV_START; 849 for (s = slot_list; s != NULL; s = s->next) 850 slot_start(s, dev_pos); 851 dev_prime = (dev_mode & SIO_PLAY) ? dev_bufsz / dev_round : 0; 852 sio_start(dev_sh); 853 if (log_level >= 2) 854 log_puts("started\n"); 855 } else { 856 #ifdef DEBUG 857 if (log_level >= 3) 858 log_puts("ignoring mmc start\n"); 859 #endif 860 } 861 } 862 863 /* 864 * stop all slots simultaneously 865 */ 866 static void 867 dev_mmcstop(void) 868 { 869 struct slot *s; 870 871 if (dev_pstate == DEV_START) { 872 dev_pstate = DEV_STOP; 873 for (s = slot_list; s != NULL; s = s->next) 874 slot_stop(s); 875 sio_stop(dev_sh); 876 if (log_level >= 2) 877 log_puts("stopped\n"); 878 } else { 879 #ifdef DEBUG 880 if (log_level >= 3) 881 log_puts("ignored mmc stop\n"); 882 #endif 883 } 884 } 885 886 /* 887 * relocate all slots simultaneously 888 */ 889 static void 890 dev_mmcloc(int hr, int min, int sec, int fr, int cent, int fps) 891 { 892 long long pos; 893 894 pos = (long long)dev_rate * hr * 3600 + 895 (long long)dev_rate * min * 60 + 896 (long long)dev_rate * sec + 897 (long long)dev_rate * fr / fps + 898 (long long)dev_rate * cent / (100 * fps); 899 if (dev_pos == pos) 900 return; 901 dev_pos = pos; 902 if (log_level >= 2) { 903 log_puts("relocated to "); 904 log_putu(hr); 905 log_puts(":"); 906 log_putu(min); 907 log_puts(":"); 908 log_putu(sec); 909 log_puts("."); 910 log_putu(fr); 911 log_puts("."); 912 log_putu(cent); 913 log_puts(" at "); 914 log_putu(fps); 915 log_puts("fps\n"); 916 } 917 if (dev_pstate == DEV_START) { 918 dev_mmcstop(); 919 dev_mmcstart(); 920 } 921 } 922 923 static void 924 dev_imsg(unsigned char *msg, unsigned int len) 925 { 926 struct sysex *x; 927 unsigned int fps, chan; 928 929 if ((msg[0] & MIDI_CMDMASK) == MIDI_CTL && msg[1] == MIDI_CTL_VOL) { 930 chan = msg[0] & MIDI_CHANMASK; 931 dev_slotvol(chan, msg[2]); 932 return; 933 } 934 x = (struct sysex *)msg; 935 if (x->start != SYSEX_START) 936 return; 937 if (len < SYSEX_SIZE(empty)) 938 return; 939 if (x->type != SYSEX_TYPE_RT) 940 return; 941 if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) { 942 if (len == SYSEX_SIZE(master)) 943 dev_master(x->u.master.coarse); 944 return; 945 } 946 if (x->id0 != SYSEX_MMC) 947 return; 948 switch (x->id1) { 949 case SYSEX_MMC_STOP: 950 if (len != SYSEX_SIZE(stop)) 951 return; 952 dev_mmcstop(); 953 break; 954 case SYSEX_MMC_START: 955 if (len != SYSEX_SIZE(start)) 956 return; 957 dev_mmcstart(); 958 break; 959 case SYSEX_MMC_LOC: 960 if (len != SYSEX_SIZE(loc) || 961 x->u.loc.len != SYSEX_MMC_LOC_LEN || 962 x->u.loc.cmd != SYSEX_MMC_LOC_CMD) 963 return; 964 switch (x->u.loc.hr >> 5) { 965 case MTC_FPS_24: 966 fps = 24; 967 break; 968 case MTC_FPS_25: 969 fps = 25; 970 break; 971 case MTC_FPS_30: 972 fps = 30; 973 break; 974 default: 975 dev_mmcstop(); 976 return; 977 } 978 dev_mmcloc(x->u.loc.hr & 0x1f, 979 x->u.loc.min, 980 x->u.loc.sec, 981 x->u.loc.fr, 982 x->u.loc.cent, 983 fps); 984 break; 985 } 986 } 987 988 /* 989 * parse the given data chunk and call imsg() for each message 990 */ 991 static void 992 midi_in(unsigned char *idata, int icount) 993 { 994 int i; 995 unsigned char c; 996 997 for (i = 0; i < icount; i++) { 998 c = *idata++; 999 if (c >= 0xf8) { 1000 /* we don't use real-time events */ 1001 } else if (c == SYSEX_END) { 1002 if (dev_mst == SYSEX_START) { 1003 dev_msg[dev_midx++] = c; 1004 dev_imsg(dev_msg, dev_midx); 1005 } 1006 dev_mst = 0; 1007 dev_midx = 0; 1008 } else if (c >= 0xf0) { 1009 dev_msg[0] = c; 1010 dev_mlen = common_len[c & 7]; 1011 dev_mst = c; 1012 dev_midx = 1; 1013 } else if (c >= 0x80) { 1014 dev_msg[0] = c; 1015 dev_mlen = voice_len[(c >> 4) & 7]; 1016 dev_mst = c; 1017 dev_midx = 1; 1018 } else if (dev_mst) { 1019 if (dev_midx == 0 && dev_mst != SYSEX_START) 1020 dev_msg[dev_midx++] = dev_mst; 1021 dev_msg[dev_midx++] = c; 1022 if (dev_midx == dev_mlen) { 1023 dev_imsg(dev_msg, dev_midx); 1024 if (dev_mst >= 0xf0) 1025 dev_mst = 0; 1026 dev_midx = 0; 1027 } else if (dev_midx == MIDI_MSGMAX) { 1028 /* sysex too long */ 1029 dev_mst = 0; 1030 } 1031 } 1032 } 1033 } 1034 1035 static int 1036 slot_list_mix(unsigned int round, unsigned int pchan, adata_t *pbuf) 1037 { 1038 unsigned int done, n; 1039 struct slot *s; 1040 1041 memset(pbuf, 0, pchan * round * sizeof(adata_t)); 1042 done = 0; 1043 for (s = slot_list; s != NULL; s = s->next) { 1044 if (s->pstate == SLOT_INIT || !(s->mode & SIO_PLAY)) 1045 continue; 1046 if (s->pstate == SLOT_STOP && s->buf.used < s->bpf) { 1047 #ifdef DEBUG 1048 if (log_level >= 3) { 1049 slot_log(s); 1050 log_puts(": drained, done\n"); 1051 } 1052 #endif 1053 slot_stop(s); 1054 continue; 1055 } 1056 n = slot_mix_badd(s, dev_pbuf); 1057 if (n > done) 1058 done = n; 1059 } 1060 return done; 1061 } 1062 1063 static int 1064 slot_list_copy(unsigned int count, unsigned int rchan, adata_t *rbuf) 1065 { 1066 unsigned int done; 1067 struct slot *s; 1068 1069 done = 0; 1070 for (s = slot_list; s != NULL; s = s->next) { 1071 if (s->pstate == SLOT_INIT || !(s->mode & SIO_REC)) 1072 continue; 1073 slot_sub_bcopy(s, rbuf, count); 1074 done = count; 1075 } 1076 return done; 1077 } 1078 1079 static void 1080 slot_list_iodo(void) 1081 { 1082 struct slot *s; 1083 1084 for (s = slot_list; s != NULL; s = s->next) { 1085 if (s->pstate != SLOT_RUN) 1086 continue; 1087 if ((s->mode & SIO_PLAY) && 1088 (s->buf.used < s->round * s->bpf)) 1089 slot_fill(s); 1090 if ((s->mode & SIO_REC) && 1091 (s->buf.len - s->buf.used < s->round * s->bpf)) 1092 slot_flush(s); 1093 } 1094 } 1095 1096 static int 1097 offline(void) 1098 { 1099 unsigned int todo; 1100 int rate, cmax; 1101 struct slot *s; 1102 1103 if (pledge("stdio", NULL) == -1) 1104 err(1, "pledge"); 1105 1106 rate = cmax = 0; 1107 for (s = slot_list; s != NULL; s = s->next) { 1108 if (s->afile.rate > rate) 1109 rate = s->afile.rate; 1110 if (s->imax > cmax) 1111 cmax = s->imax; 1112 if (s->omax > cmax) 1113 cmax = s->omax; 1114 } 1115 dev_sh = NULL; 1116 dev_name = "offline"; 1117 dev_mode = SIO_PLAY | SIO_REC; 1118 dev_rate = rate; 1119 dev_bufsz = rate; 1120 dev_round = rate; 1121 dev_pchan = dev_rchan = cmax + 1; 1122 dev_pbuf = dev_rbuf = allocbuf(dev_round, dev_pchan, sizeof(adata_t)); 1123 dev_pstate = DEV_STOP; 1124 for (s = slot_list; s != NULL; s = s->next) 1125 slot_init(s); 1126 for (s = slot_list; s != NULL; s = s->next) 1127 slot_start(s, 0); 1128 for (;;) { 1129 todo = slot_list_mix(dev_round, dev_pchan, dev_pbuf); 1130 if (todo == 0) 1131 break; 1132 slot_list_copy(todo, dev_pchan, dev_pbuf); 1133 slot_list_iodo(); 1134 } 1135 xfree(dev_pbuf); 1136 while (slot_list) 1137 slot_del(slot_list); 1138 return 1; 1139 } 1140 1141 static int 1142 playrec_cycle(void) 1143 { 1144 unsigned int n, todo; 1145 unsigned char *p; 1146 int pcnt, rcnt; 1147 1148 #ifdef DEBUG 1149 if (log_level >= 4) { 1150 log_puts(dev_name); 1151 log_puts(": cycle, prime = "); 1152 log_putu(dev_prime); 1153 log_puts("\n"); 1154 } 1155 #endif 1156 pcnt = rcnt = 0; 1157 if (dev_mode & SIO_REC) { 1158 if (dev_prime > 0) 1159 dev_prime--; 1160 else { 1161 todo = dev_round * dev_rchan * dev_par.bps; 1162 p = dev_decbuf ? dev_decbuf : (unsigned char *)dev_rbuf; 1163 while (todo > 0) { 1164 n = sio_read(dev_sh, p, todo); 1165 if (n == 0) { 1166 log_puts(dev_name); 1167 log_puts(": failed to read " 1168 "from device\n"); 1169 return 0; 1170 } 1171 p += n; 1172 todo -= n; 1173 } 1174 rcnt = slot_list_copy(dev_round, dev_rchan, dev_rbuf); 1175 if (dev_decbuf) { 1176 dec_do(&dev_dec, 1177 dev_decbuf, (unsigned char *)dev_rbuf, 1178 dev_round); 1179 } 1180 } 1181 } 1182 if (dev_mode & SIO_PLAY) { 1183 pcnt = slot_list_mix(dev_round, dev_pchan, dev_pbuf); 1184 todo = dev_par.bps * dev_pchan * dev_round; 1185 if (dev_encbuf) { 1186 enc_do(&dev_enc, 1187 (unsigned char *)dev_pbuf, dev_encbuf, 1188 dev_round); 1189 p = dev_encbuf; 1190 } else 1191 p = (unsigned char *)dev_pbuf; 1192 n = sio_write(dev_sh, p, todo); 1193 if (n == 0) { 1194 log_puts(dev_name); 1195 log_puts(": failed to write to device\n"); 1196 return 0; 1197 } 1198 } 1199 slot_list_iodo(); 1200 return pcnt > 0 || rcnt > 0; 1201 } 1202 1203 static void 1204 sigint(int s) 1205 { 1206 if (quit_flag) 1207 _exit(1); 1208 quit_flag = 1; 1209 } 1210 1211 static int 1212 playrec(char *dev, int mode, int bufsz, char *port) 1213 { 1214 #define MIDIBUFSZ 0x100 1215 unsigned char mbuf[MIDIBUFSZ]; 1216 struct sigaction sa; 1217 struct pollfd *pfds; 1218 struct slot *s; 1219 int n, ns, nm, ev; 1220 1221 if (!dev_open(dev, mode, bufsz, port)) 1222 return 0; 1223 if (pledge("stdio audio", NULL) == -1) 1224 err(1, "pledge"); 1225 1226 n = sio_nfds(dev_sh); 1227 if (dev_mh) 1228 n += mio_nfds(dev_mh); 1229 pfds = reallocarray(NULL, n, sizeof(struct pollfd)); 1230 if (pfds == NULL) 1231 err(1, "malloc"); 1232 1233 for (s = slot_list; s != NULL; s = s->next) 1234 slot_init(s); 1235 if (dev_mh == NULL) 1236 dev_mmcstart(); 1237 else { 1238 if (log_level >= 2) 1239 log_puts("ready, waiting for mmc messages\n"); 1240 } 1241 1242 quit_flag = 0; 1243 sigfillset(&sa.sa_mask); 1244 sa.sa_flags = SA_RESTART; 1245 sa.sa_handler = sigint; 1246 sigaction(SIGINT, &sa, NULL); 1247 sigaction(SIGTERM, &sa, NULL); 1248 sigaction(SIGHUP, &sa, NULL); 1249 while (!quit_flag) { 1250 if (dev_pstate == DEV_START) { 1251 ev = 0; 1252 if (mode & SIO_PLAY) 1253 ev |= POLLOUT; 1254 if (mode & SIO_REC) 1255 ev |= POLLIN; 1256 ns = sio_pollfd(dev_sh, pfds, ev); 1257 } else 1258 ns = 0; 1259 if (dev_mh) 1260 nm = mio_pollfd(dev_mh, pfds + ns, POLLIN); 1261 else 1262 nm = 0; 1263 if (poll(pfds, ns + nm, -1) == -1) { 1264 if (errno == EINTR) 1265 continue; 1266 log_puts("poll failed\n"); 1267 panic(); 1268 } 1269 if (dev_pstate == DEV_START) { 1270 ev = sio_revents(dev_sh, pfds); 1271 if (ev & POLLHUP) { 1272 log_puts(dev); 1273 log_puts(": audio device gone, stopping\n"); 1274 break; 1275 } 1276 if (ev & (POLLIN | POLLOUT)) { 1277 if (!playrec_cycle() && dev_mh == NULL) 1278 break; 1279 } 1280 } 1281 if (dev_mh) { 1282 ev = mio_revents(dev_mh, pfds + ns); 1283 if (ev & POLLHUP) { 1284 log_puts(dev_port); 1285 log_puts(": midi port gone, stopping\n"); 1286 break; 1287 } 1288 if (ev & POLLIN) { 1289 n = mio_read(dev_mh, mbuf, MIDIBUFSZ); 1290 midi_in(mbuf, n); 1291 } 1292 } 1293 } 1294 sigfillset(&sa.sa_mask); 1295 sa.sa_flags = SA_RESTART; 1296 sa.sa_handler = SIG_DFL; 1297 sigaction(SIGINT, &sa, NULL); 1298 sigaction(SIGTERM, &sa, NULL); 1299 sigaction(SIGHUP, &sa, NULL); 1300 1301 if (dev_pstate == DEV_START) 1302 dev_mmcstop(); 1303 xfree(pfds); 1304 dev_close(); 1305 while (slot_list) 1306 slot_del(slot_list); 1307 return 1; 1308 } 1309 1310 static int 1311 opt_onoff(char *s, int *flag) 1312 { 1313 if (strcmp("off", s) == 0) { 1314 *flag = 0; 1315 return 1; 1316 } 1317 if (strcmp("on", s) == 0) { 1318 *flag = 1; 1319 return 1; 1320 } 1321 log_puts(s); 1322 log_puts(": on/off expected\n"); 1323 return 0; 1324 } 1325 1326 static int 1327 opt_enc(char *s, struct aparams *par) 1328 { 1329 int len; 1330 1331 len = aparams_strtoenc(par, s); 1332 if (len == 0 || s[len] != '\0') { 1333 log_puts(s); 1334 log_puts(": bad encoding\n"); 1335 return 0; 1336 } 1337 return 1; 1338 } 1339 1340 static int 1341 opt_hdr(char *s, int *hdr) 1342 { 1343 if (strcmp("auto", s) == 0) { 1344 *hdr = AFILE_HDR_AUTO; 1345 return 1; 1346 } 1347 if (strcmp("raw", s) == 0) { 1348 *hdr = AFILE_HDR_RAW; 1349 return 1; 1350 } 1351 if (strcmp("wav", s) == 0) { 1352 *hdr = AFILE_HDR_WAV; 1353 return 1; 1354 } 1355 if (strcmp("aiff", s) == 0) { 1356 *hdr = AFILE_HDR_AIFF; 1357 return 1; 1358 } 1359 if (strcmp("au", s) == 0) { 1360 *hdr = AFILE_HDR_AU; 1361 return 1; 1362 } 1363 log_puts(s); 1364 log_puts(": bad header type\n"); 1365 return 0; 1366 } 1367 1368 static int 1369 opt_map(char *str, int *rimin, int *rimax, int *romin, int *romax) 1370 { 1371 char *s, *next; 1372 long imin, imax, omin, omax; 1373 1374 errno = 0; 1375 s = str; 1376 imin = strtol(s, &next, 10); 1377 if (next == s || *next != ':') 1378 goto failed; 1379 s = next + 1; 1380 imax = strtol(s, &next, 10); 1381 if (next == s || *next != '/') 1382 goto failed; 1383 s = next + 1; 1384 omin = strtol(s, &next, 10); 1385 if (next == s || *next != ':') 1386 goto failed; 1387 s = next + 1; 1388 omax = strtol(s, &next, 10); 1389 if (next == s || *next != '\0') 1390 goto failed; 1391 if (imin < 0 || imax < imin || imax >= NCHAN_MAX) 1392 goto failed; 1393 if (omin < 0 || omax < omin || omax >= NCHAN_MAX) 1394 goto failed; 1395 *rimin = imin; 1396 *rimax = imax; 1397 *romin = omin; 1398 *romax = omax; 1399 return 1; 1400 failed: 1401 log_puts(str); 1402 log_puts(": channel mapping expected\n"); 1403 return 0; 1404 } 1405 1406 static int 1407 opt_nch(char *str, int *rnch, int *roff) 1408 { 1409 char *s, *next; 1410 long nch, off, cmin, cmax; 1411 1412 errno = 0; 1413 s = str; 1414 nch = strtol(s, &next, 10); 1415 if (next == s) 1416 goto failed; 1417 if (*next == ':') { 1418 /* compat with legacy -c syntax */ 1419 s = next + 1; 1420 cmin = nch; 1421 cmax = strtol(s, &next, 10); 1422 if (next == s) 1423 goto failed; 1424 if (cmin < 0 || cmax < cmin || cmax >= NCHAN_MAX) 1425 goto failed; 1426 nch = cmax - cmin + 1; 1427 off = cmin; 1428 } else { 1429 off = 0; 1430 if (nch < 0 || nch >= NCHAN_MAX) 1431 goto failed; 1432 } 1433 if (*next != '\0') 1434 goto failed; 1435 *rnch = nch; 1436 *roff = off; 1437 return 1; 1438 failed: 1439 log_puts(str); 1440 log_puts(": channel count expected\n"); 1441 return 0; 1442 } 1443 1444 static int 1445 opt_num(char *s, int min, int max, int *num) 1446 { 1447 const char *errstr; 1448 1449 *num = strtonum(s, min, max, &errstr); 1450 if (errstr) { 1451 log_puts(s); 1452 log_puts(": expected integer between "); 1453 log_puti(min); 1454 log_puts(" and "); 1455 log_puti(max); 1456 log_puts("\n"); 1457 return 0; 1458 } 1459 return 1; 1460 } 1461 1462 static int 1463 opt_pos(char *s, long long *pos) 1464 { 1465 const char *errstr; 1466 1467 *pos = strtonum(s, 0, LLONG_MAX, &errstr); 1468 if (errstr) { 1469 log_puts(s); 1470 log_puts(": positive number of samples expected\n"); 1471 return 0; 1472 } 1473 return 1; 1474 } 1475 1476 int 1477 main(int argc, char **argv) 1478 { 1479 int dup, imin, imax, omin, omax, nch, off, rate, vol, bufsz, hdr, mode; 1480 char *port, *dev; 1481 struct aparams par; 1482 int n_flag, c; 1483 long long pos; 1484 1485 if (pledge("stdio rpath wpath cpath inet unix dns audio", NULL) == -1) 1486 err(1, "pledge"); 1487 1488 vol = 127; 1489 dup = 0; 1490 bufsz = 0; 1491 nch = 2; 1492 off = 0; 1493 rate = DEFAULT_RATE; 1494 imin = imax = omin = omax = -1; 1495 par.bits = ADATA_BITS; 1496 par.bps = APARAMS_BPS(par.bits); 1497 par.le = ADATA_LE; 1498 par.sig = 1; 1499 par.msb = 1; 1500 hdr = AFILE_HDR_AUTO; 1501 n_flag = 0; 1502 port = NULL; 1503 dev = NULL; 1504 mode = 0; 1505 pos = 0; 1506 1507 while ((c = getopt(argc, argv, 1508 "b:c:de:f:g:h:i:j:m:no:p:q:r:t:v:")) != -1) { 1509 switch (c) { 1510 case 'b': 1511 if (!opt_num(optarg, 1, RATE_MAX, &bufsz)) 1512 return 1; 1513 break; 1514 case 'c': 1515 if (!opt_nch(optarg, &nch, &off)) 1516 return 1; 1517 break; 1518 case 'd': 1519 log_level++; 1520 break; 1521 case 'e': 1522 if (!opt_enc(optarg, &par)) 1523 return 1; 1524 break; 1525 case 'f': 1526 dev = optarg; 1527 break; 1528 case 'g': 1529 if (!opt_pos(optarg, &dev_pos)) 1530 return 1; 1531 break; 1532 case 'h': 1533 if (!opt_hdr(optarg, &hdr)) 1534 return 1; 1535 break; 1536 case 'i': 1537 if (off > 0) { 1538 /* compat with legacy -c syntax */ 1539 omin = off; 1540 omax = off + nch - 1; 1541 } 1542 if (!slot_new(optarg, SIO_PLAY, 1543 &par, hdr, imin, imax, omin, omax, 1544 nch, rate, dup, vol, pos)) 1545 return 1; 1546 mode |= SIO_PLAY; 1547 imin = imax = omin = omax = -1; 1548 break; 1549 case 'j': 1550 /* compat with legacy -j option */ 1551 if (!opt_onoff(optarg, &dup)) 1552 return 1; 1553 break; 1554 case 'm': 1555 if (!opt_map(optarg, &imin, &imax, &omin, &omax)) 1556 return 1; 1557 break; 1558 case 'n': 1559 n_flag = 1; 1560 break; 1561 case 'o': 1562 if (off > 0) { 1563 /* compat with legacy -c syntax */ 1564 imin = off; 1565 imax = off + nch - 1; 1566 } 1567 if (!slot_new(optarg, SIO_REC, 1568 &par, hdr, imin, imax, omin, omax, 1569 nch, rate, dup, 0, pos)) 1570 return 1; 1571 imin = imax = omin = omax = -1; 1572 mode |= SIO_REC; 1573 break; 1574 case 'p': 1575 if (!opt_pos(optarg, &pos)) 1576 return 1; 1577 break; 1578 case 'q': 1579 port = optarg; 1580 break; 1581 case 'r': 1582 if (!opt_num(optarg, RATE_MIN, RATE_MAX, &rate)) 1583 return 1; 1584 break; 1585 case 'v': 1586 if (!opt_num(optarg, 0, MIDI_MAXCTL, &vol)) 1587 return 1; 1588 break; 1589 default: 1590 goto bad_usage; 1591 } 1592 } 1593 argc -= optind; 1594 argv += optind; 1595 if (argc != 0) { 1596 bad_usage: 1597 log_puts(usagestr); 1598 return 1; 1599 } 1600 if (n_flag) { 1601 if (dev != NULL || port != NULL) { 1602 log_puts("-f and -q make no sense in off-line mode\n"); 1603 return 1; 1604 } 1605 if (mode != (SIO_PLAY | SIO_REC)) { 1606 log_puts("both -i and -o required\n"); 1607 return 1; 1608 } 1609 if (!offline()) 1610 return 1; 1611 } else { 1612 if (dev == NULL) 1613 dev = SIO_DEVANY; 1614 if (mode == 0) { 1615 log_puts("at least -i or -o required\n"); 1616 return 1; 1617 } 1618 if (!playrec(dev, mode, bufsz, port)) 1619 return 1; 1620 } 1621 return 0; 1622 } 1623