/[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 1485 - (hide 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 senoner 1485 /***************************************************************************
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