/[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 1424 - (hide annotations) (download)
Sun Oct 14 22:00:17 2007 UTC (16 years, 6 months ago) by schoenebeck
File size: 22776 byte(s)
* code cleanup:
- global.h now only covers global definitions that are needed for the C++
  API header files, all implementation internal global definitions are now
  in global_private.h
- atomic.h is not exposed to the C++ API anymore (replaced the references
  in SynchronizedConfig.h for this with local definitions)
- no need to include config.h anymore for using LS's API header files
- DB instruments classes are not exposed to the C++ API
- POSIX callback functions of Thread.h are hidden
- the (optional) gig Engine benchmark compiles again
- updated Doxyfile.in
- fixed warnings in API doc generation
* preparations for release 0.5.0

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

  ViewVC Help
Powered by ViewVC