3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005 - 2007 Christian Schoenebeck * |
* Copyright (C) 2005 - 2012 Christian Schoenebeck * |
7 |
* * |
* * |
8 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
9 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
29 |
|
|
30 |
namespace LinuxSampler { |
namespace LinuxSampler { |
31 |
|
|
32 |
void CALLBACK MidiInputDeviceMme::MidiInputPortMme::win32_midiin_callback(HMIDIIN handle, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { |
void CALLBACK MidiInputDeviceMme::MidiInputPortMme::win32_midiin_callback(HMIDIIN handle, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { |
33 |
MidiInputDeviceMme::MidiInputPortMme* p = (MidiInputDeviceMme::MidiInputPortMme*)dwInstance; |
MidiInputDeviceMme::MidiInputPortMme* p = (MidiInputDeviceMme::MidiInputPortMme*)dwInstance; |
34 |
p->MmeCallbackDispatcher(handle, uMsg, dwParam1, dwParam2); |
p->MmeCallbackDispatcher(handle, uMsg, dwParam1, dwParam2); |
35 |
} |
} |
89 |
String MidiInputDeviceMme::ParameterPorts::Name() { |
String MidiInputDeviceMme::ParameterPorts::Name() { |
90 |
return "PORTS"; |
return "PORTS"; |
91 |
} |
} |
92 |
|
|
93 |
// the MME driver supports only one port so to manage multiple MME MIDI ports the user just creates several MME drivers and connects each one to the desired MME port |
// the MME driver supports only one port so to manage multiple MME MIDI ports the user just creates several MME drivers and connects each one to the desired MME port |
94 |
|
|
95 |
|
|
96 |
|
|
97 |
// *************** ParameterPort *************** |
// *************** ParameterPort *************** |
151 |
} |
} |
152 |
|
|
153 |
MidiInputDeviceMme::MidiInputPortMme::~MidiInputPortMme() { |
MidiInputDeviceMme::MidiInputPortMme::~MidiInputPortMme() { |
154 |
delete TmpSysExBuf; |
delete[] TmpSysExBuf; |
155 |
delete SysExBuf; |
delete[] SysExBuf; |
156 |
} |
} |
157 |
|
|
158 |
|
|
199 |
if(FoundMidiInDeviceId == -1) throw MidiInputException("MIDI port connect failed"); |
if(FoundMidiInDeviceId == -1) throw MidiInputException("MIDI port connect failed"); |
200 |
|
|
201 |
int res; |
int res; |
202 |
res = midiInOpen(&MidiInHandle, FoundMidiInDeviceId, (DWORD)win32_midiin_callback, (DWORD)this, CALLBACK_FUNCTION); |
res = midiInOpen(&MidiInHandle, FoundMidiInDeviceId, (DWORD_PTR)win32_midiin_callback, (DWORD_PTR)this, CALLBACK_FUNCTION); |
203 |
if(res != MMSYSERR_NOERROR) { |
if(res != MMSYSERR_NOERROR) { |
204 |
throw MidiInputException("MIDI port connect failed. midiInOpen error"); |
throw MidiInputException("MIDI port connect failed. midiInOpen error"); |
205 |
} |
} |
206 |
|
|
207 |
MidiInOpened = true; |
MidiInOpened = true; |
208 |
|
|
209 |
/* Store pointer to our input buffer for System Exclusive messages in MIDIHDR */ |
/* Store pointer to our input buffer for System Exclusive messages in MIDIHDR */ |
221 |
CloseMmeMidiPort(); |
CloseMmeMidiPort(); |
222 |
throw MidiInputException("MIDI port connect failed. midiInPrepareHeader error"); |
throw MidiInputException("MIDI port connect failed. midiInPrepareHeader error"); |
223 |
} |
} |
224 |
|
|
225 |
/* Queue MIDI input buffer */ |
/* Queue MIDI input buffer */ |
226 |
res = midiInAddBuffer(MidiInHandle, &midiHdr, sizeof(MIDIHDR)); |
res = midiInAddBuffer(MidiInHandle, &midiHdr, sizeof(MIDIHDR)); |
227 |
if(res != MMSYSERR_NOERROR) { |
if(res != MMSYSERR_NOERROR) { |
229 |
throw MidiInputException("MIDI port connect failed. midiInAddBuffer error"); |
throw MidiInputException("MIDI port connect failed. midiInAddBuffer error"); |
230 |
} |
} |
231 |
|
|
232 |
|
|
233 |
res = midiInStart(MidiInHandle); |
res = midiInStart(MidiInHandle); |
234 |
if(res != MMSYSERR_NOERROR) { |
if(res != MMSYSERR_NOERROR) { |
235 |
CloseMmeMidiPort(); |
CloseMmeMidiPort(); |
237 |
} |
} |
238 |
|
|
239 |
} |
} |
240 |
|
|
241 |
void MidiInputDeviceMme::MidiInputPortMme::MmeCallbackDispatcher(HMIDIIN handle, UINT uMsg, DWORD dwParam1, DWORD dwParam2) { |
void MidiInputDeviceMme::MidiInputPortMme::MmeCallbackDispatcher(HMIDIIN handle, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { |
242 |
|
|
243 |
unsigned char *DataPtr; // pointer to SysEx data |
unsigned char *DataPtr; // pointer to SysEx data |
244 |
unsigned char *data; // pointer to standard MIDI messages which are not sysex data(max 3 bytes long) |
unsigned char *data; // pointer to standard MIDI messages which are not sysex data(max 3 bytes long) |
246 |
data = (unsigned char *)&dwParam1; |
data = (unsigned char *)&dwParam1; |
247 |
|
|
248 |
switch(uMsg) { |
switch(uMsg) { |
249 |
case MIM_DATA: |
case MIM_DATA: { |
250 |
switch(data[0] & 0xF0) { // status byte |
//FIXME: passing timeStamp this way here does not work, since the DispatchRaw() expects it to be in period position, not miliseconds, requires additional code in RTMath to be able to transform the value for this purpose here |
251 |
|
//int32_t timeStamp = dwParam2; |
252 |
case 0xB0: |
//DispatchRaw(data, timeStamp); |
253 |
if (data[1] == 0) |
DispatchRaw(data); |
|
DispatchBankSelectMsb(data[2], data[0] & 0x0F); |
|
|
else if (data[1] == 32) |
|
|
DispatchBankSelectLsb(data[2], data[0] & 0x0F); |
|
|
else |
|
|
DispatchControlChange(data[1], data[2], data[0] & 0x0F); |
|
|
break; |
|
|
|
|
|
case 0xD0: |
|
|
DispatchControlChange(128, data[1], data[0] & 0x0F); |
|
|
break; |
|
|
|
|
|
case 0xE0: |
|
|
DispatchPitchbend(data[1], data[0] & 0x0F); |
|
|
break; |
|
|
|
|
|
case 0x90: |
|
|
if (data[1] < 0x80) { |
|
|
if (data[2] > 0){ |
|
|
DispatchNoteOn(data[1], data[2], data[0] & 0x0F); |
|
|
}else{ |
|
|
DispatchNoteOff(data[1], data[2], data[0] & 0x0F); |
|
|
} |
|
|
} |
|
|
break; |
|
|
|
|
|
case 0x80: |
|
|
if (data[1] < 0x80) { |
|
|
DispatchNoteOff(data[1], data[2], data[0] & 0x0F); |
|
|
} |
|
|
break; |
|
|
|
|
|
case 0xC0: |
|
|
if (data[1] < 0x80) { |
|
|
DispatchProgramChange(data[1], data[0] & 0x0F); |
|
|
} |
|
|
break; |
|
|
} |
|
|
|
|
254 |
break; |
break; |
255 |
|
} |
256 |
|
|
257 |
case MIM_LONGDATA: |
case MIM_LONGDATA: |
258 |
if(!ExitFlag) { |
if(!ExitFlag) { |
259 |
LPMIDIHDR lpMIDIHeader = (LPMIDIHDR)dwParam1; |
LPMIDIHDR lpMIDIHeader = (LPMIDIHDR)dwParam1; |
280 |
|
|
281 |
if(SysExMsgComplete) DispatchSysex(SysExBuf, SysExOffset); |
if(SysExMsgComplete) DispatchSysex(SysExBuf, SysExOffset); |
282 |
|
|
283 |
/* Queue the MIDIHDR for more input, only if ExitFlag was not set otherwise we risk an infinite loop |
/* Queue the MIDIHDR for more input, only if ExitFlag was not set otherwise we risk an infinite loop |
284 |
because when we call midiInReset() below, Windows will send a final MIM_LONGDATA message to that callback. |
because when we call midiInReset() below, Windows will send a final MIM_LONGDATA message to that callback. |
285 |
*/ |
*/ |
286 |
midiInAddBuffer(MidiInHandle, lpMIDIHeader, sizeof(MIDIHDR)); |
midiInAddBuffer(MidiInHandle, lpMIDIHeader, sizeof(MIDIHDR)); |
287 |
} |
} |
288 |
break; |
break; |
289 |
} |
} |
290 |
|
|
338 |
} |
} |
339 |
|
|
340 |
String MidiInputDeviceMme::Version() { |
String MidiInputDeviceMme::Version() { |
341 |
String s = "$Revision: 1.2 $"; |
String s = "$Revision: 1.5 $"; |
342 |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
343 |
} |
} |
344 |
|
|
345 |
|
|
346 |
|
|
347 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |