/[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 2324 - (hide annotations) (download)
Sun Mar 4 09:01:32 2012 UTC (12 years ago) by persson
File size: 12014 byte(s)
* plugin bugfix: instrument loading hang when the plugin was loaded a
  second time (this time it's for Linux and Mac, previous similar fix
  was for Windows)
* thread safety fixes for the instrument loading thread
* MME driver: removed compiler warning
* LV2: fixed invalid realtime statement in plugin metadata

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 2311 delete[] TmpSysExBuf;
155     delete[] SysExBuf;
156 senoner 1485 }
157    
158    
159     /***
160     * Closes the MME MIDI Input port in a safe way
161     */
162     void MidiInputDeviceMme::MidiInputPortMme::CloseMmeMidiPort(void) {
163     int res;
164     if (MidiInOpened == true) {
165     ExitFlag = true;
166     midiInReset(MidiInHandle);
167     while ((res = midiInClose(MidiInHandle)) == MIDIERR_STILLPLAYING) Sleep(100);
168     midiInUnprepareHeader(MidiInHandle, &midiHdr, sizeof(MIDIHDR));
169     MidiInOpened = false;
170     }
171     }
172    
173     /**
174     * Connects the port with the MME Midi Input port
175     *
176     * @param Name of the MME Midi Input port e.g. "MAUDIO MIDI IN"
177     * @throws MidiInputException if connection cannot be established
178     */
179    
180     void MidiInputDeviceMme::MidiInputPortMme::ConnectToMmeMidiSource(const char* MidiSource) {
181    
182     // close the old MIDI Input port if it was already opened
183     CloseMmeMidiPort();
184    
185     MIDIINCAPS midiincaps;
186     int NumDevs = midiInGetNumDevs();
187    
188     int FoundMidiInDeviceId = -1;
189     for(int i=0;i<NumDevs;i++) {
190     int res = midiInGetDevCaps(i, &midiincaps, sizeof(MIDIINCAPS));
191     if(res == MMSYSERR_NOERROR) {
192     if(!strcmp(midiincaps.szPname, MidiSource)) {
193     FoundMidiInDeviceId = i;
194     break;
195     }
196     }
197     }
198    
199     if(FoundMidiInDeviceId == -1) throw MidiInputException("MIDI port connect failed");
200    
201     int res;
202 persson 1889 res = midiInOpen(&MidiInHandle, FoundMidiInDeviceId, (DWORD_PTR)win32_midiin_callback, (DWORD_PTR)this, CALLBACK_FUNCTION);
203 senoner 1485 if(res != MMSYSERR_NOERROR) {
204     throw MidiInputException("MIDI port connect failed. midiInOpen error");
205     }
206 persson 1887
207 senoner 1485 MidiInOpened = true;
208    
209     /* Store pointer to our input buffer for System Exclusive messages in MIDIHDR */
210     midiHdr.lpData = &TmpSysExBuf[0];
211    
212     /* Store its size in the MIDIHDR */
213     midiHdr.dwBufferLength = MME_MAX_SYSEX_BUF_SIZE;
214    
215     /* Flags must be set to 0 */
216     midiHdr.dwFlags = 0;
217    
218     /* Prepare the buffer and MIDIHDR */
219     res = midiInPrepareHeader(MidiInHandle, &midiHdr, sizeof(MIDIHDR));
220     if(res != MMSYSERR_NOERROR) {
221     CloseMmeMidiPort();
222     throw MidiInputException("MIDI port connect failed. midiInPrepareHeader error");
223     }
224 persson 1887
225 senoner 1485 /* Queue MIDI input buffer */
226     res = midiInAddBuffer(MidiInHandle, &midiHdr, sizeof(MIDIHDR));
227     if(res != MMSYSERR_NOERROR) {
228     CloseMmeMidiPort();
229     throw MidiInputException("MIDI port connect failed. midiInAddBuffer error");
230     }
231    
232 persson 1887
233 senoner 1485 res = midiInStart(MidiInHandle);
234     if(res != MMSYSERR_NOERROR) {
235     CloseMmeMidiPort();
236     throw MidiInputException("MIDI port connect failed, midiInStart failed.");
237     }
238    
239     }
240 persson 1887
241 persson 2324 void MidiInputDeviceMme::MidiInputPortMme::MmeCallbackDispatcher(HMIDIIN handle, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
242 senoner 1485
243     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)
245    
246     data = (unsigned char *)&dwParam1;
247    
248     switch(uMsg) {
249     case MIM_DATA:
250 persson 1887 DispatchRaw(data);
251     break;
252 senoner 1485
253     case MIM_LONGDATA:
254     if(!ExitFlag) {
255     LPMIDIHDR lpMIDIHeader = (LPMIDIHDR)dwParam1;
256     DataPtr = (unsigned char *)(lpMIDIHeader->lpData);
257     if(lpMIDIHeader->dwBytesRecorded == 0) break;
258    
259     if(FirstSysExBlock) {
260     SysExOffset = 0;
261     FirstSysExBlock = false;
262     }
263    
264     if( DataPtr[lpMIDIHeader->dwBytesRecorded - 1] == 0xF7) {
265     SysExMsgComplete = true;
266     FirstSysExBlock = true;
267     }
268     else {
269     SysExMsgComplete = false;
270     }
271    
272     if(SysExOffset + lpMIDIHeader->dwBytesRecorded <= MME_MAX_SYSEX_BUF_SIZE) {
273     memcpy(&SysExBuf[SysExOffset], DataPtr, lpMIDIHeader->dwBytesRecorded);
274     SysExOffset += lpMIDIHeader->dwBytesRecorded;
275     }
276    
277     if(SysExMsgComplete) DispatchSysex(SysExBuf, SysExOffset);
278    
279 persson 1887 /* Queue the MIDIHDR for more input, only if ExitFlag was not set otherwise we risk an infinite loop
280 senoner 1485 because when we call midiInReset() below, Windows will send a final MIM_LONGDATA message to that callback.
281     */
282 persson 1887 midiInAddBuffer(MidiInHandle, lpMIDIHeader, sizeof(MIDIHDR));
283     }
284 senoner 1485 break;
285     }
286    
287     }
288    
289    
290    
291    
292     // *************** MidiInputDeviceMme ***************
293     // *
294    
295     MidiInputDeviceMme::MidiInputDeviceMme(std::map<String,DeviceCreationParameter*> Parameters, void* pSampler) : MidiInputDevice(Parameters, pSampler) {
296     AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt());
297     if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
298     Listen();
299     }
300     }
301    
302     MidiInputDeviceMme::~MidiInputDeviceMme() {
303     // free the midi ports (we can't let the base class do this,
304     // as the MidiInputPortMme destructors need access to
305     // hAlsaSeq)
306     for (std::map<int,MidiInputPort*>::iterator iter = Ports.begin(); iter != Ports.end() ; iter++) {
307     delete static_cast<MidiInputPortMme*>(iter->second);
308     }
309     Ports.clear();
310     }
311    
312     MidiInputDeviceMme::MidiInputPortMme* MidiInputDeviceMme::CreateMidiPort() {
313     return new MidiInputPortMme(this);
314     }
315    
316     String MidiInputDeviceMme::Name() {
317     return "MME";
318     }
319    
320     String MidiInputDeviceMme::Driver() {
321     return Name();
322     }
323    
324     void MidiInputDeviceMme::Listen() {
325     //TODO: ...
326     }
327    
328     void MidiInputDeviceMme::StopListen() {
329     //TODO: ...
330     }
331    
332     String MidiInputDeviceMme::Description() {
333     return "MultiMedia Extensions";
334     }
335    
336     String MidiInputDeviceMme::Version() {
337 persson 1889 String s = "$Revision: 1.5 $";
338 senoner 1485 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
339     }
340    
341 persson 1887
342    
343 senoner 1485 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC