/[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 1924 - (hide annotations) (download)
Sun Jun 28 16:43:38 2009 UTC (14 years, 9 months ago) by persson
File size: 24599 byte(s)
* made program change handling in MIDI thread real-time safe by moving
  the logic to a non-RT thread

1 schoenebeck 221 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 persson 1887 * Copyright (C) 2005 - 2009 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 persson 922 if (Program > 127 || MidiChannel > 16) return;
281 schoenebeck 551 if (!pDevice || !pDevice->pSampler) {
282     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
283     << "This is a bug, please report it!\n" << std::flush;
284     return;
285     }
286 schoenebeck 973
287 schoenebeck 947 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
288     // dispatch event for engines listening to the same MIDI channel
289     {
290     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
291     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
292 persson 1924 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
293 schoenebeck 947 }
294     // dispatch event for engines listening to ALL MIDI channels
295     {
296     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
297     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
298 persson 1924 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
299 schoenebeck 947 }
300     MidiChannelMapReader.Unlock();
301     }
302 schoenebeck 551
303 schoenebeck 947 void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
304     if (BankMSB > 127 || MidiChannel > 16) return;
305     if (!pDevice || !pDevice->pSampler) {
306     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select MSB."
307     << "This is a bug, please report it!\n" << std::flush;
308     return;
309     }
310     const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
311     // dispatch event for engines listening to the same MIDI channel
312     {
313     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
314     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
315     // according to the MIDI specs, a bank select should not alter the patch
316     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
317     }
318     // dispatch event for engines listening to ALL MIDI channels
319     {
320     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
321     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
322     // according to the MIDI specs, a bank select should not alter the patch
323     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
324     }
325     MidiChannelMapReader.Unlock();
326     }
327 schoenebeck 551
328 schoenebeck 947 void MidiInputPort::DispatchBankSelectLsb(uint8_t BankLSB, uint MidiChannel) {
329     if (BankLSB > 127 || MidiChannel > 16) return;
330     if (!pDevice || !pDevice->pSampler) {
331     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select LSB."
332     << "This is a bug, please report it!\n" << std::flush;
333     return;
334 schoenebeck 551 }
335 schoenebeck 947 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
336     // dispatch event for engines listening to the same MIDI channel
337     {
338     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
339     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
340     // according to the MIDI specs, a bank select should not alter the patch
341     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
342     }
343     // dispatch event for engines listening to ALL MIDI channels
344     {
345     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
346     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
347     // according to the MIDI specs, a bank select should not alter the patch
348     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
349     }
350     MidiChannelMapReader.Unlock();
351 schoenebeck 551 }
352    
353 persson 1887 void MidiInputPort::DispatchRaw(uint8_t* pData) {
354     uint8_t channel = pData[0] & 0x0f;
355     switch (pData[0] & 0xf0) {
356     case 0x80:
357     DispatchNoteOff(pData[1], pData[2], channel);
358     break;
359     case 0x90:
360     if (pData[2]) {
361     DispatchNoteOn(pData[1], pData[2], channel);
362     } else {
363     DispatchNoteOff(pData[1], pData[2], channel);
364     }
365     break;
366     case 0xb0:
367     if (pData[1] == 0) {
368     DispatchBankSelectMsb(pData[2], channel);
369     } else if (pData[1] == 32) {
370     DispatchBankSelectLsb(pData[2], channel);
371     }
372     DispatchControlChange(pData[1], pData[2], channel);
373     break;
374     case 0xc0:
375     DispatchProgramChange(pData[1], channel);
376     break;
377     case 0xd0:
378     DispatchControlChange(128, pData[1], channel);
379     break;
380     case 0xe0:
381     DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel);
382     break;
383     }
384     }
385    
386 persson 1765 void MidiInputPort::DispatchRaw(uint8_t* pData, int32_t FragmentPos) {
387     uint8_t channel = pData[0] & 0x0f;
388     switch (pData[0] & 0xf0) {
389     case 0x80:
390     DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
391     break;
392     case 0x90:
393     if (pData[2]) {
394     DispatchNoteOn(pData[1], pData[2], channel, FragmentPos);
395     } else {
396     DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
397     }
398     break;
399     case 0xb0:
400     if (pData[1] == 0) {
401     DispatchBankSelectMsb(pData[2], channel);
402     } else if (pData[1] == 32) {
403     DispatchBankSelectLsb(pData[2], channel);
404     }
405     DispatchControlChange(pData[1], pData[2], channel, FragmentPos);
406     break;
407     case 0xc0:
408     DispatchProgramChange(pData[1], channel);
409     break;
410     case 0xd0:
411     DispatchControlChange(128, pData[1], channel, FragmentPos);
412     break;
413     case 0xe0:
414 persson 1887 DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel, FragmentPos);
415 persson 1765 break;
416     }
417     }
418    
419 schoenebeck 411 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
420 schoenebeck 221 if (MidiChannel < 0 || MidiChannel > 16)
421     throw MidiInputException("MIDI channel index out of bounds");
422 schoenebeck 670
423 persson 840 // first check if desired connection is already established
424 schoenebeck 675 MidiChannelMapMutex.Lock();
425 persson 840 MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
426     bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
427 schoenebeck 675 MidiChannelMapMutex.Unlock();
428     if (bAlreadyDone) return;
429    
430     // remove all other connections of that engine channel (if any)
431 schoenebeck 411 Disconnect(pEngineChannel);
432 schoenebeck 670
433 schoenebeck 675 // register engine channel on the desired MIDI channel
434 schoenebeck 551 MidiChannelMapMutex.Lock();
435 persson 840 MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
436     MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
437 schoenebeck 551 MidiChannelMapMutex.Unlock();
438 schoenebeck 670
439 schoenebeck 675 // inform engine channel about this connection
440     pEngineChannel->Connect(this, MidiChannel);
441    
442 schoenebeck 670 // mark engine channel as changed
443     pEngineChannel->StatusChanged(true);
444 schoenebeck 221 }
445    
446 schoenebeck 411 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
447 schoenebeck 675 if (!pEngineChannel) return;
448    
449     bool bChannelFound = false;
450    
451     // unregister engine channel from all MIDI channels
452 schoenebeck 551 MidiChannelMapMutex.Lock();
453 schoenebeck 675 try {
454 persson 840 {
455     MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
456     for (int i = 0; i <= 16; i++) {
457     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
458     midiChannelMap[i].erase(pEngineChannel);
459     }
460 schoenebeck 675 }
461 persson 840 // do the same update again, after switching to the other config
462     {
463     MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
464     for (int i = 0; i <= 16; i++) {
465     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
466     midiChannelMap[i].erase(pEngineChannel);
467     }
468     }
469 schoenebeck 675 }
470 schoenebeck 221 catch(...) { /* NOOP */ }
471 schoenebeck 551 MidiChannelMapMutex.Unlock();
472 schoenebeck 675
473     // inform engine channel about the disconnection (if there is one)
474     if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
475    
476 schoenebeck 670 // mark engine channel as changed
477     pEngineChannel->StatusChanged(true);
478 schoenebeck 221 }
479    
480 persson 846 SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
481    
482     void MidiInputPort::AddSysexListener(Engine* engine) {
483     std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
484     if (p.second) SysexListeners.SwitchConfig().insert(engine);
485     }
486    
487     bool MidiInputPort::RemoveSysexListener(Engine* engine) {
488     int count = SysexListeners.GetConfigForUpdate().erase(engine);
489     if (count) SysexListeners.SwitchConfig().erase(engine);
490     return count;
491     }
492    
493 schoenebeck 1695 void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
494     virtualMidiDevicesMutex.Lock();
495     // double buffer ... double work ...
496     {
497     std::vector<VirtualMidiDevice*>& devices =
498     virtualMidiDevices.GetConfigForUpdate();
499     devices.push_back(pDevice);
500     }
501     {
502     std::vector<VirtualMidiDevice*>& devices =
503     virtualMidiDevices.SwitchConfig();
504     devices.push_back(pDevice);
505     }
506     virtualMidiDevicesMutex.Unlock();
507     }
508    
509     void MidiInputPort::Disconnect(VirtualMidiDevice* pDevice) {
510     virtualMidiDevicesMutex.Lock();
511     // double buffer ... double work ...
512     {
513     std::vector<VirtualMidiDevice*>& devices =
514     virtualMidiDevices.GetConfigForUpdate();
515     devices.erase(std::find(devices.begin(), devices.end(), pDevice));
516     }
517     {
518     std::vector<VirtualMidiDevice*>& devices =
519     virtualMidiDevices.SwitchConfig();
520     devices.erase(std::find(devices.begin(), devices.end(), pDevice));
521     }
522     virtualMidiDevicesMutex.Unlock();
523     }
524    
525 schoenebeck 221 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC