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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2494 - (hide 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 senoner 1485 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 persson 2311 * Copyright (C) 2005 - 2012 Christian Schoenebeck *
7 senoner 1485 * *
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 persson 2324 void CALLBACK MidiInputDeviceMme::MidiInputPortMme::win32_midiin_callback(HMIDIIN handle, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
33 senoner 1485 MidiInputDeviceMme::MidiInputPortMme* p = (MidiInputDeviceMme::MidiInputPortMme*)dwInstance;
34     p->MmeCallbackDispatcher(handle, uMsg, dwParam1, dwParam2);
35     }
36    
37    
38    
39 senoner 1500 // *************** ParameterPorts ***************
40     // *
41 senoner 1485
42 senoner 1500 // *************** 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 persson 1887
93 senoner 1500 // 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 persson 1887
97 senoner 1485 // *************** 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 persson 2451 CloseMmeMidiPort();
155 persson 2311 delete[] TmpSysExBuf;
156     delete[] SysExBuf;
157 senoner 1485 }
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 persson 1889 res = midiInOpen(&MidiInHandle, FoundMidiInDeviceId, (DWORD_PTR)win32_midiin_callback, (DWORD_PTR)this, CALLBACK_FUNCTION);
204 senoner 1485 if(res != MMSYSERR_NOERROR) {
205     throw MidiInputException("MIDI port connect failed. midiInOpen error");
206     }
207 persson 1887
208 senoner 1485 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 persson 1887
226 senoner 1485 /* 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 persson 1887
234 senoner 1485 res = midiInStart(MidiInHandle);
235     if(res != MMSYSERR_NOERROR) {
236     CloseMmeMidiPort();
237     throw MidiInputException("MIDI port connect failed, midiInStart failed.");
238     }
239    
240     }
241 persson 1887
242 persson 2324 void MidiInputDeviceMme::MidiInputPortMme::MmeCallbackDispatcher(HMIDIIN handle, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
243 senoner 1485
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 schoenebeck 2426 case MIM_DATA: {
251 schoenebeck 2428 //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 persson 1887 break;
256 schoenebeck 2426 }
257 senoner 1485
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 persson 1887 /* Queue the MIDIHDR for more input, only if ExitFlag was not set otherwise we risk an infinite loop
285 senoner 1485 because when we call midiInReset() below, Windows will send a final MIM_LONGDATA message to that callback.
286     */
287 persson 1887 midiInAddBuffer(MidiInHandle, lpMIDIHeader, sizeof(MIDIHDR));
288     }
289 senoner 1485 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 schoenebeck 2494 String s = "$Revision$";
343 senoner 1485 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
344     }
345    
346 persson 1887
347    
348 senoner 1485 } // namespace LinuxSampler

Properties

Name Value
svn:keywords Revision

  ViewVC Help
Powered by ViewVC