/[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 2494 - (show annotations) (download)
Wed Jan 1 17:48:01 2014 UTC (10 years, 3 months ago) by schoenebeck
File size: 12373 byte(s)
* Enabled automatic svn "Revision" macro expansion on certain files.
* Bumped version to 1.0.0.svn24.

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

Properties

Name Value
svn:keywords Revision

  ViewVC Help
Powered by ViewVC