/[svn]/linuxsampler/trunk/src/drivers/midi/MidiInputDeviceMme.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/drivers/midi/MidiInputDeviceMme.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1485 - (show annotations) (download)
Thu Nov 15 23:35:45 2007 UTC (16 years, 5 months ago) by senoner
File size: 11529 byte(s)
* win32 port, work in progress:
* added MME MIDI Input driver
* Resampler.h, gig/Synthesizer.h:
* changed return type of getSample() from int to int32_t

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2007 Christian Schoenebeck *
7 * *
8 * 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 *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include "MidiInputDeviceMme.h"
25 #include "MidiInputDeviceFactory.h"
26
27
28
29
30 namespace LinuxSampler {
31
32 void CALLBACK MidiInputDeviceMme::MidiInputPortMme::win32_midiin_callback(HMIDIIN handle, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) {
33 MidiInputDeviceMme::MidiInputPortMme* p = (MidiInputDeviceMme::MidiInputPortMme*)dwInstance;
34 p->MmeCallbackDispatcher(handle, uMsg, dwParam1, dwParam2);
35 }
36
37
38
39
40 // *************** ParameterPort ***************
41 // *
42
43 MidiInputDeviceMme::MidiInputPortMme::ParameterPort::ParameterPort(MidiInputPortMme* pPort)
44 : DeviceRuntimeParameterString("") {
45 this->pPort = pPort;
46 }
47
48 String MidiInputDeviceMme::MidiInputPortMme::ParameterPort::Description() {
49 return "MME Destination MIDI Port";
50 }
51
52 bool MidiInputDeviceMme::MidiInputPortMme::ParameterPort::Fix() {
53 return false;
54 }
55
56 std::vector<String> MidiInputDeviceMme::MidiInputPortMme::ParameterPort::PossibilitiesAsString() {
57 // returns a list of the available MME Input MIDI ports you can connect to
58 std::vector<String> ports;
59 MIDIINCAPS midiincaps;
60
61 int NumDevs = midiInGetNumDevs();
62
63 for(int i=0;i<NumDevs;i++) {
64 int res = midiInGetDevCaps(i, &midiincaps, sizeof(MIDIINCAPS));
65 if(res == MMSYSERR_NOERROR) {
66 ports.push_back( (String)midiincaps.szPname);
67 }
68 }
69
70 return ports;
71 }
72
73 void MidiInputDeviceMme::MidiInputPortMme::ParameterPort::OnSetValue(String s) {
74 pPort->ConnectToMmeMidiSource(s.c_str());
75 }
76
77
78
79 // *************** MidiInputPortMme ***************
80 // *
81
82 MidiInputDeviceMme::MidiInputPortMme::MidiInputPortMme(MidiInputDeviceMme* pDevice) throw (MidiInputException)
83 : MidiInputPort(pDevice, ((DeviceCreationParameterInt*)pDevice->Parameters["PORTS"])->ValueAsInt() - 1)
84 {
85 this->pDevice = pDevice;
86 MidiInOpened = false;
87 SysExBuf = new char[MME_MAX_SYSEX_BUF_SIZE];
88 TmpSysExBuf = new char[MME_MAX_SYSEX_BUF_SIZE];
89 ExitFlag = false;
90 FirstSysExBlock = true;
91 SysExMsgComplete = false;
92 dmsg(3,("created MME port %d\n", this->portNumber));
93 Parameters["PORT"] = new ParameterPort(this);
94 }
95
96 MidiInputDeviceMme::MidiInputPortMme::~MidiInputPortMme() {
97 delete TmpSysExBuf;
98 delete SysExBuf;
99 }
100
101
102 /***
103 * Closes the MME MIDI Input port in a safe way
104 */
105 void MidiInputDeviceMme::MidiInputPortMme::CloseMmeMidiPort(void) {
106 int res;
107 if (MidiInOpened == true) {
108 ExitFlag = true;
109 midiInReset(MidiInHandle);
110 while ((res = midiInClose(MidiInHandle)) == MIDIERR_STILLPLAYING) Sleep(100);
111 midiInUnprepareHeader(MidiInHandle, &midiHdr, sizeof(MIDIHDR));
112 MidiInOpened = false;
113 }
114 }
115
116 /**
117 * Connects the port with the MME Midi Input port
118 *
119 * @param Name of the MME Midi Input port e.g. "MAUDIO MIDI IN"
120 * @throws MidiInputException if connection cannot be established
121 */
122
123 void MidiInputDeviceMme::MidiInputPortMme::ConnectToMmeMidiSource(const char* MidiSource) {
124
125 // close the old MIDI Input port if it was already opened
126 CloseMmeMidiPort();
127
128 MIDIINCAPS midiincaps;
129 int NumDevs = midiInGetNumDevs();
130
131 int FoundMidiInDeviceId = -1;
132 for(int i=0;i<NumDevs;i++) {
133 int res = midiInGetDevCaps(i, &midiincaps, sizeof(MIDIINCAPS));
134 if(res == MMSYSERR_NOERROR) {
135 if(!strcmp(midiincaps.szPname, MidiSource)) {
136 FoundMidiInDeviceId = i;
137 break;
138 }
139 }
140 }
141
142 if(FoundMidiInDeviceId == -1) throw MidiInputException("MIDI port connect failed");
143
144 int res;
145 res = midiInOpen(&MidiInHandle, FoundMidiInDeviceId, (DWORD)win32_midiin_callback, (DWORD)this, CALLBACK_FUNCTION);
146 if(res != MMSYSERR_NOERROR) {
147 throw MidiInputException("MIDI port connect failed. midiInOpen error");
148 }
149
150 MidiInOpened = true;
151
152 /* Store pointer to our input buffer for System Exclusive messages in MIDIHDR */
153 midiHdr.lpData = &TmpSysExBuf[0];
154
155 /* Store its size in the MIDIHDR */
156 midiHdr.dwBufferLength = MME_MAX_SYSEX_BUF_SIZE;
157
158 /* Flags must be set to 0 */
159 midiHdr.dwFlags = 0;
160
161 /* Prepare the buffer and MIDIHDR */
162 res = midiInPrepareHeader(MidiInHandle, &midiHdr, sizeof(MIDIHDR));
163 if(res != MMSYSERR_NOERROR) {
164 CloseMmeMidiPort();
165 throw MidiInputException("MIDI port connect failed. midiInPrepareHeader error");
166 }
167
168 /* Queue MIDI input buffer */
169 res = midiInAddBuffer(MidiInHandle, &midiHdr, sizeof(MIDIHDR));
170 if(res != MMSYSERR_NOERROR) {
171 CloseMmeMidiPort();
172 throw MidiInputException("MIDI port connect failed. midiInAddBuffer error");
173 }
174
175
176 res = midiInStart(MidiInHandle);
177 if(res != MMSYSERR_NOERROR) {
178 CloseMmeMidiPort();
179 throw MidiInputException("MIDI port connect failed, midiInStart failed.");
180 }
181
182 }
183
184 void MidiInputDeviceMme::MidiInputPortMme::MmeCallbackDispatcher(HMIDIIN handle, UINT uMsg, DWORD dwParam1, DWORD dwParam2) {
185
186 unsigned char *DataPtr; // pointer to SysEx data
187 unsigned char *data; // pointer to standard MIDI messages which are not sysex data(max 3 bytes long)
188
189 data = (unsigned char *)&dwParam1;
190
191 switch(uMsg) {
192 case MIM_DATA:
193 switch(data[0] & 0xF0) { // status byte
194
195 case 0xB0:
196 if (data[1] == 0)
197 DispatchBankSelectMsb(data[2], data[0] & 0x0F);
198 else if (data[1] == 32)
199 DispatchBankSelectLsb(data[2], data[0] & 0x0F);
200 else
201 DispatchControlChange(data[1], data[2], data[0] & 0x0F);
202 break;
203
204 case 0xD0:
205 DispatchControlChange(128, data[1], data[0] & 0x0F);
206 break;
207
208 case 0xE0:
209 DispatchPitchbend(data[1], data[0] & 0x0F);
210 break;
211
212 case 0x90:
213 if (data[1] < 0x80) {
214 if (data[2] > 0){
215 DispatchNoteOn(data[1], data[2], data[0] & 0x0F);
216 }else{
217 DispatchNoteOff(data[1], data[2], data[0] & 0x0F);
218 }
219 }
220 break;
221
222 case 0x80:
223 if (data[1] < 0x80) {
224 DispatchNoteOff(data[1], data[2], data[0] & 0x0F);
225 }
226 break;
227
228 case 0xC0:
229 if (data[1] < 0x80) {
230 DispatchProgramChange(data[1], data[0] & 0x0F);
231 }
232 break;
233 }
234
235 break;
236
237 case MIM_LONGDATA:
238 if(!ExitFlag) {
239 LPMIDIHDR lpMIDIHeader = (LPMIDIHDR)dwParam1;
240 DataPtr = (unsigned char *)(lpMIDIHeader->lpData);
241 if(lpMIDIHeader->dwBytesRecorded == 0) break;
242
243 if(FirstSysExBlock) {
244 SysExOffset = 0;
245 FirstSysExBlock = false;
246 }
247
248 if( DataPtr[lpMIDIHeader->dwBytesRecorded - 1] == 0xF7) {
249 SysExMsgComplete = true;
250 FirstSysExBlock = true;
251 }
252 else {
253 SysExMsgComplete = false;
254 }
255
256 if(SysExOffset + lpMIDIHeader->dwBytesRecorded <= MME_MAX_SYSEX_BUF_SIZE) {
257 memcpy(&SysExBuf[SysExOffset], DataPtr, lpMIDIHeader->dwBytesRecorded);
258 SysExOffset += lpMIDIHeader->dwBytesRecorded;
259 }
260
261 if(SysExMsgComplete) DispatchSysex(SysExBuf, SysExOffset);
262
263 /* Queue the MIDIHDR for more input, only if ExitFlag was not set otherwise we risk an infinite loop
264 because when we call midiInReset() below, Windows will send a final MIM_LONGDATA message to that callback.
265 */
266 midiInAddBuffer(MidiInHandle, lpMIDIHeader, sizeof(MIDIHDR));
267 }
268 break;
269 }
270
271 }
272
273
274
275
276 // *************** MidiInputDeviceMme ***************
277 // *
278
279 MidiInputDeviceMme::MidiInputDeviceMme(std::map<String,DeviceCreationParameter*> Parameters, void* pSampler) : MidiInputDevice(Parameters, pSampler) {
280 AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt());
281 if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
282 Listen();
283 }
284 }
285
286 MidiInputDeviceMme::~MidiInputDeviceMme() {
287 // free the midi ports (we can't let the base class do this,
288 // as the MidiInputPortMme destructors need access to
289 // hAlsaSeq)
290 for (std::map<int,MidiInputPort*>::iterator iter = Ports.begin(); iter != Ports.end() ; iter++) {
291 delete static_cast<MidiInputPortMme*>(iter->second);
292 }
293 Ports.clear();
294 }
295
296 MidiInputDeviceMme::MidiInputPortMme* MidiInputDeviceMme::CreateMidiPort() {
297 dmsg(1,("foo\n"));
298 return new MidiInputPortMme(this);
299 }
300
301 String MidiInputDeviceMme::Name() {
302 return "MME";
303 }
304
305 String MidiInputDeviceMme::Driver() {
306 return Name();
307 }
308
309 void MidiInputDeviceMme::Listen() {
310 //TODO: ...
311 }
312
313 void MidiInputDeviceMme::StopListen() {
314 //TODO: ...
315 }
316
317 String MidiInputDeviceMme::Description() {
318 return "MultiMedia Extensions";
319 }
320
321 String MidiInputDeviceMme::Version() {
322 String s = "$Revision: 1.1 $";
323 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
324 }
325
326
327
328 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC