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