2
Copyright (C) 2008 Hans Fugal <hans@fugal.net>
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
/* OS X CoreMIDI version of Imidi. Might be cleaner to do some kind of
20
* inheritance, but for now this will do. Makefile.osx doesn't build imidi.cc
21
* but rather this file, and vice versa for the normal Linux Makefile.
28
Imidi::Imidi (Lfq_u32 *qnote, Lfq_u8 *qmidi, uint16_t *midimap, const char *appname) :
43
void Imidi::terminate (void)
45
put_event (EV_EXIT, 1);
49
void Imidi::thr_main (void)
52
get_event (1 << EV_EXIT);
54
send_event (EV_EXIT, 1);
58
static void coremidi_proc_static (const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
60
Imidi *imidi = (Imidi*)refCon;
61
imidi->coremidi_proc (pktlist, 0, connRefCon);
65
void Imidi::open_midi (void)
67
// If in the future dest is needed in close_midi (or elsewhere) this could
68
// be made an instance variable.
72
CFStringRef name = CFStringCreateWithCString(0, _appname, kCFStringEncodingUTF8);
73
MIDIClientCreate(name, NULL, NULL, &_handle);
74
MIDIDestinationCreate(_handle, name, coremidi_proc_static, this, &dest);
77
// is this stuff needed? I'm guessing no, but we'll see when I plugin the
79
MIDIPortRef inPort = NULL;
80
MIDIInputPortCreate(_handle, CFSTR("In"), coremidi_proc_static, this, &inPort);
82
// open connections from all sources (TODO is this what we want?)
83
int n = MIDIGetNumberOfSources();
84
for (int i=0; i<n; i++)
86
MIDIEndpointRef src = MIDIGetSource(i);
87
MIDIPortConnectSource(inPort, src, (void*)src);
92
// _client and _ippport are printed in the main window's title as [_client:_ipport]
93
// They are the info required to connect to a source using the ALSA sequencer.
94
// Anything equivalent for OSX ?
97
// _appname is the name of the destination, and that's what users are
98
// likely to use when connecting MIDI sources to it.
100
M_midi_info *M = new M_midi_info ();
103
memcpy (M->_chbits, _midimap, 16);
104
send_event (TO_MODEL, M);
108
void Imidi::close_midi (void)
110
// nothing to do here - everything is closed automagically (if I
111
// understand the docs correctly)
115
void Imidi::coremidi_proc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
117
int c, d, f, m, n, p, t, v, s;
118
MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
120
for (unsigned int j=0; j < pktlist->numPackets; j++)
122
for (int i=0; i < packet->length; i++)
125
// Maybe this should be factored out so it can be
126
// shared with the ALSA version. But not urgent.
129
// Yeah, and the JACK MIDI version too.
131
Byte *E = &packet->data[i];
137
continue; // skip data bytes
139
m = _midimap [c] & 127; // Keyboard and hold bits
140
d = (_midimap [c] >> 8) & 7; // Division number if (f & 2)
141
f = (_midimap [c] >> 12) & 7; // Control enabled if (f & 4)
150
if ((t == 0x90) && v)
155
if ((f & 4) && (n >= 24) && (n < 34))
157
// Preset selection, sent to model thread
158
// if on control-enabled channel.
159
if (_qmidi->write_avail () >= 3)
161
_qmidi->write (0, 0x90);
162
_qmidi->write (1, n);
163
_qmidi->write (2, v);
164
_qmidi->write_commit (3);
172
if (_qnote->write_avail () > 0)
174
_qnote->write (0, (1 << 24) | ((n - 36) << 8) | m);
175
_qnote->write_commit (1);
190
if (_qnote->write_avail () > 0)
192
_qnote->write (0, ((n - 36) << 8) | m);
193
_qnote->write_commit (1);
209
v = (v > 63) ? 9 : 8;
210
if (_qnote->write_avail () > 0)
212
_qnote->write (0, (v << 24) | (m << 16));
213
_qnote->write_commit (1);
219
// All sound off, accepted on control channels only.
220
// Clears all keyboards, including held notes.
223
if (_qnote->write_avail () > 0)
225
_qnote->write (0, (2 << 24) | ( ALL_MASK << 16) | ALL_MASK);
226
_qnote->write_commit (1);
232
// All notes off, accepted on channels controlling
233
// a keyboard. Does not clear held notes.
236
if (_qnote->write_avail () > 0)
238
_qnote->write (0, (2 << 24) | (m << 16) | m);
239
_qnote->write_commit (1);
246
// Program bank selection or stop control, sent
247
// to model thread if on control-enabled channel.
250
if (_qmidi->write_avail () >= 3)
252
_qmidi->write (0, 0xB0 | c);
253
_qmidi->write (1, p);
254
_qmidi->write (2, v);
255
_qmidi->write_commit (3);
261
// Per-division performance controls, sent to model
262
// thread if on a channel that controls a division.
265
if (_qmidi->write_avail () >= 3)
267
_qmidi->write (0, 0xB0 | c);
268
_qmidi->write (1, p);
269
_qmidi->write (2, v);
270
_qmidi->write_commit (3);
278
// Program change sent to model thread
279
// if on control-enabled channel.
283
if (_qmidi->write_avail () >= 3)
285
_qmidi->write (0, 0xC0);
286
_qmidi->write (1, n);
287
_qmidi->write (2, 0);
288
_qmidi->write_commit (3);
295
packet = MIDIPacketNext(packet);