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 #include <stdio.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <math.h>
28 
29 #include "bristolmessages.h"
30 #include "bristol.h"
31 #include "bristolmidi.h"
32 
33 #ifdef _BRISTOL_JACK_MIDI
34 #include <jack/jack.h>
35 #include <jack/midiport.h>
36 
37 extern bristolMidiMain bmidi;
38 
39 /* We only have one of these for a single registration per engine. */
40 static jack_client_t *client = NULL;
41 static int deviceIndex = -1;
42 
43 static jack_port_t *input_port = NULL;
44 extern void checkcallbacks(bristolMidiMsg *);
45 
46 void
jackMidiRegisterPort(jack_port_t * midi_input_port)47 jackMidiRegisterPort(jack_port_t *midi_input_port)
48 {
49 	input_port = midi_input_port;
50 }
51 
52 int
jackMidiRoutine(jack_nframes_t nframes,void * arg)53 jackMidiRoutine(jack_nframes_t nframes, void *arg)
54 {
55 	int i;
56 	void* port_buf;
57 	jack_midi_event_t in_event;
58 	jack_nframes_t event_count;
59 	bristolMidiMsg msg;
60 
61 	if (input_port == NULL)
62 		return(0);
63 
64 	port_buf = jack_port_get_buffer(input_port, nframes);
65 	event_count = jack_midi_get_event_count(port_buf);
66 
67 	bmidi.dev[deviceIndex].flags = BRISTOL_CONN_JACK|0x40000000;
68 
69 	if (event_count <= 0)
70 		return(0);
71 
72 	/*
73 	else
74 		printf("received %i events\n", event_count);
75 `	*/
76 	for (i = 0; i < event_count; i++)
77 	{
78 		memset(&in_event, 0, sizeof(jack_midi_event_t));
79 		memset(&msg, 0, sizeof(bristolMidiMsg));
80 
81 		if (jack_midi_event_get(&in_event, port_buf, i) != 0)
82 			continue;
83 
84 		/*
85 		printf("    event %d time is %d. %x/%i/%i (%i)\n", i, in_event.time,
86 			*(in_event.buffer), *(in_event.buffer+1), *(in_event.buffer+2),
87 			in_event.size);
88 		*/
89 
90 		/*
91 		 * Convert these events into our internal format and then have then
92 		 * dispatched. We could probably call a quite early routine since we
93 		 * appear to have reasonably raw midi.
94 		 *
95 		 * Jack always gives me a status byte. We need to parse this then parse
96 		 * the actual midi message.
97 		 */
98 		bristolMidiRawToMsg(in_event.buffer, in_event.size, 0, deviceIndex,
99 			&msg);
100 		if (bristolMidiRawToMsg(in_event.buffer + 1, in_event.size - 1, 0,
101 			deviceIndex, &msg) > 0)
102 		{
103 			msg.params.bristol.msgLen = in_event.size;
104 			msg.params.bristol.from = deviceIndex;
105 			msg.offset = in_event.time;
106 
107 			checkcallbacks(&msg);
108 		} else if (bmidi.flags & BRISTOL_BMIDI_DEBUG)
109 			printf("unknown jack midi event\n");
110 	}
111 
112 	/*
113 	jack_midi_event_get(&in_event, port_buf, 0);
114 
115 	for (i=0; i<nframes; i++)
116 	{
117 		if ((in_event.time == i) && (event_index < event_count))
118 		{
119 			if( ((*(in_event.buffer) & 0xf0)) == 0x90 )
120 			{
121 				note = *(in_event.buffer + 1);
122 				note_on = 1.0;
123 			}
124 			else if( ((*(in_event.buffer)) & 0xf0) == 0x80 )
125 			{
126 				note = *(in_event.buffer + 1);
127 				note_on = 0.0;
128 			}
129 			event_index++;
130 			if(event_index < event_count)
131 				jack_midi_event_get(&in_event, port_buf, event_index);
132 		}
133 	}
134 	*/
135 	return 0;
136 }
137 
jack_midi_shutdown(void * arg)138 void jack_midi_shutdown(void *arg)
139 {
140 	exit(1);
141 }
142 
143 int
bristolMidiJackOpen(char * devname,int flags,int chan,int messages,int (* callback)(),void * param,int dev,int handle)144 bristolMidiJackOpen(char *devname, int flags, int chan, int messages,
145 int (*callback)(), void *param, int dev, int handle)
146 {
147 	printf("bristolMidiJackOpen(%s, %i, %x)\n", devname, dev, flags);
148 
149 	deviceIndex = dev;
150 
151 //	bmidi.flags &= ~BRISTOL_MIDI_FORWARD;
152 //	bmidi.dev[dev].flags = BRISTOL_CONN_JACK|0x40000000;
153 
154 	if (client == 0)
155 	{
156 		if ((client = jack_client_open(devname, 0, NULL)) == 0)
157 		{
158 			fprintf(stderr, "jack server not running?\n");
159 			return 1;
160 		}
161 		printf("registered jack midi name %s\n", devname);
162 
163 		jack_set_process_callback(client, jackMidiRoutine, (void *) dev);
164 
165 		jack_on_shutdown(client, jack_midi_shutdown, 0);
166 
167 		input_port = jack_port_register(client, "midi_in",
168 			JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
169 
170 		if (jack_activate(client))
171 		{
172 			fprintf(stderr, "cannot activate client");
173 			return 1;
174 		}
175 	} else {
176 		input_port = jack_port_register(client, "midi_in",
177 			JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
178 		printf("reused jack registration\n");
179 	}
180 
181 	return(handle);
182 }
183 
184 void
bristolJackSetMidiHandle(jack_client_t * jackHandle)185 bristolJackSetMidiHandle(jack_client_t *jackHandle)
186 {
187 	client = jackHandle;
188 }
189 
190 int
bristolMidiJackClose(int handle)191 bristolMidiJackClose(int handle)
192 {
193 	jack_client_close(client);
194 	return(handle);
195 }
196 #else /* _BRISTOL_JACK */
197 /*
198  * No jack so if we got here we need a couple of error messages to say so.
199  */
200 int
bristolMidiJackOpen(char * devname,int flags,int chan,int messages,int (* callback)(),void * param,int dev,int handle)201 bristolMidiJackOpen(char *devname, int flags, int chan, int messages,
202 int (*callback)(), void *param, int dev, int handle)
203 {
204 	printf("Jack MIDI requested but not linked into the library\n");
205 	return(BRISTOL_MIDI_DRIVER);
206 }
207 
208 int
bristolMidiJackClose(int handle)209 bristolMidiJackClose(int handle)
210 {
211 	printf("Jack MIDI close not linked into the library\n");
212 	return(BRISTOL_MIDI_DRIVER);
213 }
214 #endif
215