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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1765 - (hide annotations) (download)
Sat Sep 6 16:44:42 2008 UTC (15 years, 7 months ago) by persson
File size: 26477 byte(s)
* refactoring: extracted lscp notification from main() to a separate
  function
* added helper function MidiInputPort::DispatchRaw for midi device
  implementations with raw byte data
* fixed a win32 build error (atomic.h is working on windows too)
* code cleanup: moved lscp classes into LinuxSampler namespace

1 schoenebeck 221 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 1695 * Copyright (C) 2005 - 2008 Christian Schoenebeck *
7 schoenebeck 221 * *
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 "MidiInputPort.h"
25    
26 schoenebeck 1424 #include "../../common/global_private.h"
27 schoenebeck 947 #include "MidiInstrumentMapper.h"
28 schoenebeck 551 #include "../../Sampler.h"
29 schoenebeck 775 #include "../../engines/EngineFactory.h"
30 schoenebeck 1695 #include "VirtualMidiDevice.h"
31 schoenebeck 551
32 schoenebeck 1695 #include <algorithm>
33    
34 schoenebeck 221 namespace LinuxSampler {
35    
36     // *************** ParameterName ***************
37     // *
38    
39     MidiInputPort::ParameterName::ParameterName(MidiInputPort* pPort) : DeviceRuntimeParameterString("Port " + ToString(pPort->GetPortNumber())) {
40     this->pPort = pPort;
41     }
42    
43     MidiInputPort::ParameterName::ParameterName(MidiInputPort* pPort, String val) : DeviceRuntimeParameterString(val) {
44     this->pPort = pPort;
45     }
46    
47     String MidiInputPort::ParameterName::Description() {
48     return "Name for this port";
49     }
50    
51     bool MidiInputPort::ParameterName::Fix() {
52     return false;
53     }
54    
55     std::vector<String> MidiInputPort::ParameterName::PossibilitiesAsString() {
56     return std::vector<String>();
57     }
58    
59 schoenebeck 880 void MidiInputPort::ParameterName::OnSetValue(String s) throw (Exception) {
60 schoenebeck 221 return; /* FIXME: Nothing to do here */
61     }
62    
63    
64    
65     // *************** MidiInputPort ***************
66     // *
67    
68     MidiInputPort::~MidiInputPort() {
69     std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();
70     while (iter != Parameters.end()) {
71     delete iter->second;
72     iter++;
73     }
74 persson 836 Parameters.clear();
75 schoenebeck 221 }
76    
77 persson 846 MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
78     : MidiChannelMapReader(MidiChannelMap),
79 schoenebeck 1695 SysexListenersReader(SysexListeners),
80     virtualMidiDevicesReader(virtualMidiDevices) {
81 schoenebeck 221 this->pDevice = pDevice;
82     this->portNumber = portNumber;
83     Parameters["NAME"] = new ParameterName(this);
84     }
85    
86     MidiInputDevice* MidiInputPort::GetDevice() {
87     return pDevice;
88     }
89    
90     uint MidiInputPort::GetPortNumber() {
91     return portNumber;
92     }
93    
94     std::map<String,DeviceRuntimeParameter*> MidiInputPort::PortParameters() {
95     return Parameters;
96     }
97    
98     void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
99 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
100 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
101 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
102     {
103 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
104     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
105 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
106     }
107     // dispatch event for engines listening to ALL MIDI channels
108     {
109 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
110     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
111 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
112     }
113 persson 846 MidiChannelMapReader.Unlock();
114 schoenebeck 1695
115     // dispatch event to all low priority MIDI listeners
116     const std::vector<VirtualMidiDevice*>& listeners =
117     virtualMidiDevicesReader.Lock();
118     for (int i = 0; i < listeners.size(); ++i)
119     listeners[i]->SendNoteOnToDevice(Key, Velocity);
120     virtualMidiDevicesReader.Unlock();
121 schoenebeck 221 }
122    
123 schoenebeck 906 void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
124 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
125 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
126     // dispatch event for engines listening to the same MIDI channel
127     {
128     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
129     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
130     for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, FragmentPos);
131     }
132     // dispatch event for engines listening to ALL MIDI channels
133     {
134     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
135     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
136     for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, FragmentPos);
137     }
138     MidiChannelMapReader.Unlock();
139 schoenebeck 1695
140     // dispatch event to all low priority MIDI listeners
141     const std::vector<VirtualMidiDevice*>& listeners =
142     virtualMidiDevicesReader.Lock();
143     for (int i = 0; i < listeners.size(); ++i)
144     listeners[i]->SendNoteOnToDevice(Key, Velocity);
145     virtualMidiDevicesReader.Unlock();
146 schoenebeck 906 }
147    
148 schoenebeck 221 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
149 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
150 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
151 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
152     {
153 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
154     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
155 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
156     }
157     // dispatch event for engines listening to ALL MIDI channels
158     {
159 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
160     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
161 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
162     }
163 persson 846 MidiChannelMapReader.Unlock();
164 schoenebeck 1695
165     // dispatch event to all low priority MIDI listeners
166     const std::vector<VirtualMidiDevice*>& listeners =
167     virtualMidiDevicesReader.Lock();
168     for (int i = 0; i < listeners.size(); ++i)
169     listeners[i]->SendNoteOffToDevice(Key, Velocity);
170     virtualMidiDevicesReader.Unlock();
171 schoenebeck 221 }
172    
173 schoenebeck 906 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
174 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
175 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
176     // dispatch event for engines listening to the same MIDI channel
177     {
178     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
179     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
180     for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, FragmentPos);
181     }
182     // dispatch event for engines listening to ALL MIDI channels
183     {
184     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
185     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
186     for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, FragmentPos);
187     }
188     MidiChannelMapReader.Unlock();
189 schoenebeck 1695
190     // dispatch event to all low priority MIDI listeners
191     const std::vector<VirtualMidiDevice*>& listeners =
192     virtualMidiDevicesReader.Lock();
193     for (int i = 0; i < listeners.size(); ++i)
194     listeners[i]->SendNoteOffToDevice(Key, Velocity);
195     virtualMidiDevicesReader.Unlock();
196 schoenebeck 906 }
197    
198 schoenebeck 221 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
199 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
200 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
201 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
202     {
203 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
204     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
205 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
206     }
207     // dispatch event for engines listening to ALL MIDI channels
208     {
209 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
210     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
211 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
212     }
213 persson 846 MidiChannelMapReader.Unlock();
214 schoenebeck 221 }
215    
216 schoenebeck 906 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
217 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
218 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
219     // dispatch event for engines listening to the same MIDI channel
220     {
221     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
222     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
223     for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, FragmentPos);
224     }
225     // dispatch event for engines listening to ALL MIDI channels
226     {
227     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
228     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
229     for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, FragmentPos);
230     }
231     MidiChannelMapReader.Unlock();
232     }
233    
234 schoenebeck 221 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
235 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
236 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
237 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
238     {
239 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
240     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
241 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
242     }
243     // dispatch event for engines listening to ALL MIDI channels
244     {
245 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
246     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
247 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
248     }
249 persson 846 MidiChannelMapReader.Unlock();
250 schoenebeck 221 }
251    
252 schoenebeck 906 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
253 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
254 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
255     // dispatch event for engines listening to the same MIDI channel
256     {
257     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
258     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
259     for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
260     }
261     // dispatch event for engines listening to ALL MIDI channels
262     {
263     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
264     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
265     for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
266     }
267     MidiChannelMapReader.Unlock();
268     }
269    
270 schoenebeck 244 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
271 persson 846 const std::set<Engine*> allEngines = SysexListenersReader.Lock();
272 schoenebeck 775 // dispatch event to all engine instances
273 persson 846 std::set<Engine*>::iterator engineiter = allEngines.begin();
274     std::set<Engine*>::iterator end = allEngines.end();
275 schoenebeck 1751 for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
276 persson 846 SysexListenersReader.Unlock();
277 schoenebeck 244 }
278    
279 schoenebeck 670 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
280 schoenebeck 947 dmsg(1,("Received MIDI program change (prog=%d,ch=%d)\n",Program,MidiChannel));
281 persson 922 if (Program > 127 || MidiChannel > 16) return;
282 schoenebeck 551 if (!pDevice || !pDevice->pSampler) {
283     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
284     << "This is a bug, please report it!\n" << std::flush;
285     return;
286     }
287 schoenebeck 973 std::vector<int> maps = MidiInstrumentMapper::Maps();
288     if (maps.empty()) return;
289    
290 schoenebeck 947 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
291     // dispatch event for engines listening to the same MIDI channel
292     {
293     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
294     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
295     for (; engineiter != end; engineiter++) {
296     (*engineiter)->SetMidiProgram(Program);
297 schoenebeck 973 if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
298 iliev 1135 if (MidiInstrumentMapper::GetMapCount() == 0) continue;
299 schoenebeck 973 // retrieve the MIDI instrument map this engine channel is assigned to
300     int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
301 iliev 1135 ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
302 schoenebeck 973 // is there an entry for this MIDI bank&prog pair in that map?
303 schoenebeck 947 midi_prog_index_t midiIndex;
304     midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
305     midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
306     midiIndex.midi_prog = (*engineiter)->GetMidiProgram();
307     optional<MidiInstrumentMapper::entry_t> mapping =
308 schoenebeck 973 MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
309 schoenebeck 947 if (mapping) { // if mapping exists ...
310     InstrumentManager::instrument_id_t id;
311     id.FileName = mapping->InstrumentFile;
312     id.Index = mapping->InstrumentIndex;
313     //TODO: we should switch the engine type here
314     InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
315     (*engineiter)->Volume(mapping->Volume);
316     }
317     }
318     }
319     // dispatch event for engines listening to ALL MIDI channels
320     {
321     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
322     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
323     for (; engineiter != end; engineiter++) {
324     (*engineiter)->SetMidiProgram(Program);
325 schoenebeck 973 if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
326 iliev 1135 if (MidiInstrumentMapper::GetMapCount() == 0) continue;
327 schoenebeck 973 // retrieve the MIDI instrument map this engine channel is assigned to
328     int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
329 iliev 1135 ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
330 schoenebeck 973 // is there an entry for this MIDI bank&prog pair in that map?
331 schoenebeck 947 midi_prog_index_t midiIndex;
332     midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
333     midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
334     midiIndex.midi_prog = (*engineiter)->GetMidiProgram();
335     optional<MidiInstrumentMapper::entry_t> mapping =
336 schoenebeck 973 MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
337 schoenebeck 947 if (mapping) { // if mapping exists ...
338     InstrumentManager::instrument_id_t id;
339     id.FileName = mapping->InstrumentFile;
340     id.Index = mapping->InstrumentIndex;
341     //TODO: we should switch the engine type here
342     InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
343     (*engineiter)->Volume(mapping->Volume);
344     }
345     }
346     }
347     MidiChannelMapReader.Unlock();
348     }
349 schoenebeck 551
350 schoenebeck 947 void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
351     if (BankMSB > 127 || MidiChannel > 16) return;
352     if (!pDevice || !pDevice->pSampler) {
353     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select MSB."
354     << "This is a bug, please report it!\n" << std::flush;
355     return;
356     }
357     const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
358     // dispatch event for engines listening to the same MIDI channel
359     {
360     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
361     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
362     // according to the MIDI specs, a bank select should not alter the patch
363     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
364     }
365     // dispatch event for engines listening to ALL MIDI channels
366     {
367     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
368     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
369     // according to the MIDI specs, a bank select should not alter the patch
370     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
371     }
372     MidiChannelMapReader.Unlock();
373     }
374 schoenebeck 551
375 schoenebeck 947 void MidiInputPort::DispatchBankSelectLsb(uint8_t BankLSB, uint MidiChannel) {
376     if (BankLSB > 127 || MidiChannel > 16) return;
377     if (!pDevice || !pDevice->pSampler) {
378     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select LSB."
379     << "This is a bug, please report it!\n" << std::flush;
380     return;
381 schoenebeck 551 }
382 schoenebeck 947 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
383     // dispatch event for engines listening to the same MIDI channel
384     {
385     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
386     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
387     // according to the MIDI specs, a bank select should not alter the patch
388     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
389     }
390     // dispatch event for engines listening to ALL MIDI channels
391     {
392     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
393     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
394     // according to the MIDI specs, a bank select should not alter the patch
395     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
396     }
397     MidiChannelMapReader.Unlock();
398 schoenebeck 551 }
399    
400 persson 1765 void MidiInputPort::DispatchRaw(uint8_t* pData, int32_t FragmentPos) {
401     uint8_t channel = pData[0] & 0x0f;
402     switch (pData[0] & 0xf0) {
403     case 0x80:
404     DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
405     break;
406     case 0x90:
407     if (pData[2]) {
408     DispatchNoteOn(pData[1], pData[2], channel, FragmentPos);
409     } else {
410     DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
411     }
412     break;
413     case 0xb0:
414     if (pData[1] == 0) {
415     DispatchBankSelectMsb(pData[2], channel);
416     } else if (pData[1] == 32) {
417     DispatchBankSelectLsb(pData[2], channel);
418     }
419     DispatchControlChange(pData[1], pData[2], channel, FragmentPos);
420     break;
421     case 0xc0:
422     DispatchProgramChange(pData[1], channel);
423     break;
424     case 0xd0:
425     DispatchControlChange(128, pData[1], channel, FragmentPos);
426     break;
427     case 0xe0:
428     DispatchPitchbend(pData[1], channel, FragmentPos);
429     break;
430     }
431     }
432    
433 schoenebeck 411 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
434 schoenebeck 221 if (MidiChannel < 0 || MidiChannel > 16)
435     throw MidiInputException("MIDI channel index out of bounds");
436 schoenebeck 670
437 persson 840 // first check if desired connection is already established
438 schoenebeck 675 MidiChannelMapMutex.Lock();
439 persson 840 MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
440     bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
441 schoenebeck 675 MidiChannelMapMutex.Unlock();
442     if (bAlreadyDone) return;
443    
444     // remove all other connections of that engine channel (if any)
445 schoenebeck 411 Disconnect(pEngineChannel);
446 schoenebeck 670
447 schoenebeck 675 // register engine channel on the desired MIDI channel
448 schoenebeck 551 MidiChannelMapMutex.Lock();
449 persson 840 MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
450     MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
451 schoenebeck 551 MidiChannelMapMutex.Unlock();
452 schoenebeck 670
453 schoenebeck 675 // inform engine channel about this connection
454     pEngineChannel->Connect(this, MidiChannel);
455    
456 schoenebeck 670 // mark engine channel as changed
457     pEngineChannel->StatusChanged(true);
458 schoenebeck 221 }
459    
460 schoenebeck 411 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
461 schoenebeck 675 if (!pEngineChannel) return;
462    
463     bool bChannelFound = false;
464    
465     // unregister engine channel from all MIDI channels
466 schoenebeck 551 MidiChannelMapMutex.Lock();
467 schoenebeck 675 try {
468 persson 840 {
469     MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
470     for (int i = 0; i <= 16; i++) {
471     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
472     midiChannelMap[i].erase(pEngineChannel);
473     }
474 schoenebeck 675 }
475 persson 840 // do the same update again, after switching to the other config
476     {
477     MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
478     for (int i = 0; i <= 16; i++) {
479     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
480     midiChannelMap[i].erase(pEngineChannel);
481     }
482     }
483 schoenebeck 675 }
484 schoenebeck 221 catch(...) { /* NOOP */ }
485 schoenebeck 551 MidiChannelMapMutex.Unlock();
486 schoenebeck 675
487     // inform engine channel about the disconnection (if there is one)
488     if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
489    
490 schoenebeck 670 // mark engine channel as changed
491     pEngineChannel->StatusChanged(true);
492 schoenebeck 221 }
493    
494 persson 846 SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
495    
496     void MidiInputPort::AddSysexListener(Engine* engine) {
497     std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
498     if (p.second) SysexListeners.SwitchConfig().insert(engine);
499     }
500    
501     bool MidiInputPort::RemoveSysexListener(Engine* engine) {
502     int count = SysexListeners.GetConfigForUpdate().erase(engine);
503     if (count) SysexListeners.SwitchConfig().erase(engine);
504     return count;
505     }
506    
507 schoenebeck 1695 void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
508     virtualMidiDevicesMutex.Lock();
509     // double buffer ... double work ...
510     {
511     std::vector<VirtualMidiDevice*>& devices =
512     virtualMidiDevices.GetConfigForUpdate();
513     devices.push_back(pDevice);
514     }
515     {
516     std::vector<VirtualMidiDevice*>& devices =
517     virtualMidiDevices.SwitchConfig();
518     devices.push_back(pDevice);
519     }
520     virtualMidiDevicesMutex.Unlock();
521     }
522    
523     void MidiInputPort::Disconnect(VirtualMidiDevice* pDevice) {
524     virtualMidiDevicesMutex.Lock();
525     // double buffer ... double work ...
526     {
527     std::vector<VirtualMidiDevice*>& devices =
528     virtualMidiDevices.GetConfigForUpdate();
529     devices.erase(std::find(devices.begin(), devices.end(), pDevice));
530     }
531     {
532     std::vector<VirtualMidiDevice*>& devices =
533     virtualMidiDevices.SwitchConfig();
534     devices.erase(std::find(devices.begin(), devices.end(), pDevice));
535     }
536     virtualMidiDevicesMutex.Unlock();
537     }
538    
539 schoenebeck 221 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC