summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Hodder <dave.hodder@focusrite.com>2016-02-12 17:39:24 +0000
committerDave Hodder <dave.hodder@focusrite.com>2016-02-12 17:39:24 +0000
commitae080b1a43fa76fea39a239d7bdb0a94470e0bff (patch)
treed347d43e0037a905107d6b5e93798cf9a12a1c3a
parentcc4d02fb968342a255336f8c89cb5146ea62c10f (diff)
downloadlaunchpad-polymaker-ae080b1a43fa76fea39a239d7bdb0a94470e0bff.tar.gz
launchpad-polymaker-ae080b1a43fa76fea39a239d7bdb0a94470e0bff.zip
added virtual MIDI ports to simulator
-rw-r--r--tools/osx/simulator-osx.c111
1 files changed, 110 insertions, 1 deletions
diff --git a/tools/osx/simulator-osx.c b/tools/osx/simulator-osx.c
index 08a7b9a..7298042 100644
--- a/tools/osx/simulator-osx.c
+++ b/tools/osx/simulator-osx.c
@@ -35,12 +35,19 @@
35 35
36#include <CoreMIDI/CoreMIDI.h> 36#include <CoreMIDI/CoreMIDI.h>
37 37
38#include <mach/mach_time.h>
39
38////////////////////////////////////////////////////////////////////////// 40//////////////////////////////////////////////////////////////////////////
39static MIDIClientRef g_client = 0; 41static MIDIClientRef g_client = 0;
42
40static MIDIPortRef g_inDevPort = 0; 43static MIDIPortRef g_inDevPort = 0;
41static MIDIPortRef g_outDevPort = 0; 44static MIDIPortRef g_outDevPort = 0;
45
42static MIDIEndpointRef g_outDevEndpoint = 0; 46static MIDIEndpointRef g_outDevEndpoint = 0;
43 47
48static MIDIEndpointRef g_outVirtualEndpoint = 0;
49static MIDIEndpointRef g_inVirtualEndpoint = 0;
50
44static const float TIMER_INTERVAL_S = 0.001; //s 51static const float TIMER_INTERVAL_S = 0.001; //s
45 52
46// ____________________________________________________________________________ 53// ____________________________________________________________________________
@@ -65,7 +72,22 @@ void hal_plot_led(u8 type, u8 index, u8 red, u8 green, u8 blue)
65 72
66void hal_send_midi(u8 port, u8 status, u8 d1, u8 d2) 73void hal_send_midi(u8 port, u8 status, u8 d1, u8 d2)
67{ 74{
68 // TODO: send this up a virtual MIDI port? 75 if (port == DINMIDI)
76 {
77 // send this up the virtual "DIN" MIDI
78 u8 data[] = {status, d1, d2};
79
80 // MIDI needs host absolute time, NOT the proper time!
81
82 uint64_t timeNow = mach_absolute_time();
83
84 MIDIPacketList packetLst;
85 MIDIPacket *packet = MIDIPacketListInit(&packetLst);
86 MIDIPacketListAdd(&packetLst, 3, packet, timeNow, sizeof(data), data);
87
88 OSStatus err = MIDIReceived(g_outVirtualEndpoint, &packetLst);
89 int n=0;
90 }
69} 91}
70 92
71void hal_send_sysex(u8 port, const u8* data, u16 length) 93void hal_send_sysex(u8 port, const u8* data, u16 length)
@@ -123,6 +145,45 @@ static void processPacket(const unsigned char *data, int length)
123 } 145 }
124} 146}
125 147
148//////////////////////////////////////////////////////////////////////////
149static void processVirtualPortPacket(const unsigned char *data, int length)
150{
151 // parse MIDI (very naively)
152 while (length > 0)
153 {
154 unsigned char status = data[0];
155
156 // Wipe out channel (bottom four bits)
157 status &= 0xF0;
158
159 if (length >= 3)
160 {
161 switch (status)
162 {
163 case NOTEON:
164 case NOTEOFF:
165 case CC:
166 app_midi_event(DINMIDI, status, data[1], data[2]);
167 data += 3;
168 length -= 3;
169 break;
170
171 default:
172 // Don't know this message, so bail
173 length--;
174 data++;
175 break;
176 }
177 }
178 else
179 {
180 // We expected at least three bytes and didn't get them, so bail
181 length--;
182 data++;
183 }
184 }
185}
186
126static void readProc(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon) 187static void readProc(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon)
127{ 188{
128 // farm out the packets 189 // farm out the packets
@@ -137,6 +198,20 @@ static void readProc(const MIDIPacketList *pktlist, void *readProcRefCon, void *
137 } 198 }
138} 199}
139 200
201static void virtualReadProc(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon)
202{
203 // farm out the packets
204 const MIDIPacket *packet = &pktlist->packet[0];
205 for (int i=0; i < pktlist->numPackets; ++i)
206 {
207 // process the packet - in our case, receive a surface message
208 processVirtualPortPacket(packet->data, packet->length);
209
210 // next
211 packet = MIDIPacketNext(packet);
212 }
213}
214
140static int findLaunchpadPro() 215static int findLaunchpadPro()
141{ 216{
142 // find the input hardware port 217 // find the input hardware port
@@ -197,6 +272,34 @@ static int findLaunchpadPro()
197 return !(g_inDevPort && g_outDevPort); 272 return !(g_inDevPort && g_outDevPort);
198} 273}
199 274
275static int openVirtualPorts()
276{
277 // create the output port
278 CFStringRef name = CFStringCreateWithCString(NULL, "LPP Simulator Out", kCFStringEncodingMacRoman);
279 OSStatus result = MIDISourceCreate(g_client, name, &g_outVirtualEndpoint);
280 CFRelease(name);
281
282 if (noErr != result)
283 {
284 return -1;
285 }
286
287 MIDIObjectSetIntegerProperty(g_outVirtualEndpoint, kMIDIPropertyUniqueID, 12325436);
288
289 // create the input port
290 name = CFStringCreateWithCString(NULL, "LPP Simulator In", kCFStringEncodingMacRoman);
291 result = MIDIDestinationCreate(g_client, name, virtualReadProc, NULL, &g_inVirtualEndpoint);
292 CFRelease(name);
293
294 if (noErr != result)
295 {
296 return -1;
297 }
298 MIDIObjectSetIntegerProperty(g_outVirtualEndpoint, kMIDIPropertyUniqueID, 34534563);
299
300 return 0;
301}
302
200// ____________________________________________________________________________ 303// ____________________________________________________________________________
201 304
202static void timerCallback(CFRunLoopTimerRef timer, void * info) 305static void timerCallback(CFRunLoopTimerRef timer, void * info)
@@ -226,6 +329,12 @@ int main(int argc, char * argv[])
226 // no Launchpad Pro connected 329 // no Launchpad Pro connected
227 return -2; 330 return -2;
228 } 331 }
332
333 if (openVirtualPorts())
334 {
335 // no Launchpad Pro connected
336 return -3;
337 }
229 338
230 // now start things up 339 // now start things up
231 app_init(); 340 app_init();