/[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 411 by schoenebeck, Sat Feb 26 02:01:14 2005 UTC revision 1424 by schoenebeck, Sun Oct 14 22:00:17 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 Christian Schoenebeck                              *   *   Copyright (C) 2005 - 2007 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 23  Line 23 
23    
24  #include "MidiInputPort.h"  #include "MidiInputPort.h"
25    
26    #include "../../common/global_private.h"
27    #include "MidiInstrumentMapper.h"
28    #include "../../Sampler.h"
29    #include "../../engines/EngineFactory.h"
30    
31  namespace LinuxSampler {  namespace LinuxSampler {
32    
33  // *************** ParameterName ***************  // *************** ParameterName ***************
# Line 48  namespace LinuxSampler { Line 53  namespace LinuxSampler {
53          return std::vector<String>();          return std::vector<String>();
54      }      }
55    
56      void MidiInputPort::ParameterName::OnSetValue(String s) throw (LinuxSamplerException) {      void MidiInputPort::ParameterName::OnSetValue(String s) throw (Exception) {
57          return; /* FIXME: Nothing to do here */          return; /* FIXME: Nothing to do here */
58      }      }
59    
# Line 60  namespace LinuxSampler { Line 65  namespace LinuxSampler {
65      MidiInputPort::~MidiInputPort() {      MidiInputPort::~MidiInputPort() {
66          std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();          std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();
67          while (iter != Parameters.end()) {          while (iter != Parameters.end()) {
             Parameters.erase(iter);  
68              delete iter->second;              delete iter->second;
69              iter++;              iter++;
70          }          }
71            Parameters.clear();
72      }      }
73    
74      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber) {      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
75            : MidiChannelMapReader(MidiChannelMap),
76              SysexListenersReader(SysexListeners) {
77          this->pDevice = pDevice;          this->pDevice = pDevice;
78          this->portNumber = portNumber;          this->portNumber = portNumber;
79          Parameters["NAME"] = new ParameterName(this);          Parameters["NAME"] = new ParameterName(this);
# Line 85  namespace LinuxSampler { Line 92  namespace LinuxSampler {
92      }      }
93    
94      void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
95            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
96            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
97          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
98          {          {
99              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
100              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
101              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
102          }          }
103          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
104          {          {
105              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
106              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
107              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
108          }          }
109            MidiChannelMapReader.Unlock();
110        }
111    
112        void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
113            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
114            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      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
131            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
132            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
133          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
134          {          {
135              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
136              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
137              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
138          }          }
139          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
140          {          {
141              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
142              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
143              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
144          }          }
145            MidiChannelMapReader.Unlock();
146        }
147    
148        void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
149            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
150            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      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
167            if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
168            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
169          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
170          {          {
171              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
172              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
173              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
174          }          }
175          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
176          {          {
177              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
178              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
179              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
180          }          }
181            MidiChannelMapReader.Unlock();
182        }
183    
184        void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
185            if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
186            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      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
203            if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
204            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
205          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
206          {          {
207              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
208              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
209              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
210          }          }
211          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
212          {          {
213              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
214              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
215              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
216          }          }
217            MidiChannelMapReader.Unlock();
218        }
219    
220        void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
221            if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
222            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      void MidiInputPort::DispatchSysex(void* pData, uint Size) {      void MidiInputPort::DispatchSysex(void* pData, uint Size) {
239            const std::set<Engine*> allEngines = SysexListenersReader.Lock();
240            // dispatch event to all engine instances
241            std::set<Engine*>::iterator engineiter = allEngines.begin();
242            std::set<Engine*>::iterator end        = allEngines.end();
243            for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);
244            SysexListenersReader.Unlock();
245        }
246    
247        void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
248            dmsg(1,("Received MIDI program change (prog=%d,ch=%d)\n",Program,MidiChannel));
249            if (Program > 127 || MidiChannel > 16) return;
250            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            std::vector<int> maps = MidiInstrumentMapper::Maps();
256            if (maps.empty()) return;
257    
258            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
259          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
260          {          {
261              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
262                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
263                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              for (; engineiter != end; engineiter++) {
264                  for (; engineiter != end; engineiter++) {                  (*engineiter)->SetMidiProgram(Program);
265                      Engine* pEngine = (*engineiter)->GetEngine();                  if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
266                      if (pEngine) pEngine->SendSysex(pData, Size);                  if (MidiInstrumentMapper::GetMapCount() == 0) continue;
267                    // retrieve the MIDI instrument map this engine channel is assigned to
268                    int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
269                        ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
270                    // is there an entry for this MIDI bank&prog pair in that map?
271                    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                        MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
277                    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          // dispatch event for engines listening to ALL MIDI channels
288          {          {
289              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
290                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
291                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              for (; engineiter != end; engineiter++) {
292                  for (; engineiter != end; engineiter++) {                  (*engineiter)->SetMidiProgram(Program);
293                      Engine* pEngine = (*engineiter)->GetEngine();                  if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
294                      if (pEngine) pEngine->SendSysex(pData, Size);                  if (MidiInstrumentMapper::GetMapCount() == 0) continue;
295                    // retrieve the MIDI instrument map this engine channel is assigned to
296                    int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
297                        ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
298                    // is there an entry for this MIDI bank&prog pair in that map?
299                    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                        MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
305                    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    
318        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    
343        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            }
350            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      }      }
367    
368      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
369          if (MidiChannel < 0 || MidiChannel > 16)          if (MidiChannel < 0 || MidiChannel > 16)
370              throw MidiInputException("MIDI channel index out of bounds");              throw MidiInputException("MIDI channel index out of bounds");
371    
372            // first check if desired connection is already established
373            MidiChannelMapMutex.Lock();
374            MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
375            bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
376            MidiChannelMapMutex.Unlock();
377            if (bAlreadyDone) return;
378    
379            // remove all other connections of that engine channel (if any)
380          Disconnect(pEngineChannel);          Disconnect(pEngineChannel);
381          MidiChannelMap[MidiChannel].insert(pEngineChannel);  
382            // register engine channel on the desired MIDI channel
383            MidiChannelMapMutex.Lock();
384            MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
385            MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
386            MidiChannelMapMutex.Unlock();
387    
388            // inform engine channel about this connection
389            pEngineChannel->Connect(this, MidiChannel);
390    
391            // mark engine channel as changed
392            pEngineChannel->StatusChanged(true);
393      }      }
394    
395      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
396          try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngineChannel); }          if (!pEngineChannel) return;
397    
398            bool bChannelFound = false;
399    
400            // unregister engine channel from all MIDI channels
401            MidiChannelMapMutex.Lock();
402            try {
403                {
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                }
410                // 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            }
419          catch(...) { /* NOOP */ }          catch(...) { /* NOOP */ }
420            MidiChannelMapMutex.Unlock();
421    
422            // inform engine channel about the disconnection (if there is one)
423            if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
424    
425            // mark engine channel as changed
426            pEngineChannel->StatusChanged(true);
427        }
428    
429        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  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.411  
changed lines
  Added in v.1424

  ViewVC Help
Powered by ViewVC