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 /*#define DEBUG */
23
24 #include <sys/time.h>
25 #include <time.h>
26 #include <string.h>
27
28 #include <bristolmidi.h>
29 #include <bristolmidieventnames.h>
30 #include "bristolmessages.h"
31
32 extern bristolMidiMain bmidi;
33
34 /* We should put this into a structure */
35 static int NonOrRegistered = 0, NonOrRegisteredValue = 0;
36
37 void
bristolMidiPrintGM2(bristolMidiMsg * msg)38 bristolMidiPrintGM2(bristolMidiMsg *msg)
39 {
40 printf("GM2: base %i from %i/%i\n",
41 msg->GM2.c_id, msg->GM2.c_id_coarse, msg->GM2.c_id_fine);
42 printf(" %i/%i = %i %f\n",
43 msg->GM2.coarse, msg->GM2.fine, msg->GM2.intvalue, msg->GM2.value);
44 }
45
46 void
bristolMsgPrint(bristolMsg * msg)47 bristolMsgPrint(bristolMsg *msg)
48 {
49 printf("ID 0x%x%x%x%x\n", msg->SysID, msg->L, msg->a, msg->b);
50 printf(" msgLen %i\n", msg->msgLen);
51 printf(" msgType %i\n", msg->msgType);
52 printf(" channel %i\n", msg->channel);
53 printf(" from %i\n", msg->from);
54 printf(" op %i\n", msg->operator);
55 printf(" cont %i\n", msg->controller);
56 printf(" MSB %i\n", msg->valueMSB);
57 printf(" LSB %i\n", msg->valueLSB);
58 printf(" value %i/%x\n",
59 msg->valueLSB + (msg->valueMSB<<7),
60 msg->valueLSB + (msg->valueMSB<<7));
61 }
62
63 void
bristolMidiPrint(bristolMidiMsg * msg)64 bristolMidiPrint(bristolMidiMsg *msg)
65 {
66 int command = ((msg->command & MIDI_COMMAND_MASK) & ~MIDI_STATUS_MASK) >> 4;
67
68 switch (msg->command & MIDI_COMMAND_MASK) {
69 case MIDI_SYSTEM:
70 printf("system");
71 if ((msg->params.bristol.SysID == ((bmidi.SysID >> 24) & 0x0ff))
72 && (msg->params.bristol.L == ((bmidi.SysID >> 16) & 0x0ff))
73 && (msg->params.bristol.a == ((bmidi.SysID >> 8) & 0x0ff))
74 && (msg->params.bristol.b == (bmidi.SysID & 0x0ff)))
75 {
76 printf(" bristol (%i)\n", msg->sequence);
77 bristolMsgPrint(&msg->params.bristol);
78 } else
79 printf("\n");
80 break;
81 case MIDI_NOTE_ON:
82 printf("%s (%i) ch %i: %i, velocity %i\n", eventNames[command],
83 msg->sequence,
84 msg->channel, msg->params.key.key, msg->params.key.velocity);
85 break;
86 case MIDI_NOTE_OFF:
87 printf("%s (%i) ch %i: %i, velocity %i\n", eventNames[command],
88 msg->sequence,
89 msg->channel, msg->params.key.key, msg->params.key.velocity);
90 break;
91 case MIDI_POLY_PRESS:
92 printf("%s (%i) ch %i: key %i, pressure %i\n", eventNames[command],
93 msg->sequence, msg->channel,
94 msg->params.pressure.key, msg->params.pressure.pressure);
95 break;
96 case MIDI_CONTROL:
97 if (controllerName[msg->params.controller.c_id] == NULL)
98 printf("%s (%i) ch %i: c_id %i, c_val %i\n",
99 eventNames[command],
100 msg->sequence,
101 msg->channel,
102 msg->params.controller.c_id,
103 msg->params.controller.c_val);
104 else
105 printf("%s (%i) ch %i: %s, value %i\n", eventNames[command],
106 msg->sequence,
107 msg->channel,
108 controllerName[msg->params.controller.c_id],
109 msg->params.controller.c_val);
110 break;
111 case MIDI_PROGRAM:
112 printf("%s (%i) ch %i: p_id %i\n", eventNames[command],
113 msg->sequence,
114 msg->channel, msg->params.program.p_id);
115 break;
116 case MIDI_CHAN_PRESS:
117 printf("%s (%i) ch %i: pressure %i\n", eventNames[command],
118 msg->sequence,
119 msg->channel, msg->params.channelpress.pressure);
120 break;
121 case MIDI_PITCHWHEEL:
122 printf("%s (%i) ch %i: msb %i, lsb %i\n", eventNames[command],
123 msg->sequence,
124 msg->channel, msg->params.pitch.msb, msg->params.pitch.lsb);
125 break;
126 }
127 }
128
129 /*
130 * This will take the specified messages and recode the GM2 portion for things
131 * such as coarse/fine controllers. It will also take the values of the coded
132 * values and turn them into a floating point value.
133 *
134 * This stuff is painful for several reasons - some GM2 values denote coarse
135 * and fine, others denote semitone and cents, etc, some are integer rather
136 * than floats. It might be better to call this later if parsing is required.
137 *
138 * We also need to have a midi controller mapping system. If a controller is
139 * remapped then we should consider it to be coarse only?
140 *
141 * The engine has a version of this code with different parameterisation. It
142 * is in midihandlers and we should pull it out into the library.
143 */
144 void
bristolMidiToGM2(int GM2values[128],int midimap[128],u_char valuemap[128][128],bristolMidiMsg * msg)145 bristolMidiToGM2(int GM2values[128], int midimap[128], u_char valuemap[128][128], bristolMidiMsg *msg)
146 {
147 if (msg->command != MIDI_CONTROL)
148 {
149 /*
150 * This may be counter productive?
151 */
152 msg->GM2.c_id = -1;
153 msg->GM2.value = 0;
154 return;
155 }
156
157 /*
158 * Apply the mappings already if any are defined. This is just a controller
159 * mapping however we also want to apply a value mapping this early. It
160 * is something to the effect of the following however this table needs to
161 * be initialised
162 */
163 if (valuemap != NULL)
164 msg->params.controller.c_val = valuemap[msg->params.controller.c_id]
165 [msg->params.controller.c_val];
166 if (midimap != NULL)
167 msg->params.controller.c_id = midimap[msg->params.controller.c_id];
168
169 /*
170 * Keep a copy of the controller setting for later use.
171 */
172 GM2values[msg->params.controller.c_id] = msg->params.controller.c_val;
173
174 /*
175 * This are true for all the controllers, but the later ones may have
176 * specific modifications
177 */
178 msg->GM2.c_id = msg->params.controller.c_id;
179 msg->GM2.value = ((float) msg->params.controller.c_val) / 127.0f;
180 msg->GM2.intvalue = msg->params.controller.c_val;
181 msg->GM2.coarse = msg->params.controller.c_val;
182 msg->GM2.fine = 0;
183
184 /*
185 * These are coarse of the course/fine controls
186 */
187 if (msg->params.controller.c_id < 14)
188 {
189 msg->GM2.coarse = msg->params.controller.c_val;
190 msg->GM2.fine = GM2values[msg->params.controller.c_id + 32];
191 msg->GM2.intvalue = (msg->GM2.coarse << 7) + msg->GM2.fine;
192 msg->GM2.value = ((float) msg->GM2.intvalue) / 16383.0f;
193 return;
194 }
195
196 if (msg->params.controller.c_id < 32)
197 return;
198
199 /*
200 * Fine controls for the first 14 coarse/fine controllers.
201 */
202 if (msg->params.controller.c_id < 46)
203 {
204 /* msg->GM2.c_id -= 32; */
205 msg->GM2.fine = msg->params.controller.c_val;
206 msg->GM2.coarse = GM2values[msg->params.controller.c_id - 32];
207 msg->GM2.intvalue = (msg->GM2.coarse << 7) + msg->GM2.fine;
208 msg->GM2.value = ((float) msg->GM2.intvalue) / 16383.0f;
209 /*
210 * We should change the controller to be NRP/RP and the value to
211 * reflect the associated controller setting:
212 *
213 * c_id = N/RP
214 * find = N/RP value
215 * value/intvalue = that controller value.
216 *
217 * In other words, never deliver a c_id 38.
218 */
219 if (msg->params.controller.c_id == 38) {
220 msg->GM2.c_id = NonOrRegistered;
221 msg->GM2.coarse = NonOrRegisteredValue;
222 }
223 return;
224 }
225
226 if (msg->params.controller.c_id < 80)
227 return;
228
229 /*
230 * These are 4 buttons.
231 if (msg->params.controller.c_id < 84)
232 {
233 if (msg->GM2.intvalue > 63)
234 msg->GM2.value = 1.0;
235 else
236 msg->GM2.value = 0.0;
237 return;
238 }
239 */
240
241 if (msg->params.controller.c_id < 96)
242 return;
243
244 /*
245 * These are 2 data entry buttons.
246 if (msg->params.controller.c_id < 98)
247 {
248 if (msg->GM2.intvalue > 63)
249 msg->GM2.value = 1.0;
250 else
251 msg->GM2.value = 0.0;
252 return;
253 }
254 */
255
256 /*
257 * Non Registered Parameter Numbers.
258 */
259 if ((msg->params.controller.c_id == 98)
260 || (msg->params.controller.c_id == 99))
261 {
262 msg->GM2.c_id = 99;
263 msg->GM2.fine = GM2values[98];
264 msg->GM2.coarse = GM2values[99];
265 msg->GM2.intvalue = (msg->GM2.coarse << 7) + msg->GM2.fine;
266 msg->GM2.value = ((float) msg->GM2.intvalue) / 16383.0f;
267 NonOrRegistered = MIDI_GM_NRP;
268 NonOrRegisteredValue = msg->GM2.intvalue;
269 return;
270 }
271
272 /*
273 * Registered Parameter Numbers.
274 */
275 if ((msg->params.controller.c_id == 100)
276 || (msg->params.controller.c_id == 101))
277 {
278 msg->GM2.c_id = 101;
279 msg->GM2.fine = GM2values[100];
280 msg->GM2.coarse = GM2values[101];
281 msg->GM2.intvalue = (msg->GM2.coarse << 7) + msg->GM2.fine;
282 msg->GM2.value = ((float) msg->GM2.intvalue) / 16383.0f;
283 NonOrRegistered = MIDI_GM_RP;
284 NonOrRegisteredValue = msg->GM2.intvalue;
285 return;
286 }
287
288 /*
289 * local Keyboard
290 if (msg->params.controller.c_id == 122)
291 {
292 if (msg->GM2.intvalue > 63)
293 msg->GM2.value = 1.0;
294 else
295 msg->GM2.value = 0.0;
296 return;
297 }
298 */
299 }
300
301 char databytes[1024];
302
303 static void
buildOneMsg(unsigned char p1,unsigned char p2,int dev,bristolMidiMsg * msg)304 buildOneMsg(unsigned char p1, unsigned char p2, int dev, bristolMidiMsg *msg)
305 {
306 #ifdef DEBUG
307 printf("buildOneMsg(%x, %x, %i), comm %x\n", p1, p2, dev,
308 bmidi.dev[dev].lastcommand);
309 #endif
310
311 gettimeofday(&(msg->timestamp), 0);
312
313 /*
314 * We have enough message capacity, put information into the message buffer
315 * and return.
316 */
317 msg->command = bmidi.dev[dev].lastcommand;
318 msg->channel = bmidi.dev[dev].lastchan;
319
320 msg->sequence = bmidi.dev[dev].sequence++;
321
322 if (p1 != 0xff)
323 {
324 msg->params.key.key = p1;
325 msg->params.key.velocity = p2;
326 if (bmidi.dev[dev].flags & BRISTOL_CONN_JACK)
327 msg->params.key.flags = BRISTOL_KF_JACK;
328 else if (bmidi.dev[dev].flags & BRISTOL_CONN_TCP)
329 msg->params.key.flags = BRISTOL_KF_TCP;
330 else
331 msg->params.key.flags = BRISTOL_KF_RAW;
332 }
333
334 switch (msg->command) {
335 case MIDI_SYSTEM:
336 if (msg->params.bristol.msgType >= 8)
337 {
338 // printf("T2 data: %s\n", databytes);
339 msg->params.bristolt2.data = databytes;
340 }
341 break;
342 case MIDI_NOTE_OFF:
343 case MIDI_NOTE_ON:
344 case MIDI_POLY_PRESS:
345 case MIDI_CONTROL:
346 case MIDI_PITCHWHEEL:
347 msg->params.bristol.msgLen = 3;
348 break;
349 case MIDI_PROGRAM:
350 case MIDI_CHAN_PRESS:
351 msg->params.bristol.msgLen = 2;
352 break;
353 }
354 }
355
356 static int
parseCommand(unsigned char comm,int dev)357 parseCommand(unsigned char comm, int dev)
358 {
359 #ifdef int
360 printf("parseCommand(%x, %i)\n", comm, dev);
361 #endif
362
363 /*
364 * We have a new command, save any interesting device state infomation.
365 */
366 bmidi.dev[dev].lastchan = comm & MIDI_CHAN_MASK;
367 bmidi.dev[dev].lastcommand = comm & MIDI_COMMAND_MASK;
368
369 /*
370 * Set up how many more bytes we need.
371 */
372 switch (bmidi.dev[dev].lastcommand) {
373 case MIDI_SYSTEM:
374 if (comm == MIDI_EOS)
375 {
376 /*
377 if (bmidi.dev[dev].sysex.count != sizeof(bristolMsg))
378 printf("Was bad sysex message (wrong length)\n");
379 else
380 printf("Was right length message: %x\n",
381 bmidi.dev[dev].sysex.count);
382 */
383 bmidi.dev[dev].sysex.count = 0;
384 bmidi.dev[dev].lastcommand = 0;
385 }
386 if (comm == MIDI_SYSEX)
387 {
388 /*printf("SYSEX checks\n"); */
389 bmidi.dev[dev].sysex.count = 0;
390 return(1);
391 }
392 break;
393 case MIDI_PROGRAM:
394 case MIDI_CHAN_PRESS:
395 bmidi.dev[dev].lastcommstate =
396 BRISTOL_CHANSTATE_WAIT_1;
397 break;
398 case MIDI_NOTE_ON:
399 case MIDI_NOTE_OFF:
400 case MIDI_POLY_PRESS:
401 case MIDI_PITCHWHEEL:
402 bmidi.dev[dev].lastcommstate =
403 BRISTOL_CHANSTATE_WAIT_2;
404 break;
405 default:
406 break;
407 }
408
409 return(0);
410 }
411
412 int
bristolMidiRawToMsg(unsigned char * buff,int count,int index,int dev,bristolMidiMsg * msg)413 bristolMidiRawToMsg(unsigned char *buff, int count, int index, int dev,
414 bristolMidiMsg *msg)
415 {
416 int parsed = 0;
417
418 msg->command = -1;
419 msg->offset = 0;
420
421 /*
422 * Attempt to parse a raw message buffer. If we can resolve a complete
423 * message then return the number we have parsed.
424 */
425 if (count <= 0)
426 return(0);
427
428 #ifdef DEBUG
429 printf("bristolMidiRawToMsg(%x, %i, %i, %i) [%x]\n",
430 (size_t) buff, count, index, dev, buff[index]);
431 #endif
432
433 /*
434 * Although we know that we have buffered data, we do not know if we are
435 * being given complete messages by the raw interface - it could be byte by
436 * byte, or chunks of a large sysex. Parse the data byte by byte, and see
437 * if we can put together complete messages.
438 *
439 * Check out our current command in operation on this device:
440 */
441 bmidi.dev[dev].sysex.count = 0;
442 while (parsed < count)
443 {
444 /*
445 * If this is a status byte, find out what we cn do with it. Otherwise
446 * look for data commands.
447 if ((bmidi.dev[dev].lastcommand != MIDI_SYSTEM) &&
448 (buff[index] & MIDI_STATUS_MASK))
449 */
450 if (buff[index] & MIDI_STATUS_MASK) {
451 parseCommand(buff[index++], dev);
452 return(1);
453 } else {
454 switch (bmidi.dev[dev].lastcommand)
455 {
456 /*
457 * Looking for one more byte. We have it, since we made it here.
458 */
459 case MIDI_PROGRAM:
460 case MIDI_CHAN_PRESS:
461 buildOneMsg(buff[index], -1, dev, msg);
462 return(parsed + 1);
463 /*
464 * Looking for two more bytes, if they are there.
465 */
466 case MIDI_NOTE_ON:
467 case MIDI_CONTROL:
468 case MIDI_NOTE_OFF:
469 case MIDI_POLY_PRESS:
470 case MIDI_PITCHWHEEL:
471 /*
472 * if we do not have enough bytes, return.
473 */
474 if ((count - parsed) < 2)
475 return(0);
476
477 /*
478 * Otherwise, go get the command, checking for buffer wrap.
479 * We also need to make sure that the next spare byte is not
480 * a status byte - ie, that we have not binned a byte in the
481 * midi cable.
482 */
483 if ((index + 1) == BRISTOL_MIDI_BUFSIZE)
484 {
485 if (buff[0] & MIDI_STATUS_MASK)
486 break;
487 else
488 buildOneMsg(buff[index], buff[0], dev, msg);
489 } else {
490 if (buff[index+1] & MIDI_STATUS_MASK)
491 break;
492 else
493 buildOneMsg(buff[index], buff[index+1], dev, msg);
494 }
495
496 return(parsed + 2);
497 case MIDI_SYSTEM:
498 /*
499 * Sysex management requires we read bytes until we get
500 * a status byte, and it should minimally be blocking on
501 * this device. Assume, since we have been sent this, that
502 * it is going to be a bristolMidiMsg, and look for the
503 * first few bytes. If it is SLab we are OK, otherwise we
504 * have an issue, and should read to next status byte then
505 * dump the data.
506 *
507 * Looks bad? Turn the bm message into an array, and index
508 * it depending on which byte we have. Could do with some
509 * error handling!
510 */
511 if (bmidi.dev[dev].sysex.count < 12)
512 ((char *) &msg->params.bristol)
513 [bmidi.dev[dev].sysex.count] = buff[index];
514 bmidi.dev[dev].sysex.count++;
515
516 if (bmidi.dev[dev].sysex.count == 4)
517 {
518 /*
519 * If this is not a SLab message, then set the
520 * current state to unknown.
521 */
522 if ((msg->params.bristol.SysID
523 != ((bmidi.SysID >> 24) & 0x07f))
524 || (msg->params.bristol.L
525 != ((bmidi.SysID >> 16) & 0x07f))
526 || (msg->params.bristol.a
527 != ((bmidi.SysID >> 8) & 0x07f))
528 || (msg->params.bristol.b
529 != (bmidi.SysID & 0x07f)))
530 {
531 int rv = bmidi.dev[dev].sysex.count;
532
533 printf("unrecognised SYSEX ID %x %x %x %x (%i)\n",
534 msg->params.bristol.SysID,
535 msg->params.bristol.L,
536 msg->params.bristol.a,
537 msg->params.bristol.b,
538 index
539 );
540
541 bmidi.dev[dev].lastcommand = 0;
542 bmidi.dev[dev].sysex.count = 0;
543 return(rv);
544 }
545 //else printf("SLab SYSEX type\n");
546 }
547
548 if (bmidi.dev[dev].sysex.count == sizeof(bristolMsg))
549 {
550 /* Might be type 2 messages */
551 if (msg->params.bristol.msgType > 7)
552 {
553 //printf("Received a type 2 message\n");
554 if ((index+=1) >= BRISTOL_MIDI_BUFSIZE)
555 index = 0;
556 parsed++;
557 continue;
558 }
559
560 if (bmidi.dev[dev].sysex.count
561 == msg->params.bristol.msgLen)
562 {
563 // printf("Received a SLab SYSEX message\n");
564 buildOneMsg(0xff, 0xff, dev, msg);
565 bmidi.dev[dev].lastcommand = 0;
566 return(msg->params.bristol.msgLen);
567 } else {
568 int rv = bmidi.dev[dev].sysex.count;
569 // printf("unknown SYSEX message\n");
570 bmidi.dev[dev].lastcommand = 0;
571 bmidi.dev[dev].sysex.count = 0;
572 return(rv);
573 }
574 }
575
576 if (bmidi.dev[dev].sysex.count >= sizeof(bristolMsg))
577 {
578 if ((msg->params.bristol.msgLen >= 1023)
579 || (msg->params.bristol.msgType < 8))
580 {
581 int rv = bmidi.dev[dev].sysex.count;
582 printf("bad SLab SYSEX message length\n");
583 bmidi.dev[dev].lastcommand = 0;
584 bmidi.dev[dev].sysex.count = 0;
585 return(rv);
586 }
587
588 databytes[bmidi.dev[dev].sysex.count - 1
589 - sizeof(bristolMsg)] = buff[index];
590
591 //printf("inserted %x, %s\n", buff[index], databytes);
592
593 if (bmidi.dev[dev].sysex.count
594 >= msg->params.bristol.msgLen)
595 {
596 /* This is for strings but works generally */
597 databytes[bmidi.dev[dev].sysex.count
598 - sizeof(bristolMsg)] = '\0';
599 buildOneMsg(0xff, 0xff, dev, msg);
600 bmidi.dev[dev].lastcommand = 0;
601 return(msg->params.bristol.msgLen);
602 }
603 }
604 break;
605 default:
606 /*
607 * Looking for a recognised command:
608 if (buff[index] & MIDI_STATUS_MASK)
609 parseCommand(buff[index], dev);
610 */
611 index++;
612
613 return(1);
614 }
615 }
616
617 /*
618 * Look after our indices
619 */
620 if ((index+=1) >= BRISTOL_MIDI_BUFSIZE)
621 index = 0;
622
623 parsed++;
624 }
625
626 return(0);
627 }
628
629