1
2 /*
3 * Diverse Bristol midi routines.
4 * Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 /*
23 * This code should open the midi device and read data from it.
24 *
25 * All requests will be dispatched to the relevant handlers, with support for
26 * OSS (/dev/midi*), ALSA (hw:0,0) and as of release 0.8 also the ALSA sequencer
27 * (with client.port config).
28 *
29 * All events will be converted into a bristol native message format for
30 * independency from the driver.
31 */
32 #include <unistd.h>
33 #include <strings.h>
34
35 #include "bristolmessages.h"
36 #include "bristol.h"
37 #include "bristolmidi.h"
38
39 bristolMidiMain bmidi;
40
41 extern int bristolMidiFindDev();
42 extern int bristolMidiFindFreeHandle();
43
44 extern int bristolMidiTCPOpen();
45 extern int bristolMidiOSSOpen();
46 extern int bristolMidiALSAOpen();
47 extern int bristolMidiSeqOpen();
48 extern int bristolMidiSeqKeyEvent();
49 extern int bristolMidiSeqPressureEvent();
50 extern int bristolMidiSeqPPressureEvent();
51 extern int bristolMidiSeqCCEvent();
52 #ifdef _BRISTOL_JACK_MIDI
53 extern int bristolMidiJackOpen();
54 #endif
55
56 extern int bristolMidiTCPClose();
57 extern int bristolMidiOSSClose();
58 extern int bristolMidiALSAClose();
59 extern int bristolMidiSeqClose();
60 #ifdef _BRISTOL_JACK_MIDI
61 extern int bristolMidiJackClose();
62 #endif
63
64 extern int bristolMidiSanity();
65 extern int bristolMidiDevSanity();
66 extern int bristolMidiALSARead();
67 extern int bristolMidiSeqRead();
68 extern int bristolPhysWrite();
69
70 extern int initMidiLib();
71
72 static char devname[64] = "localhost";
73
74 /*
75 * This is the generic code. Calls the desired (configured) drivers.
76 */
77 int
bristolMidiOpen(char * dev,int flags,int chan,int msgs,int (* callback)(),void * param)78 bristolMidiOpen(char *dev, int flags, int chan, int msgs, int (*callback)(),
79 void *param)
80 {
81 int handle, devnum;
82
83 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
84 printf("bristolMidiOpen(%s, %x)\n", dev, flags);
85
86 if (dev == NULL)
87 dev = devname;
88 else {
89 if ((strncmp(dev, "unix", 4) == 0) && (strlen(dev) > 5)
90 && (dev[4] == ':'))
91 snprintf(devname, 64, "%s", &dev[5]);
92 }
93
94 initMidiLib(flags);
95
96 /*
97 * The value of -1 indicates all channels, otherwise we are only interested
98 * in messages on the given channel.
99 */
100 if ((chan < -1) || (chan >= 16))
101 {
102 /*
103 * If this is a TCP connection then we can specify a channel greater
104 * than 1024 - it is interpreted as a TCP port, all channels.
105 */
106 if ((chan < 1024)
107 || ((flags & BRISTOL_CONNMASK & BRISTOL_CONN_TCP) == 0))
108 return(BRISTOL_MIDI_CHANNEL);
109 }
110
111 /*
112 * Make sure we have a handle available
113 */
114 if ((handle = bristolMidiFindFreeHandle()) < 0)
115 return(handle);
116
117 //bmidi.msgforwarder = NULL;
118 bmidi.handle[handle].handle = handle; /* That looks kind of wierd! */
119 bmidi.handle[handle].state = BRISTOL_MIDI_OK;
120 bmidi.handle[handle].channel = chan;
121 bmidi.handle[handle].dev = -1;
122 bmidi.handle[handle].flags = BRISTOL_MIDI_OK;
123 bmidi.handle[handle].messagemask = msgs;
124
125 /*
126 * We should then check to see if this dev is open, and if so link
127 * another handle to it. We should support multiple destinations of the
128 * same midi information.
129 */
130 if (((flags & BRISTOL_CONN_FORCE) == 0)
131 && ((devnum = bristolMidiFindDev(dev)) >= 0))
132 {
133 /*
134 * We have the device open, configure the new handle, and return it.
135 */
136 bmidi.dev[devnum].handleCount++;
137 bmidi.handle[handle].dev = devnum;
138 bmidi.handle[handle].callback = callback;
139 bmidi.handle[handle].param = param;
140 bmidi.handle[handle].flags = bmidi.dev[devnum].flags;
141
142 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
143 printf("reusing connection %x\n", bmidi.dev[devnum].flags);
144 printf("reusing connection %x\n", bmidi.dev[devnum].flags);
145
146 return(handle);
147 }
148
149 /*
150 * Now try and find a device that is free.
151 */
152 if ((devnum = bristolMidiFindDev(NULL)) < 0)
153 return(devnum);
154
155 bmidi.dev[devnum].state = BRISTOL_MIDI_OK;
156
157 /*
158 * We have early returns here and we should consider cleaning up. The thing
159 * is that if this call fails then typically the engine will exit. Future
160 * code may change that where we poke around for driver availability.
161 */
162 switch (flags & BRISTOL_CONNMASK) {
163 case BRISTOL_CONN_TCP:
164 if (handle != bristolMidiTCPOpen(dev, flags,
165 chan, msgs, callback, param, devnum, handle))
166 {
167 bmidi.dev[devnum].state = -1;
168 bmidi.handle[handle].state = -1;
169 return(BRISTOL_MIDI_DRIVER);
170 }
171 bmidi.handle[handle].channel = -1;
172 break;
173 case BRISTOL_CONN_MIDI:
174 if (handle != bristolMidiALSAOpen(dev, flags,
175 chan, msgs, callback, param, devnum, handle))
176 {
177 bmidi.dev[devnum].state = -1;
178 bmidi.handle[handle].state = -1;
179 return(BRISTOL_MIDI_DRIVER);
180 }
181 break;
182 case BRISTOL_CONN_OSSMIDI:
183 if (handle != bristolMidiOSSOpen(dev, flags,
184 chan, msgs, callback, param, devnum, handle))
185 {
186 bmidi.dev[devnum].state = -1;
187 bmidi.handle[handle].state = -1;
188 return(BRISTOL_MIDI_DRIVER);
189 }
190 break;
191 case BRISTOL_CONN_SEQ:
192 if (handle != bristolMidiSeqOpen(dev, flags,
193 chan, msgs, callback, param, devnum, handle))
194 {
195 bmidi.dev[devnum].state = -1;
196 bmidi.handle[handle].state = -1;
197 return(BRISTOL_MIDI_DRIVER);
198 }
199 break;
200 case BRISTOL_CONN_JACK:
201 #ifdef _BRISTOL_JACK_MIDI
202 if (handle != bristolMidiJackOpen(dev, flags,
203 chan, msgs, callback, devnum, devnum, handle))
204 {
205 bmidi.dev[devnum].state = -1;
206 bmidi.handle[handle].state = -1;
207 return(BRISTOL_MIDI_DRIVER);
208 }
209 #endif
210 bmidi.dev[devnum].fd = -1;
211 break;
212 case BRISTOL_CONN_UNIX:
213 default:
214 printf("conn type %x not supported\n", flags & BRISTOL_CONNMASK);
215 bmidi.dev[devnum].state = -1;
216 return(BRISTOL_MIDI_DRIVER);
217 break;
218 }
219
220 sprintf(bmidi.dev[devnum].name, "%s", dev);
221
222 bmidi.dev[devnum].state = BRISTOL_MIDI_OK;
223 bmidi.dev[devnum].handleCount = 1;
224 bmidi.dev[devnum].bufindex = 0;
225 bmidi.dev[devnum].bufcount = 0;
226 bmidi.dev[devnum].sequence = 0;
227 bmidi.handle[handle].dev = devnum;
228 bmidi.handle[handle].callback = callback;
229 bmidi.handle[handle].param = param;
230
231 printf("returning handle %i, flags %x, fd %i\n", handle, bmidi.dev[devnum].flags, bmidi.dev[devnum].fd);
232
233 return(handle);
234 }
235
236 void
bristolMidiRegisterForwarder(int (* msgforwarder)())237 bristolMidiRegisterForwarder(int (*msgforwarder)())
238 {
239 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
240 printf("register message forwarder\n");
241
242 bmidi.msgforwarder = msgforwarder;
243 }
244
245 int
bristolMidiOption(int handle,int option,int value)246 bristolMidiOption(int handle, int option, int value)
247 {
248 switch (option) {
249 case BRISTOL_NRP_DEBUG:
250 {
251 int i;
252
253 if (bristolMidiSanity(handle) < 0)
254 return(bristolMidiSanity(handle));
255
256 if (value == 0)
257 {
258 bmidi.flags &= ~BRISTOL_BMIDI_DEBUG;
259 for (i = 0; i < BRISTOL_MIDI_DEVCOUNT; i++)
260 if (bmidi.handle[i].dev >= 0)
261 bmidi.dev[bmidi.handle[i].dev].flags
262 &= ~_BRISTOL_MIDI_DEBUG;
263 } else if (value == 1) {
264 for (i = 0; i < BRISTOL_MIDI_DEVCOUNT; i++)
265 if (bmidi.handle[i].dev >= 0)
266 bmidi.dev[bmidi.handle[i].dev].flags
267 |= _BRISTOL_MIDI_DEBUG;
268 }
269 if (value >= 5)
270 bmidi.flags |= BRISTOL_BMIDI_DEBUG;
271 break;
272 }
273 case BRISTOL_NRP_FORWARD:
274 /* Disable event forwarding globally */
275 if (value == 0)
276 bmidi.flags &= ~(BRISTOL_MIDI_FORWARD|BRISTOL_MIDI_FHOLD);
277 else
278 bmidi.flags |= (BRISTOL_MIDI_FORWARD|BRISTOL_MIDI_FHOLD);
279 break;
280 case BRISTOL_NRP_MIDI_GO:
281 if (value == 0)
282 bmidi.flags &= ~(BRISTOL_MIDI_GO|BRISTOL_MIDI_FORWARD);
283 else
284 bmidi.flags |= (bmidi.flags & BRISTOL_MIDI_FHOLD)?
285 (BRISTOL_MIDI_GO|BRISTOL_MIDI_FORWARD):BRISTOL_MIDI_GO;
286 break;
287 case BRISTOL_NRP_SYSID_H:
288 bmidi.SysID = (bmidi.SysID & 0x0000ffff)
289 | ((value << 16) & 0xffff0000);
290 break;
291 case BRISTOL_NRP_SYSID_L:
292 bmidi.SysID = (bmidi.SysID & 0xffff0000) | (value & 0x0000ffff);
293 break;
294 case BRISTOL_NRP_REQ_SYSEX:
295 /*
296 * This is for the local side only and will prevent event forwarding
297 * to the GUI (primarily). It prevents events being duplicated on
298 * the receiving end
299 */
300 if (bristolMidiSanity(handle) < 0)
301 return(bristolMidiSanity(handle));
302
303 if (value == 1)
304 bmidi.handle[handle].flags |= BRISTOL_CONN_SYSEX;
305 else
306 bmidi.handle[handle].flags &= ~BRISTOL_CONN_SYSEX;
307 bmidi.handle[handle].flags |= BRISTOL_CONN_SYSEX;
308 break;
309 case BRISTOL_NRP_REQ_FORWARD:
310 if (bristolMidiSanity(handle) < 0)
311 return(bristolMidiSanity(handle));
312
313 if (value != 0)
314 bmidi.dev[bmidi.handle[handle].dev].flags
315 |= BRISTOL_CONN_FORWARD;
316 else
317 bmidi.dev[bmidi.handle[handle].dev].flags
318 &= ~BRISTOL_CONN_FORWARD;
319 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
320 printf(" Requested forward on handle %i %i %x %i\n",
321 handle,
322 value,
323 bmidi.dev[bmidi.handle[handle].dev].flags,
324 bmidi.handle[handle].dev);
325 break;
326 }
327
328 return(0);
329 }
330
331 int
bristolMidiClose(int handle)332 bristolMidiClose(int handle)
333 {
334 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
335 printf("bristolMidiClose(%i) %x\n", handle,
336 bmidi.dev[bmidi.handle[handle].dev].flags & BRISTOL_CONNMASK);
337
338 /*
339 * We close a handle, not a device. We need to clean out the handle, and if
340 * no other handles have this device open then close the physical device as
341 * well.
342 */
343 if (bristolMidiSanity(handle) < 0)
344 return(bristolMidiSanity(handle));
345
346 if (bmidi.dev[0].flags & BRISTOL_ACCEPT_SOCKET)
347 {
348 char filename[128];
349
350 snprintf(filename, 128, "/tmp/br.%s", devname);
351
352 unlink(filename);
353 }
354
355 switch (bmidi.dev[bmidi.handle[handle].dev].flags & BRISTOL_CONNMASK) {
356 case BRISTOL_CONN_OSSMIDI:
357 return(bristolMidiOSSClose(handle));
358 case BRISTOL_CONN_MIDI:
359 return(bristolMidiALSAClose(handle));
360 case BRISTOL_CONN_SEQ:
361 return(bristolMidiSeqClose(handle));
362 case BRISTOL_CONN_JACK:
363 #ifdef _BRISTOL_JACK_MIDI
364 return(bristolMidiJackClose(handle));
365 #endif
366 break;
367 case BRISTOL_CONN_TCP:
368 return(bristolMidiTCPClose(handle));
369 default:
370 printf("DID NOT CLOSE A HANDLE!!!\n");
371 }
372
373 return(BRISTOL_MIDI_DRIVER);
374 }
375
376 int
bristolMidiDevRead(int dev,bristolMidiMsg * msg)377 bristolMidiDevRead(int dev, bristolMidiMsg *msg)
378 {
379 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
380 printf("bristolMidiDevRead(%i)\n", dev);
381
382 if (bristolMidiDevSanity(dev) < 0)
383 return(bristolMidiDevSanity(dev));
384
385 /*
386 * ALSARead handles all the TCP interface as well. It should be reworked to
387 * manage OSS raw interfaces as well.....
388 */
389 switch (bmidi.dev[dev].flags & BRISTOL_CONNMASK) {
390 case BRISTOL_CONN_MIDI:
391 case BRISTOL_CONN_TCP:
392 case BRISTOL_CONN_OSSMIDI:
393 return(bristolMidiALSARead(dev, msg));
394 case BRISTOL_CONN_SEQ:
395 return(bristolMidiSeqRead(dev, msg));
396 }
397
398 return(BRISTOL_MIDI_DRIVER);
399 }
400
401 int
bristolGetMidiFD(int handle)402 bristolGetMidiFD(int handle)
403 {
404 return(bmidi.handle[handle].dev);
405 }
406
407 static bristolMidiMsg post;
408
409 void
bristolMidiPost(bristolMidiMsg * msg)410 bristolMidiPost(bristolMidiMsg *msg)
411 {
412 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
413 printf("post %i bytes\n", (int) sizeof(bristolMidiMsg));
414 bcopy(msg, &post, sizeof(bristolMidiMsg));
415 }
416
417 int
bristolMidiRead(int handle,bristolMidiMsg * msg)418 bristolMidiRead(int handle, bristolMidiMsg *msg)
419 {
420 int c = 50;
421
422 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
423 printf("bristolMidiRead(%i): %i/%i\n", handle,
424 bmidi.handle[handle].dev, bmidi.dev[bmidi.handle[handle].dev].fd);
425
426 if (bristolMidiSanity(handle) < 0)
427 return(bristolMidiSanity(handle));
428
429 // msg->command = 0xff;
430
431 if (bmidi.handle[handle].callback == NULL)
432 {
433 while (msg->command == 0xff)
434 {
435 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
436 printf("reading type %x\n",
437 bmidi.dev[bmidi.handle[handle].dev].flags);
438
439 switch (bmidi.dev[bmidi.handle[handle].dev].flags
440 & BRISTOL_CONNMASK)
441 {
442 case BRISTOL_CONN_TCP:
443 case BRISTOL_CONN_MIDI:
444 case BRISTOL_CONN_OSSMIDI:
445 if (bristolMidiALSARead(bmidi.handle[handle].dev, msg) < 0)
446 return(-1);
447 break;
448 case BRISTOL_CONN_SEQ:
449 if (bristolMidiSeqRead(bmidi.handle[handle].dev, msg) < 0)
450 return(-1);
451 break;
452 }
453 }
454
455 return(BRISTOL_MIDI_OK);
456 } else {
457 switch (bmidi.dev[handle].flags & BRISTOL_CONNMASK) {
458 case BRISTOL_CONN_TCP:
459 /*
460 * If this is the TCP port we should have a wait loop for a
461 * response from the engine, the event comes in another thread.
462 */
463 if (bmidi.dev[handle].fd < 0)
464 return(BRISTOL_MIDI_DRIVER);
465
466 while (post.channel == 0xff)
467 {
468 usleep(100000);
469
470 if (--c <= 0) {
471 int i;
472
473 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
474 printf("MIDI/TCP read failure\n");
475
476 for (i = 0; i < BRISTOL_MIDI_DEVCOUNT; i++)
477 {
478 if ((bmidi.dev[i].fd > 0)
479 && ((bmidi.dev[i].flags & BRISTOL_CONTROL_SOCKET) == 0)
480 && (bmidi.dev[i].flags & BRISTOL_CONN_TCP))
481 bristolMidiTCPClose(bmidi.dev[i].fd);
482 }
483
484 printf("closing down TCP sockets\n");
485
486 return(BRISTOL_MIDI_DRIVER);
487 }
488 }
489 bcopy(&post, msg, sizeof(bristolMidiMsg));
490 post.channel = 0xff;
491 return(BRISTOL_MIDI_OK);
492 case BRISTOL_CONN_MIDI:
493 case BRISTOL_CONN_OSSMIDI:
494 return(bristolMidiALSARead(bmidi.handle[handle].dev, msg));
495 case BRISTOL_CONN_SEQ:
496 return(bristolMidiSeqRead(bmidi.handle[handle].dev, msg));
497 }
498 }
499
500 return(BRISTOL_MIDI_DRIVER);
501 }
502
503 int
bristolMidiTerminate()504 bristolMidiTerminate()
505 {
506 printf("terminate MIDI signalling\n");
507 /*
508 * We need this since the library never actually returns when we are
509 * using the midiCheck routines. We are going to close all handles.
510 */
511 bmidi.flags = BRISTOL_MIDI_TERMINATE;
512
513 if (bmidi.dev[0].flags & BRISTOL_CONTROL_SOCKET)
514 {
515 char filename[128];
516
517 /*
518 * We should send an all_notes_off and terminate the socket layer with
519 * a REQSTOP
520 */
521 sleep(1);
522 close(bmidi.dev[0].fd);
523 bmidi.dev[0].fd = -1;
524
525 snprintf(filename, 128, "/tmp/br.%s", devname);
526
527 unlink(filename);
528 }
529
530 /*
531 * Free up the semaphores
532 */
533
534 return(0);
535 }
536
537 int
bristolMidiRawWrite(int dev,bristolMidiMsg * msg,int size)538 bristolMidiRawWrite(int dev, bristolMidiMsg *msg, int size)
539 {
540 if (bristolMidiDevSanity(dev) < 0)
541 return(bristolMidiDevSanity(dev));
542
543 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
544 printf("bristolMidiRawWrite (%x) %x/%i\n",
545 msg->command,
546 msg->channel,
547 size);
548
549 /*
550 * For short messages we are going to join the channel back together. This
551 * is not needed for SYSEX/Bristol messages.
552 */
553 if (msg->params.bristol.msgLen < 4)
554 {
555 unsigned char ch = (msg->command & 0xf0)|msg->channel;
556
557 if (bristolPhysWrite(bmidi.dev[dev].fd, (unsigned char *) &ch, 1) != 0)
558 return(1);
559 } else
560 if (bristolPhysWrite(bmidi.dev[dev].fd,
561 (unsigned char *) &msg->command, 1) != 0)
562 return(1);
563
564 if (msg->command != MIDI_SYSEX)
565 {
566 if (bristolPhysWrite(bmidi.dev[dev].fd,
567 (unsigned char *) &msg->params, size - 1) != 0)
568 return(1);
569 } else {
570 if (msg->params.bristol.msgType < 8)
571 {
572 if (bristolPhysWrite(bmidi.dev[dev].fd,
573 (unsigned char *) &msg->params, size) != 0)
574 return(1);
575 } else {
576 if (bristolPhysWrite(bmidi.dev[dev].fd,
577 (unsigned char *) &msg->params, 12) != 0)
578 return(1);
579 if (bristolPhysWrite(bmidi.dev[dev].fd,
580 (unsigned char *) msg->params.bristolt2.data,
581 msg->params.bristol.msgLen - 12) != 0)
582 return(1);
583 }
584 }
585
586 if (msg->command == MIDI_SYSEX)
587 {
588 unsigned char comm = MIDI_EOS;
589
590 return(bristolPhysWrite(bmidi.dev[dev].fd, (unsigned char *) &comm, 1));
591 }
592
593 return(0);
594 }
595
596 int
bristolMidiWrite(int dev,bristolMsg * msg,int size)597 bristolMidiWrite(int dev, bristolMsg *msg, int size)
598 {
599 unsigned char byte;
600
601 if (bristolMidiDevSanity(dev) < 0)
602 return(bristolMidiDevSanity(dev));
603
604 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
605 printf("bristolMidiWrite %i/%i, %i\n", dev, bmidi.dev[dev].fd, size);
606
607 byte = MIDI_SYSEX;
608 if (bristolPhysWrite(bmidi.dev[dev].fd, &byte, 1) != 0)
609 return(1);
610
611 if (bristolPhysWrite(bmidi.dev[dev].fd, (unsigned char *) msg, size) != 0)
612 return(1);
613
614 byte = MIDI_EOS;
615 if (bristolPhysWrite(bmidi.dev[dev].fd, &byte, 1) != 0)
616 return(1);
617
618 return(0);
619 }
620
621 int
bristolMidiControl(int handle,int channel,int operator,int controller,int value)622 bristolMidiControl(int handle, int channel, int operator, int controller,
623 int value)
624 {
625 unsigned char comm = 0xb0, ctr, val;
626
627 /* printf("Midi Control %i %i %i %i\n", channel, operator, controller, value); */
628
629 comm |= channel;
630 ctr = controller;
631 val = value & 0x7f;
632
633 switch (bmidi.dev[bmidi.handle[handle].dev].flags & BRISTOL_CONNMASK) {
634 case BRISTOL_CONN_SEQ:
635 return(bristolMidiSeqCCEvent(bmidi.handle[handle].dev,
636 operator, channel, controller, value));
637 default:
638 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &comm, 1);
639 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &ctr, 1);
640 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &val, 1);
641 break;
642 }
643
644 return(0);
645 }
646
647 int
bristolPitchEvent(int handle,int op,int channel,int key)648 bristolPitchEvent(int handle, int op, int channel, int key)
649 {
650 unsigned char comm = 0xe0, lsb, msb;
651
652 /* printf("pitch event %i %i %i\n", op, channel, key); */
653
654 comm |= channel;
655 lsb = key & 0x7f;
656 msb = (key >> 7) & 0x7f;
657
658 /* printf("Sending %i %i %i on %i\n", comm, msb, lsb, */
659 /* bmidi.dev[bmidi.handle[handle].dev].fd); */
660
661 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &comm, 1);
662 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &lsb, 1);
663 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &msb, 1);
664
665 return(0);
666 }
667
668 #ifdef NOT_THIS_DEBUG
669 static int toggle = 0;
670 #endif
671
672 int
bristolKeyEvent(int handle,int op,int channel,int key,int velocity)673 bristolKeyEvent(int handle, int op, int channel, int key, int velocity)
674 {
675 unsigned char comm;
676
677 key &= 0x7f;
678 velocity &= 0x7f;
679
680 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
681 printf("key event ch: %i, key: %i over fd %i\n", channel, key,
682 bmidi.dev[bmidi.handle[handle].dev].fd);
683
684 if (bristolMidiSanity(handle) < 0)
685 return(bristolMidiSanity(handle));
686
687 if (op == BRISTOL_EVENT_KEYON)
688 comm = MIDI_NOTE_ON | channel;
689 else
690 comm = MIDI_NOTE_OFF | channel;
691
692 switch (bmidi.dev[bmidi.handle[handle].dev].flags & BRISTOL_CONNMASK) {
693 case BRISTOL_CONN_SEQ:
694 return(bristolMidiSeqKeyEvent(bmidi.handle[handle].dev,
695 op, channel, key, velocity));
696 default:
697 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &comm, 1);
698 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &key, 1);
699 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &velocity, 1);
700 break;
701 }
702
703 return(0);
704 }
705
706 int
bristolPolyPressureEvent(int handle,int op,int channel,int key,int press)707 bristolPolyPressureEvent(int handle, int op, int channel, int key, int press)
708 {
709 unsigned char comm;
710
711 comm = 0xa0 | (channel & 0x0f);
712 key &= 0x7f;
713 press &= 0x7f;
714
715 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
716 printf("pressure ch: %i, pressure: %i over fd %i\n", channel, press,
717 bmidi.dev[bmidi.handle[handle].dev].fd);
718
719 if (bristolMidiSanity(handle) < 0)
720 return(bristolMidiSanity(handle));
721
722 switch (bmidi.dev[bmidi.handle[handle].dev].flags & BRISTOL_CONNMASK) {
723 case BRISTOL_CONN_SEQ:
724 return(bristolMidiSeqPPressureEvent(bmidi.handle[handle].dev,
725 op, channel, key, press));
726 default:
727 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &comm, 1);
728 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &key, 1);
729 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &press, 1);
730 }
731
732 return(0);
733 }
734
735 int
bristolPressureEvent(int handle,int op,int channel,int press)736 bristolPressureEvent(int handle, int op, int channel, int press)
737 {
738 unsigned char comm;
739
740 comm = 0xd0 | (channel & 0x0f);
741 press &= 0x7f;
742
743 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
744 printf("pressure ch: %i, pressure: %i over fd %i\n", channel, press,
745 bmidi.dev[bmidi.handle[handle].dev].fd);
746
747 if (bristolMidiSanity(handle) < 0)
748 return(bristolMidiSanity(handle));
749
750 switch (bmidi.dev[bmidi.handle[handle].dev].flags & BRISTOL_CONNMASK) {
751 case BRISTOL_CONN_SEQ:
752 return(bristolMidiSeqPressureEvent(bmidi.handle[handle].dev,
753 op, channel, press));
754 default:
755 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &comm, 1);
756 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &press, 1);
757 }
758
759 return(0);
760 }
761
762 /*
763 * This is the second implementation, the previous uses superfluous params....
764 */
765 int
bristolMidiSendControlMsg(int handle,int channel,int ctrl,int value)766 bristolMidiSendControlMsg(int handle, int channel, int ctrl, int value)
767 {
768 unsigned char comm = 0xb0;
769
770 comm |= channel;
771 ctrl &= 0x7f;
772 value &= 0x7f;
773
774 /* printf("control event %i %i %i\n", channel, ctrl, value); */
775
776 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &comm, 1);
777 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &ctrl, 1);
778 bristolPhysWrite(bmidi.dev[bmidi.handle[handle].dev].fd, &value, 1);
779
780 return(0);
781 }
782
783 int
bristolMidiSendNRP(int handle,int channel,int nrp,int value)784 bristolMidiSendNRP(int handle, int channel, int nrp, int value)
785 {
786 /*
787 * Send the NRP index.
788 */
789 bristolMidiSendControlMsg(handle, channel, 99, (nrp >> 7) & 0x7f);
790 bristolMidiSendControlMsg(handle, channel, 98, nrp & 0x7f);
791
792 /*
793 * Send the controller values.
794 */
795 bristolMidiSendControlMsg(handle, channel, 6, (value >> 7) & 0x7f);
796 bristolMidiSendControlMsg(handle, channel, 38, value & 0x7f);
797
798 return(0);
799 }
800
801 int
bristolMidiSendRP(int handle,int channel,int nrp,int value)802 bristolMidiSendRP(int handle, int channel, int nrp, int value)
803 {
804 /*
805 * Send the NRP index.
806 */
807 bristolMidiSendControlMsg(handle, channel, 101, (nrp >> 7) & 0x7f);
808 bristolMidiSendControlMsg(handle, channel, 100, nrp & 0x7f);
809
810 /*
811 * Send the controller values.
812 */
813 bristolMidiSendControlMsg(handle, channel, 6, (value >> 7) & 0x7f);
814 bristolMidiSendControlMsg(handle, channel, 38, value & 0x7f);
815
816 return(0);
817 }
818
819 int
bristolMidiSendKeyMsg(int handle,int channel,int operator,int key,int volume)820 bristolMidiSendKeyMsg(int handle, int channel, int operator, int key, int volume)
821 {
822 if (operator != BRISTOL_EVENT_KEYON)
823 operator = BRISTOL_EVENT_KEYOFF;
824
825 bristolKeyEvent(bmidi.handle[handle].dev, operator, channel, key, volume);
826
827 return(0);
828 }
829
830 static int velocity = 0;
831
832 int
bristolMidiSendMsg(int handle,int channel,int operator,int controller,int value)833 bristolMidiSendMsg(int handle, int channel, int operator, int controller,
834 int value)
835 {
836 bristolMsg msg;
837
838 bzero(&msg, sizeof(bristolMsg));
839
840 if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
841 {
842 printf("bristolMidiSendMsg(%i, %i, %i, %i, %i)\n",
843 handle, channel, operator, controller, value);
844 printf("%i %i %i\n", handle, bmidi.handle[handle].dev,
845 bmidi.dev[bmidi.handle[handle].dev].fd);
846 }
847
848 if ((value > C_RANGE_MIN_1) || (value < 0))
849 printf("controller %i/%i value %i outside range\n",
850 operator, controller, value);
851
852 value &= C_RANGE_MIN_1;
853
854 /*
855 * Key on and off events are NOT sent as system messages, but as normal
856 * key events on the control channel. As such they require separate formats.
857 */
858 if (operator == BRISTOL_EVENT_PITCH)
859 {
860 bristolPitchEvent(bmidi.handle[handle].dev, operator, channel, value);
861 return(0);
862 }
863
864 if ((operator == BRISTOL_EVENT_KEYON) || (operator == BRISTOL_EVENT_KEYOFF))
865 {
866 if ((bmidi.flags & BRISTOL_BMIDI_DEBUG) && (++velocity > 127))
867 {
868 velocity = 0;
869 printf("velocity %i\n", velocity);
870 } else
871 velocity = 120;
872
873 return(bristolKeyEvent(bmidi.handle[handle].dev, operator,
874 channel, value & BRISTOL_PARAMMASK, velocity));
875 }
876 /*
877 * We are going to send this through to the control port as a basic format
878 * message. The parameter is not going to be scaled, just given as a value
879 * from 0 to 16383. The receiver can decide how to scale the value.
880 */
881 msg.SysID = (bmidi.SysID >> 24) & 0x0ff;
882 msg.L = (bmidi.SysID >> 16) & 0x0ff;
883 msg.a = (bmidi.SysID >> 8) & 0x0ff;
884 msg.b = bmidi.SysID & 0x0ff;
885
886 msg.msgLen = sizeof(bristolMsg);
887 msg.msgType = MSG_TYPE_PARAM;
888
889 msg.channel = channel;
890 msg.from = handle;
891 msg.operator = operator;
892 msg.controller = controller;
893 msg.valueLSB = value & 0x007f;
894 msg.valueMSB = (value >> 7) & 0x007f;
895
896 // bristolMsgPrint(&msg);
897
898 post.channel = 0xff;
899
900 bristolMidiWrite(bmidi.handle[handle].dev, &msg, sizeof(bristolMsg));
901
902 return(0);
903 }
904
905