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