1 /* $OpenBSD: midi.c,v 1.29 2021/11/01 14:43:25 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 <stdlib.h> 19 #include <string.h> 20 21 #include "abuf.h" 22 #include "defs.h" 23 #include "dev.h" 24 #include "file.h" 25 #include "midi.h" 26 #include "miofile.h" 27 #include "sysex.h" 28 #include "utils.h" 29 30 int port_open(struct port *); 31 void port_imsg(void *, unsigned char *, int); 32 void port_omsg(void *, unsigned char *, int); 33 void port_fill(void *, int); 34 void port_exit(void *); 35 void port_exitall(struct port *); 36 37 struct midiops port_midiops = { 38 port_imsg, 39 port_omsg, 40 port_fill, 41 port_exit 42 }; 43 44 #define MIDI_NEP 32 45 struct midi midi_ep[MIDI_NEP]; 46 struct port *port_list = NULL; 47 unsigned int midi_portnum = 0; 48 49 struct midithru { 50 unsigned int txmask, rxmask; 51 #define MIDITHRU_NMAX 32 52 } midithru[MIDITHRU_NMAX]; 53 54 /* 55 * length of voice and common messages (status byte included) 56 */ 57 const unsigned int voice_len[] = { 3, 3, 3, 3, 2, 2, 3 }; 58 const unsigned int common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 }; 59 60 void 61 midi_log(struct midi *ep) 62 { 63 log_puts("midi"); 64 log_putu(ep - midi_ep); 65 } 66 67 void 68 midi_init(void) 69 { 70 } 71 72 void 73 midi_done(void) 74 { 75 } 76 77 struct midi * 78 midi_new(struct midiops *ops, void *arg, int mode) 79 { 80 int i; 81 struct midi *ep; 82 83 for (i = 0, ep = midi_ep;; i++, ep++) { 84 if (i == MIDI_NEP) 85 return NULL; 86 if (ep->ops == NULL) 87 break; 88 } 89 ep->ops = ops; 90 ep->arg = arg; 91 ep->used = 0; 92 ep->len = 0; 93 ep->idx = 0; 94 ep->st = 0; 95 ep->last_st = 0; 96 ep->txmask = 0; 97 ep->self = 1 << i; 98 ep->tickets = 0; 99 ep->mode = mode; 100 101 /* 102 * the output buffer is the client input 103 */ 104 if (ep->mode & MODE_MIDIIN) 105 abuf_init(&ep->obuf, MIDI_BUFSZ); 106 midi_tickets(ep); 107 return ep; 108 } 109 110 void 111 midi_del(struct midi *ep) 112 { 113 int i; 114 struct midi *peer; 115 116 ep->txmask = 0; 117 for (i = 0; i < MIDI_NEP; i++) { 118 peer = midi_ep + i; 119 if (peer->txmask & ep->self) { 120 peer->txmask &= ~ep->self; 121 midi_tickets(peer); 122 } 123 } 124 for (i = 0; i < MIDITHRU_NMAX; i++) { 125 midithru[i].txmask &= ~ep->self; 126 midithru[i].rxmask &= ~ep->self; 127 } 128 ep->ops = NULL; 129 if (ep->mode & MODE_MIDIIN) { 130 abuf_done(&ep->obuf); 131 } 132 } 133 134 /* 135 * connect two midi endpoints 136 */ 137 void 138 midi_link(struct midi *ep, struct midi *peer) 139 { 140 if (ep->mode & MODE_MIDIOUT) { 141 ep->txmask |= peer->self; 142 midi_tickets(ep); 143 } 144 if (ep->mode & MODE_MIDIIN) { 145 #ifdef DEBUG 146 if (ep->obuf.used > 0) { 147 midi_log(ep); 148 log_puts(": linked with non-empty buffer\n"); 149 panic(); 150 } 151 #endif 152 /* ep has empty buffer, so no need to call midi_tickets() */ 153 peer->txmask |= ep->self; 154 } 155 } 156 157 /* 158 * add the midi endpoint in the ``tag'' midi thru box 159 */ 160 void 161 midi_tag(struct midi *ep, unsigned int tag) 162 { 163 struct midi *peer; 164 struct midithru *t = midithru + tag; 165 int i; 166 167 if (ep->mode & MODE_MIDIOUT) { 168 ep->txmask |= t->txmask; 169 midi_tickets(ep); 170 } 171 if (ep->mode & MODE_MIDIIN) { 172 #ifdef DEBUG 173 if (ep->obuf.used > 0) { 174 midi_log(ep); 175 log_puts(": tagged with non-empty buffer\n"); 176 panic(); 177 } 178 #endif 179 for (i = 0; i < MIDI_NEP; i++) { 180 if (!(t->rxmask & (1 << i))) 181 continue; 182 peer = midi_ep + i; 183 peer->txmask |= ep->self; 184 } 185 } 186 if (ep->mode & MODE_MIDIOUT) 187 t->rxmask |= ep->self; 188 if (ep->mode & MODE_MIDIIN) 189 t->txmask |= ep->self; 190 } 191 192 /* 193 * return the list of tags 194 */ 195 unsigned int 196 midi_tags(struct midi *ep) 197 { 198 int i; 199 struct midithru *t; 200 unsigned int tags; 201 202 tags = 0; 203 for (i = 0; i < MIDITHRU_NMAX; i++) { 204 t = midithru + i; 205 if ((t->txmask | t->rxmask) & ep->self) 206 tags |= 1 << i; 207 } 208 return tags; 209 } 210 211 /* 212 * broadcast the given message to other endpoints 213 */ 214 void 215 midi_send(struct midi *iep, unsigned char *msg, int size) 216 { 217 struct midi *oep; 218 int i; 219 220 #ifdef DEBUG 221 if (log_level >= 4) { 222 midi_log(iep); 223 log_puts(": sending:"); 224 for (i = 0; i < size; i++) { 225 log_puts(" "); 226 log_putx(msg[i]); 227 } 228 log_puts("\n"); 229 } 230 #endif 231 for (i = 0; i < MIDI_NEP ; i++) { 232 if ((iep->txmask & (1 << i)) == 0) 233 continue; 234 oep = midi_ep + i; 235 if (msg[0] <= 0x7f) { 236 if (oep->owner != iep) 237 continue; 238 } else if (msg[0] <= 0xf7) 239 oep->owner = iep; 240 #ifdef DEBUG 241 if (log_level >= 4) { 242 midi_log(iep); 243 log_puts(" -> "); 244 midi_log(oep); 245 log_puts("\n"); 246 } 247 #endif 248 oep->ops->omsg(oep->arg, msg, size); 249 } 250 } 251 252 /* 253 * determine if we have gained more input tickets, and if so call the 254 * fill() call-back to notify the i/o layer that it can send more data 255 */ 256 void 257 midi_tickets(struct midi *iep) 258 { 259 int i, tickets, avail, maxavail; 260 struct midi *oep; 261 262 /* 263 * don't request iep->ops->fill() too often as it generates 264 * useless network traffic: wait until we reach half of the 265 * max tickets count. As in the worst case (see comment below) 266 * one ticket may consume two bytes, the max ticket count is 267 * BUFSZ / 2 and halt of it is simply BUFSZ / 4. 268 */ 269 if (iep->tickets >= MIDI_BUFSZ / 4) 270 return; 271 272 maxavail = MIDI_BUFSZ; 273 for (i = 0; i < MIDI_NEP ; i++) { 274 if ((iep->txmask & (1 << i)) == 0) 275 continue; 276 oep = midi_ep + i; 277 avail = oep->obuf.len - oep->obuf.used; 278 if (maxavail > avail) 279 maxavail = avail; 280 } 281 282 /* 283 * in the worst case output message is twice the 284 * input message (2-byte messages with running status) 285 */ 286 tickets = maxavail / 2 - iep->tickets; 287 if (tickets > 0) { 288 iep->tickets += tickets; 289 iep->ops->fill(iep->arg, tickets); 290 } 291 } 292 293 /* 294 * recalculate tickets of endpoints sending data to this one 295 */ 296 void 297 midi_fill(struct midi *oep) 298 { 299 int i; 300 struct midi *iep; 301 302 for (i = 0; i < MIDI_NEP; i++) { 303 iep = midi_ep + i; 304 if (iep->txmask & oep->self) 305 midi_tickets(iep); 306 } 307 } 308 309 /* 310 * parse then give data chunk, and calling imsg() for each message 311 */ 312 void 313 midi_in(struct midi *iep, unsigned char *idata, int icount) 314 { 315 int i; 316 unsigned char c; 317 318 for (i = 0; i < icount; i++) { 319 c = *idata++; 320 if (c >= 0xf8) { 321 if (c != MIDI_ACK) 322 iep->ops->imsg(iep->arg, &c, 1); 323 } else if (c == SYSEX_END) { 324 if (iep->st == SYSEX_START) { 325 iep->msg[iep->idx++] = c; 326 iep->ops->imsg(iep->arg, iep->msg, iep->idx); 327 } 328 329 /* 330 * There are bogus MIDI sources that keep 331 * state across sysex; Linux virmidi ports fed 332 * by the sequencer is an example. We 333 * workaround this by saving the current 334 * status and restoring it at the end of the 335 * sysex. 336 */ 337 iep->st = iep->last_st; 338 if (iep->st) 339 iep->len = voice_len[(iep->st >> 4) & 7]; 340 iep->idx = 0; 341 } else if (c >= 0xf0) { 342 iep->msg[0] = c; 343 iep->len = common_len[c & 7]; 344 iep->st = c; 345 iep->idx = 1; 346 } else if (c >= 0x80) { 347 iep->msg[0] = c; 348 iep->len = voice_len[(c >> 4) & 7]; 349 iep->last_st = iep->st = c; 350 iep->idx = 1; 351 } else if (iep->st) { 352 if (iep->idx == 0 && iep->st != SYSEX_START) 353 iep->msg[iep->idx++] = iep->st; 354 iep->msg[iep->idx++] = c; 355 if (iep->idx == iep->len) { 356 iep->ops->imsg(iep->arg, iep->msg, iep->idx); 357 if (iep->st >= 0xf0) 358 iep->st = 0; 359 iep->idx = 0; 360 } else if (iep->idx == MIDI_MSGMAX) { 361 /* sysex continued */ 362 iep->ops->imsg(iep->arg, iep->msg, iep->idx); 363 iep->idx = 0; 364 } 365 } 366 } 367 iep->tickets -= icount; 368 if (iep->tickets < 0) 369 iep->tickets = 0; 370 midi_tickets(iep); 371 } 372 373 /* 374 * store the given message in the output buffer 375 */ 376 void 377 midi_out(struct midi *oep, unsigned char *idata, int icount) 378 { 379 unsigned char *odata; 380 int ocount; 381 #ifdef DEBUG 382 int i; 383 #endif 384 385 while (icount > 0) { 386 if (oep->obuf.used == oep->obuf.len) { 387 #ifdef DEBUG 388 if (log_level >= 2) { 389 midi_log(oep); 390 log_puts(": too slow, discarding "); 391 log_putu(oep->obuf.used); 392 log_puts(" bytes\n"); 393 } 394 #endif 395 abuf_rdiscard(&oep->obuf, oep->obuf.used); 396 oep->owner = NULL; 397 return; 398 } 399 odata = abuf_wgetblk(&oep->obuf, &ocount); 400 if (ocount > icount) 401 ocount = icount; 402 memcpy(odata, idata, ocount); 403 #ifdef DEBUG 404 if (log_level >= 4) { 405 midi_log(oep); 406 log_puts(": out: "); 407 for (i = 0; i < ocount; i++) { 408 log_puts(" "); 409 log_putx(odata[i]); 410 } 411 log_puts("\n"); 412 } 413 #endif 414 abuf_wcommit(&oep->obuf, ocount); 415 icount -= ocount; 416 idata += ocount; 417 } 418 } 419 420 /* 421 * disconnect clients attached to this end-point 422 */ 423 void 424 midi_abort(struct midi *p) 425 { 426 int i; 427 struct midi *ep; 428 429 for (i = 0; i < MIDI_NEP; i++) { 430 ep = midi_ep + i; 431 if ((ep->txmask & p->self) || (p->txmask & ep->self)) 432 ep->ops->exit(ep->arg); 433 } 434 } 435 436 /* 437 * connect to "nep" all endpoints currently connected to "oep" 438 */ 439 void 440 midi_migrate(struct midi *oep, struct midi *nep) 441 { 442 struct midithru *t; 443 struct midi *ep; 444 int i; 445 446 for (i = 0; i < MIDITHRU_NMAX; i++) { 447 t = midithru + i; 448 if (t->txmask & oep->self) { 449 t->txmask &= ~oep->self; 450 t->txmask |= nep->self; 451 } 452 if (t->rxmask & oep->self) { 453 t->rxmask &= ~oep->self; 454 t->rxmask |= nep->self; 455 } 456 } 457 458 for (i = 0; i < MIDI_NEP; i++) { 459 ep = midi_ep + i; 460 if (ep->txmask & oep->self) { 461 ep->txmask &= ~oep->self; 462 ep->txmask |= nep->self; 463 } 464 } 465 466 for (i = 0; i < MIDI_NEP; i++) { 467 ep = midi_ep + i; 468 if (oep->txmask & ep->self) { 469 oep->txmask &= ~ep->self; 470 nep->txmask |= ep->self; 471 } 472 } 473 } 474 475 void 476 port_log(struct port *p) 477 { 478 midi_log(p->midi); 479 } 480 481 void 482 port_imsg(void *arg, unsigned char *msg, int size) 483 { 484 struct port *p = arg; 485 486 midi_send(p->midi, msg, size); 487 } 488 489 490 void 491 port_omsg(void *arg, unsigned char *msg, int size) 492 { 493 struct port *p = arg; 494 495 midi_out(p->midi, msg, size); 496 } 497 498 void 499 port_fill(void *arg, int count) 500 { 501 /* no flow control */ 502 } 503 504 void 505 port_exit(void *arg) 506 { 507 #ifdef DEBUG 508 struct port *p = arg; 509 510 if (log_level >= 3) { 511 port_log(p); 512 log_puts(": port exit\n"); 513 panic(); 514 } 515 #endif 516 } 517 518 /* 519 * create a new midi port 520 */ 521 struct port * 522 port_new(char *path, unsigned int mode, int hold) 523 { 524 struct port *c; 525 526 c = xmalloc(sizeof(struct port)); 527 c->path = path; 528 c->state = PORT_CFG; 529 c->hold = hold; 530 c->midi = midi_new(&port_midiops, c, mode); 531 c->num = midi_portnum++; 532 c->alt_next = c; 533 c->next = port_list; 534 port_list = c; 535 return c; 536 } 537 538 /* 539 * destroy the given midi port 540 */ 541 void 542 port_del(struct port *c) 543 { 544 struct port **p; 545 546 if (c->state != PORT_CFG) 547 port_close(c); 548 midi_del(c->midi); 549 for (p = &port_list; *p != c; p = &(*p)->next) { 550 #ifdef DEBUG 551 if (*p == NULL) { 552 log_puts("port to delete not on list\n"); 553 panic(); 554 } 555 #endif 556 } 557 *p = c->next; 558 xfree(c); 559 } 560 561 int 562 port_ref(struct port *c) 563 { 564 #ifdef DEBUG 565 if (log_level >= 3) { 566 port_log(c); 567 log_puts(": port requested\n"); 568 } 569 #endif 570 if (c->state == PORT_CFG && !port_open(c)) 571 return 0; 572 return 1; 573 } 574 575 void 576 port_unref(struct port *c) 577 { 578 int i, rxmask; 579 580 #ifdef DEBUG 581 if (log_level >= 3) { 582 port_log(c); 583 log_puts(": port released\n"); 584 } 585 #endif 586 for (rxmask = 0, i = 0; i < MIDI_NEP; i++) 587 rxmask |= midi_ep[i].txmask; 588 if ((rxmask & c->midi->self) == 0 && c->midi->txmask == 0 && 589 c->state == PORT_INIT && !c->hold) 590 port_drain(c); 591 } 592 593 struct port * 594 port_alt_ref(int num) 595 { 596 struct port *a, *p; 597 598 a = port_bynum(num); 599 if (a == NULL) 600 return NULL; 601 602 /* circulate to first alt port */ 603 while (a->alt_next->num > a->num) 604 a = a->alt_next; 605 606 p = a; 607 while (1) { 608 if (port_ref(p)) 609 break; 610 p = p->alt_next; 611 if (p == a) 612 return NULL; 613 } 614 615 return p; 616 } 617 618 struct port * 619 port_migrate(struct port *op) 620 { 621 struct port *np; 622 623 /* not opened */ 624 if (op->state == PORT_CFG) 625 return op; 626 627 np = op; 628 while (1) { 629 /* try next one, circulating through the list */ 630 np = np->alt_next; 631 if (np == op) { 632 if (log_level >= 2) { 633 port_log(op); 634 log_puts(": no fall-back port found\n"); 635 } 636 return op; 637 } 638 639 if (port_ref(np)) 640 break; 641 } 642 643 if (log_level >= 2) { 644 port_log(op); 645 log_puts(": switching to "); 646 port_log(np); 647 log_puts("\n"); 648 } 649 650 midi_migrate(op->midi, np->midi); 651 return np; 652 } 653 654 struct port * 655 port_bynum(int num) 656 { 657 struct port *p; 658 659 for (p = port_list; p != NULL; p = p->next) { 660 if (p->num == num) 661 return p; 662 } 663 return NULL; 664 } 665 666 int 667 port_open(struct port *c) 668 { 669 if (!port_mio_open(c)) { 670 if (log_level >= 1) { 671 port_log(c); 672 log_puts(": failed to open midi port\n"); 673 } 674 return 0; 675 } 676 c->state = PORT_INIT; 677 return 1; 678 } 679 680 int 681 port_close(struct port *c) 682 { 683 #ifdef DEBUG 684 if (c->state == PORT_CFG) { 685 port_log(c); 686 log_puts(": can't close port (not opened)\n"); 687 panic(); 688 } 689 #endif 690 port_log(c); 691 log_puts(": closed\n"); 692 c->state = PORT_CFG; 693 port_mio_close(c); 694 return 1; 695 } 696 697 void 698 port_drain(struct port *c) 699 { 700 struct midi *ep = c->midi; 701 702 if (!(ep->mode & MODE_MIDIOUT) || ep->obuf.used == 0) 703 port_close(c); 704 else { 705 c->state = PORT_DRAIN; 706 #ifdef DEBUG 707 if (log_level >= 3) { 708 port_log(c); 709 log_puts(": draining\n"); 710 } 711 #endif 712 } 713 } 714 715 int 716 port_init(struct port *c) 717 { 718 if (c->hold) 719 return port_open(c); 720 return 1; 721 } 722 723 void 724 port_done(struct port *c) 725 { 726 if (c->state == PORT_INIT) 727 port_drain(c); 728 } 729