1 /* $OpenBSD: midi.c,v 1.31 2024/05/19 00:05:43 jsg 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 void
midi_log(struct midi * ep)60 midi_log(struct midi *ep)
61 {
62 log_puts("midi");
63 log_putu(ep - midi_ep);
64 }
65
66 void
midi_init(void)67 midi_init(void)
68 {
69 }
70
71 void
midi_done(void)72 midi_done(void)
73 {
74 }
75
76 struct midi *
midi_new(struct midiops * ops,void * arg,int mode)77 midi_new(struct midiops *ops, void *arg, int mode)
78 {
79 int i;
80 struct midi *ep;
81
82 for (i = 0, ep = midi_ep;; i++, ep++) {
83 if (i == MIDI_NEP)
84 return NULL;
85 if (ep->ops == NULL)
86 break;
87 }
88 ep->ops = ops;
89 ep->arg = arg;
90 ep->used = 0;
91 ep->len = 0;
92 ep->idx = 0;
93 ep->st = 0;
94 ep->last_st = 0;
95 ep->txmask = 0;
96 ep->self = 1 << i;
97 ep->tickets = 0;
98 ep->mode = mode;
99
100 /*
101 * the output buffer is the client input
102 */
103 if (ep->mode & MODE_MIDIIN)
104 abuf_init(&ep->obuf, MIDI_BUFSZ);
105 midi_tickets(ep);
106 return ep;
107 }
108
109 void
midi_del(struct midi * ep)110 midi_del(struct midi *ep)
111 {
112 int i;
113 struct midi *peer;
114
115 ep->txmask = 0;
116 for (i = 0; i < MIDI_NEP; i++) {
117 peer = midi_ep + i;
118 if (peer->txmask & ep->self) {
119 peer->txmask &= ~ep->self;
120 midi_tickets(peer);
121 }
122 }
123 for (i = 0; i < MIDITHRU_NMAX; i++) {
124 midithru[i].txmask &= ~ep->self;
125 midithru[i].rxmask &= ~ep->self;
126 }
127 ep->ops = NULL;
128 if (ep->mode & MODE_MIDIIN) {
129 abuf_done(&ep->obuf);
130 }
131 }
132
133 /*
134 * connect two midi endpoints
135 */
136 void
midi_link(struct midi * ep,struct midi * peer)137 midi_link(struct midi *ep, struct midi *peer)
138 {
139 if (ep->mode & MODE_MIDIOUT) {
140 ep->txmask |= peer->self;
141 midi_tickets(ep);
142 }
143 if (ep->mode & MODE_MIDIIN) {
144 #ifdef DEBUG
145 if (ep->obuf.used > 0) {
146 midi_log(ep);
147 log_puts(": linked with non-empty buffer\n");
148 panic();
149 }
150 #endif
151 /* ep has empty buffer, so no need to call midi_tickets() */
152 peer->txmask |= ep->self;
153 }
154 }
155
156 /*
157 * return the list of endpoints the given one receives from
158 */
159 unsigned int
midi_rxmask(struct midi * ep)160 midi_rxmask(struct midi *ep)
161 {
162 int i, rxmask;
163
164 for (rxmask = 0, i = 0; i < MIDI_NEP; i++) {
165 if ((midi_ep[i].txmask & ep->self) == 0)
166 continue;
167 rxmask |= midi_ep[i].self;
168 }
169
170 return rxmask;
171 }
172
173 /*
174 * add the midi endpoint in the ``tag'' midi thru box
175 */
176 void
midi_tag(struct midi * ep,unsigned int tag)177 midi_tag(struct midi *ep, unsigned int tag)
178 {
179 struct midi *peer;
180 struct midithru *t = midithru + tag;
181 int i;
182
183 if (ep->mode & MODE_MIDIOUT) {
184 ep->txmask |= t->txmask;
185 midi_tickets(ep);
186 }
187 if (ep->mode & MODE_MIDIIN) {
188 #ifdef DEBUG
189 if (ep->obuf.used > 0) {
190 midi_log(ep);
191 log_puts(": tagged with non-empty buffer\n");
192 panic();
193 }
194 #endif
195 for (i = 0; i < MIDI_NEP; i++) {
196 if (!(t->rxmask & (1 << i)))
197 continue;
198 peer = midi_ep + i;
199 peer->txmask |= ep->self;
200 }
201 }
202 if (ep->mode & MODE_MIDIOUT)
203 t->rxmask |= ep->self;
204 if (ep->mode & MODE_MIDIIN)
205 t->txmask |= ep->self;
206 }
207
208 /*
209 * return the list of tags
210 */
211 unsigned int
midi_tags(struct midi * ep)212 midi_tags(struct midi *ep)
213 {
214 int i;
215 struct midithru *t;
216 unsigned int tags;
217
218 tags = 0;
219 for (i = 0; i < MIDITHRU_NMAX; i++) {
220 t = midithru + i;
221 if ((t->txmask | t->rxmask) & ep->self)
222 tags |= 1 << i;
223 }
224 return tags;
225 }
226
227 /*
228 * broadcast the given message to other endpoints
229 */
230 void
midi_send(struct midi * iep,unsigned char * msg,int size)231 midi_send(struct midi *iep, unsigned char *msg, int size)
232 {
233 struct midi *oep;
234 int i;
235
236 #ifdef DEBUG
237 if (log_level >= 4) {
238 midi_log(iep);
239 log_puts(": sending:");
240 for (i = 0; i < size; i++) {
241 log_puts(" ");
242 log_putx(msg[i]);
243 }
244 log_puts("\n");
245 }
246 #endif
247 for (i = 0; i < MIDI_NEP ; i++) {
248 if ((iep->txmask & (1 << i)) == 0)
249 continue;
250 oep = midi_ep + i;
251 if (msg[0] <= 0x7f) {
252 if (oep->owner != iep)
253 continue;
254 } else if (msg[0] <= 0xf7)
255 oep->owner = iep;
256 #ifdef DEBUG
257 if (log_level >= 4) {
258 midi_log(iep);
259 log_puts(" -> ");
260 midi_log(oep);
261 log_puts("\n");
262 }
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
midi_tickets(struct midi * iep)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
midi_fill(struct midi * oep)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
midi_in(struct midi * iep,unsigned char * idata,int icount)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
midi_out(struct midi * oep,unsigned char * idata,int icount)393 midi_out(struct midi *oep, unsigned char *idata, int icount)
394 {
395 unsigned char *odata;
396 int ocount;
397 #ifdef DEBUG
398 int i;
399 #endif
400
401 while (icount > 0) {
402 if (oep->obuf.used == oep->obuf.len) {
403 #ifdef DEBUG
404 if (log_level >= 2) {
405 midi_log(oep);
406 log_puts(": too slow, discarding ");
407 log_putu(oep->obuf.used);
408 log_puts(" bytes\n");
409 }
410 #endif
411 abuf_rdiscard(&oep->obuf, oep->obuf.used);
412 oep->owner = NULL;
413 return;
414 }
415 odata = abuf_wgetblk(&oep->obuf, &ocount);
416 if (ocount > icount)
417 ocount = icount;
418 memcpy(odata, idata, ocount);
419 #ifdef DEBUG
420 if (log_level >= 4) {
421 midi_log(oep);
422 log_puts(": out: ");
423 for (i = 0; i < ocount; i++) {
424 log_puts(" ");
425 log_putx(odata[i]);
426 }
427 log_puts("\n");
428 }
429 #endif
430 abuf_wcommit(&oep->obuf, ocount);
431 icount -= ocount;
432 idata += ocount;
433 }
434 }
435
436 /*
437 * disconnect clients attached to this end-point
438 */
439 void
midi_abort(struct midi * p)440 midi_abort(struct midi *p)
441 {
442 int i;
443 struct midi *ep;
444
445 for (i = 0; i < MIDI_NEP; i++) {
446 ep = midi_ep + i;
447 if ((ep->txmask & p->self) || (p->txmask & ep->self))
448 ep->ops->exit(ep->arg);
449 }
450 }
451
452 /*
453 * connect to "nep" all endpoints currently connected to "oep"
454 */
455 void
midi_migrate(struct midi * oep,struct midi * nep)456 midi_migrate(struct midi *oep, struct midi *nep)
457 {
458 struct midithru *t;
459 struct midi *ep;
460 int i;
461
462 for (i = 0; i < MIDITHRU_NMAX; i++) {
463 t = midithru + i;
464 if (t->txmask & oep->self) {
465 t->txmask &= ~oep->self;
466 t->txmask |= nep->self;
467 }
468 if (t->rxmask & oep->self) {
469 t->rxmask &= ~oep->self;
470 t->rxmask |= nep->self;
471 }
472 }
473
474 for (i = 0; i < MIDI_NEP; i++) {
475 ep = midi_ep + i;
476 if (ep->txmask & oep->self) {
477 ep->txmask &= ~oep->self;
478 ep->txmask |= nep->self;
479 }
480 }
481
482 for (i = 0; i < MIDI_NEP; i++) {
483 ep = midi_ep + i;
484 if (oep->txmask & ep->self) {
485 oep->txmask &= ~ep->self;
486 nep->txmask |= ep->self;
487 }
488 }
489 }
490
491 void
port_log(struct port * p)492 port_log(struct port *p)
493 {
494 midi_log(p->midi);
495 }
496
497 void
port_imsg(void * arg,unsigned char * msg,int size)498 port_imsg(void *arg, unsigned char *msg, int size)
499 {
500 struct port *p = arg;
501
502 midi_send(p->midi, msg, size);
503 }
504
505
506 void
port_omsg(void * arg,unsigned char * msg,int size)507 port_omsg(void *arg, unsigned char *msg, int size)
508 {
509 struct port *p = arg;
510
511 midi_out(p->midi, msg, size);
512 }
513
514 void
port_fill(void * arg,int count)515 port_fill(void *arg, int count)
516 {
517 /* no flow control */
518 }
519
520 void
port_exit(void * arg)521 port_exit(void *arg)
522 {
523 #ifdef DEBUG
524 struct port *p = arg;
525
526 if (log_level >= 3) {
527 port_log(p);
528 log_puts(": port exit\n");
529 panic();
530 }
531 #endif
532 }
533
534 /*
535 * create a new midi port
536 */
537 struct port *
port_new(char * path,unsigned int mode,int hold)538 port_new(char *path, unsigned int mode, int hold)
539 {
540 struct port *c;
541
542 c = xmalloc(sizeof(struct port));
543 c->path = path;
544 c->state = PORT_CFG;
545 c->hold = hold;
546 c->midi = midi_new(&port_midiops, c, mode);
547 c->num = midi_portnum++;
548 c->alt_next = c;
549 c->next = port_list;
550 port_list = c;
551 return c;
552 }
553
554 /*
555 * destroy the given midi port
556 */
557 void
port_del(struct port * c)558 port_del(struct port *c)
559 {
560 struct port **p;
561
562 if (c->state != PORT_CFG)
563 port_close(c);
564 midi_del(c->midi);
565 for (p = &port_list; *p != c; p = &(*p)->next) {
566 #ifdef DEBUG
567 if (*p == NULL) {
568 log_puts("port to delete not on list\n");
569 panic();
570 }
571 #endif
572 }
573 *p = c->next;
574 xfree(c);
575 }
576
577 int
port_ref(struct port * c)578 port_ref(struct port *c)
579 {
580 #ifdef DEBUG
581 if (log_level >= 3) {
582 port_log(c);
583 log_puts(": port requested\n");
584 }
585 #endif
586 if (c->state == PORT_CFG && !port_open(c))
587 return 0;
588 return 1;
589 }
590
591 void
port_unref(struct port * c)592 port_unref(struct port *c)
593 {
594 int i, rxmask;
595
596 #ifdef DEBUG
597 if (log_level >= 3) {
598 port_log(c);
599 log_puts(": port released\n");
600 }
601 #endif
602 for (rxmask = 0, i = 0; i < MIDI_NEP; i++)
603 rxmask |= midi_ep[i].txmask;
604 if ((rxmask & c->midi->self) == 0 && c->midi->txmask == 0 &&
605 c->state == PORT_INIT && !c->hold)
606 port_drain(c);
607 }
608
609 struct port *
port_alt_ref(int num)610 port_alt_ref(int num)
611 {
612 struct port *a, *p;
613
614 a = port_bynum(num);
615 if (a == NULL)
616 return NULL;
617
618 /* circulate to first alt port */
619 while (a->alt_next->num > a->num)
620 a = a->alt_next;
621
622 p = a;
623 while (1) {
624 if (port_ref(p))
625 break;
626 p = p->alt_next;
627 if (p == a)
628 return NULL;
629 }
630
631 return p;
632 }
633
634 struct port *
port_migrate(struct port * op)635 port_migrate(struct port *op)
636 {
637 struct port *np;
638
639 /* not opened */
640 if (op->state == PORT_CFG)
641 return op;
642
643 np = op;
644 while (1) {
645 /* try next one, circulating through the list */
646 np = np->alt_next;
647 if (np == op) {
648 if (log_level >= 2) {
649 port_log(op);
650 log_puts(": no fall-back port found\n");
651 }
652 return op;
653 }
654
655 if (port_ref(np))
656 break;
657 }
658
659 if (log_level >= 2) {
660 port_log(op);
661 log_puts(": switching to ");
662 port_log(np);
663 log_puts("\n");
664 }
665
666 midi_migrate(op->midi, np->midi);
667 return np;
668 }
669
670 struct port *
port_bynum(int num)671 port_bynum(int num)
672 {
673 struct port *p;
674
675 for (p = port_list; p != NULL; p = p->next) {
676 if (p->num == num)
677 return p;
678 }
679 return NULL;
680 }
681
682 int
port_open(struct port * c)683 port_open(struct port *c)
684 {
685 if (!port_mio_open(c)) {
686 if (log_level >= 1) {
687 port_log(c);
688 log_puts(": failed to open midi port\n");
689 }
690 return 0;
691 }
692 c->state = PORT_INIT;
693 return 1;
694 }
695
696 int
port_close(struct port * c)697 port_close(struct port *c)
698 {
699 #ifdef DEBUG
700 if (c->state == PORT_CFG) {
701 port_log(c);
702 log_puts(": can't close port (not opened)\n");
703 panic();
704 }
705 #endif
706 port_log(c);
707 log_puts(": closed\n");
708 c->state = PORT_CFG;
709 port_mio_close(c);
710 return 1;
711 }
712
713 void
port_drain(struct port * c)714 port_drain(struct port *c)
715 {
716 struct midi *ep = c->midi;
717
718 if (!(ep->mode & MODE_MIDIOUT) || ep->obuf.used == 0)
719 port_close(c);
720 else {
721 c->state = PORT_DRAIN;
722 #ifdef DEBUG
723 if (log_level >= 3) {
724 port_log(c);
725 log_puts(": draining\n");
726 }
727 #endif
728 }
729 }
730
731 int
port_init(struct port * c)732 port_init(struct port *c)
733 {
734 if (c->hold)
735 return port_open(c);
736 return 1;
737 }
738
739 void
port_done(struct port * c)740 port_done(struct port *c)
741 {
742 if (c->state == PORT_INIT)
743 port_drain(c);
744 }
745