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