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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.274  
changed lines
  Added in v.1135

  ViewVC Help
Powered by ViewVC