/[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 1751 by schoenebeck, Mon Jul 28 07:36:35 2008 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 - 2008 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    #include "VirtualMidiDevice.h"
31    
32    #include <algorithm>
33    
34  namespace LinuxSampler {  namespace LinuxSampler {
35    
36  // *************** ParameterName ***************  // *************** ParameterName ***************
# Line 48  namespace LinuxSampler { Line 56  namespace LinuxSampler {
56          return std::vector<String>();          return std::vector<String>();
57      }      }
58    
59      void MidiInputPort::ParameterName::OnSetValue(String s) throw (LinuxSamplerException) {      void MidiInputPort::ParameterName::OnSetValue(String s) throw (Exception) {
60          return; /* FIXME: Nothing to do here */          return; /* FIXME: Nothing to do here */
61      }      }
62    
# Line 60  namespace LinuxSampler { Line 68  namespace LinuxSampler {
68      MidiInputPort::~MidiInputPort() {      MidiInputPort::~MidiInputPort() {
69          std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();          std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();
70          while (iter != Parameters.end()) {          while (iter != Parameters.end()) {
             Parameters.erase(iter);  
71              delete iter->second;              delete iter->second;
72              iter++;              iter++;
73          }          }
74            Parameters.clear();
75      }      }
76    
77      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber) {      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
78            : MidiChannelMapReader(MidiChannelMap),
79              SysexListenersReader(SysexListeners),
80              virtualMidiDevicesReader(virtualMidiDevices) {
81          this->pDevice = pDevice;          this->pDevice = pDevice;
82          this->portNumber = portNumber;          this->portNumber = portNumber;
83          Parameters["NAME"] = new ParameterName(this);          Parameters["NAME"] = new ParameterName(this);
# Line 85  namespace LinuxSampler { Line 96  namespace LinuxSampler {
96      }      }
97    
98      void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
99            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
100            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
101          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
102          {          {
103              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
104              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
105              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
106          }          }
107          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
108          {          {
109              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
110              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
111              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
112          }          }
113            MidiChannelMapReader.Unlock();
114    
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        }
122    
123        void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
124            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
125            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    
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      }      }
147    
148      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
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          // dispatch event for engines listening to the same MIDI channel
152          {          {
153              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
154              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
155              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
156          }          }
157          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
158          {          {
159              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
160              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
161              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
162          }          }
163            MidiChannelMapReader.Unlock();
164    
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        }
172    
173        void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
174            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
175            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    
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      }      }
197    
198      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
199            if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
200            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
201          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
202          {          {
203              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
204              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
205              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
206          }          }
207          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
208          {          {
209              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
210              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
211              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
212          }          }
213            MidiChannelMapReader.Unlock();
214        }
215    
216        void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
217            if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
218            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      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
235            if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
236            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
237          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
238          {          {
239              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
240              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
241              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
242          }          }
243          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
244          {          {
245              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
246              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
247              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
248          }          }
249            MidiChannelMapReader.Unlock();
250        }
251    
252        void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
253            if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
254            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      void MidiInputPort::DispatchSysex(void* pData, uint Size) {      void MidiInputPort::DispatchSysex(void* pData, uint Size) {
271            const std::set<Engine*> allEngines = SysexListenersReader.Lock();
272            // dispatch event to all engine instances
273            std::set<Engine*>::iterator engineiter = allEngines.begin();
274            std::set<Engine*>::iterator end        = allEngines.end();
275            for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
276            SysexListenersReader.Unlock();
277        }
278    
279        void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
280            dmsg(1,("Received MIDI program change (prog=%d,ch=%d)\n",Program,MidiChannel));
281            if (Program > 127 || MidiChannel > 16) return;
282            if (!pDevice || !pDevice->pSampler) {
283                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
284                          << "This is a bug, please report it!\n" << std::flush;
285                return;
286            }
287            std::vector<int> maps = MidiInstrumentMapper::Maps();
288            if (maps.empty()) return;
289    
290            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
291          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
292          {          {
293              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
294                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
295                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              for (; engineiter != end; engineiter++) {
296                  for (; engineiter != end; engineiter++) {                  (*engineiter)->SetMidiProgram(Program);
297                      Engine* pEngine = (*engineiter)->GetEngine();                  if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
298                      if (pEngine) pEngine->SendSysex(pData, Size);                  if (MidiInstrumentMapper::GetMapCount() == 0) continue;
299                    // retrieve the MIDI instrument map this engine channel is assigned to
300                    int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
301                        ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
302                    // is there an entry for this MIDI bank&prog pair in that map?
303                    midi_prog_index_t midiIndex;
304                    midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
305                    midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
306                    midiIndex.midi_prog     = (*engineiter)->GetMidiProgram();
307                    optional<MidiInstrumentMapper::entry_t> mapping =
308                        MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
309                    if (mapping) { // if mapping exists ...
310                        InstrumentManager::instrument_id_t id;
311                        id.FileName = mapping->InstrumentFile;
312                        id.Index    = mapping->InstrumentIndex;
313                        //TODO: we should switch the engine type here
314                        InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
315                        (*engineiter)->Volume(mapping->Volume);
316                  }                  }
317              }              }
318          }          }
319          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
320          {          {
321              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
322                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
323                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              for (; engineiter != end; engineiter++) {
324                  for (; engineiter != end; engineiter++) {                  (*engineiter)->SetMidiProgram(Program);
325                      Engine* pEngine = (*engineiter)->GetEngine();                  if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
326                      if (pEngine) pEngine->SendSysex(pData, Size);                  if (MidiInstrumentMapper::GetMapCount() == 0) continue;
327                    // retrieve the MIDI instrument map this engine channel is assigned to
328                    int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
329                        ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
330                    // is there an entry for this MIDI bank&prog pair in that map?
331                    midi_prog_index_t midiIndex;
332                    midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
333                    midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
334                    midiIndex.midi_prog     = (*engineiter)->GetMidiProgram();
335                    optional<MidiInstrumentMapper::entry_t> mapping =
336                        MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
337                    if (mapping) { // if mapping exists ...
338                        InstrumentManager::instrument_id_t id;
339                        id.FileName = mapping->InstrumentFile;
340                        id.Index    = mapping->InstrumentIndex;
341                        //TODO: we should switch the engine type here
342                        InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
343                        (*engineiter)->Volume(mapping->Volume);
344                  }                  }
345              }              }
346          }          }
347            MidiChannelMapReader.Unlock();
348        }
349    
350        void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
351            if (BankMSB > 127 || MidiChannel > 16) return;
352            if (!pDevice || !pDevice->pSampler) {
353                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select MSB."
354                          << "This is a bug, please report it!\n" << std::flush;
355                return;
356            }
357            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
358            // dispatch event for engines listening to the same MIDI channel
359            {
360                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
361                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
362                // according to the MIDI specs, a bank select should not alter the patch
363                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
364            }
365            // dispatch event for engines listening to ALL MIDI channels
366            {
367                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
368                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
369                // according to the MIDI specs, a bank select should not alter the patch
370                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
371            }
372            MidiChannelMapReader.Unlock();
373        }
374    
375        void MidiInputPort::DispatchBankSelectLsb(uint8_t BankLSB, uint MidiChannel) {
376            if (BankLSB > 127 || MidiChannel > 16) return;
377            if (!pDevice || !pDevice->pSampler) {
378                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select LSB."
379                          << "This is a bug, please report it!\n" << std::flush;
380                return;
381            }
382            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
383            // dispatch event for engines listening to the same MIDI channel
384            {
385                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
386                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
387                // according to the MIDI specs, a bank select should not alter the patch
388                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
389            }
390            // dispatch event for engines listening to ALL MIDI channels
391            {
392                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
393                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
394                // according to the MIDI specs, a bank select should not alter the patch
395                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
396            }
397            MidiChannelMapReader.Unlock();
398      }      }
399    
400      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
401          if (MidiChannel < 0 || MidiChannel > 16)          if (MidiChannel < 0 || MidiChannel > 16)
402              throw MidiInputException("MIDI channel index out of bounds");              throw MidiInputException("MIDI channel index out of bounds");
403    
404            // first check if desired connection is already established
405            MidiChannelMapMutex.Lock();
406            MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
407            bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
408            MidiChannelMapMutex.Unlock();
409            if (bAlreadyDone) return;
410    
411            // remove all other connections of that engine channel (if any)
412          Disconnect(pEngineChannel);          Disconnect(pEngineChannel);
413          MidiChannelMap[MidiChannel].insert(pEngineChannel);  
414            // register engine channel on the desired MIDI channel
415            MidiChannelMapMutex.Lock();
416            MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
417            MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
418            MidiChannelMapMutex.Unlock();
419    
420            // inform engine channel about this connection
421            pEngineChannel->Connect(this, MidiChannel);
422    
423            // mark engine channel as changed
424            pEngineChannel->StatusChanged(true);
425      }      }
426    
427      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
428          try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngineChannel); }          if (!pEngineChannel) return;
429    
430            bool bChannelFound = false;
431    
432            // unregister engine channel from all MIDI channels
433            MidiChannelMapMutex.Lock();
434            try {
435                {
436                    MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
437                    for (int i = 0; i <= 16; i++) {
438                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
439                        midiChannelMap[i].erase(pEngineChannel);
440                    }
441                }
442                // do the same update again, after switching to the other config
443                {
444                    MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
445                    for (int i = 0; i <= 16; i++) {
446                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
447                        midiChannelMap[i].erase(pEngineChannel);
448                    }
449                }
450            }
451          catch(...) { /* NOOP */ }          catch(...) { /* NOOP */ }
452            MidiChannelMapMutex.Unlock();
453    
454            // inform engine channel about the disconnection (if there is one)
455            if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
456    
457            // mark engine channel as changed
458            pEngineChannel->StatusChanged(true);
459        }
460    
461        SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
462    
463        void MidiInputPort::AddSysexListener(Engine* engine) {
464            std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
465            if (p.second) SysexListeners.SwitchConfig().insert(engine);
466        }
467    
468        bool MidiInputPort::RemoveSysexListener(Engine* engine) {
469            int count = SysexListeners.GetConfigForUpdate().erase(engine);
470            if (count) SysexListeners.SwitchConfig().erase(engine);
471            return count;
472        }
473    
474        void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
475            virtualMidiDevicesMutex.Lock();
476            // double buffer ... double work ...
477            {
478                std::vector<VirtualMidiDevice*>& devices =
479                    virtualMidiDevices.GetConfigForUpdate();
480                devices.push_back(pDevice);
481            }
482            {
483                std::vector<VirtualMidiDevice*>& devices =
484                    virtualMidiDevices.SwitchConfig();
485                devices.push_back(pDevice);
486            }
487            virtualMidiDevicesMutex.Unlock();
488        }
489    
490        void MidiInputPort::Disconnect(VirtualMidiDevice* pDevice) {
491            virtualMidiDevicesMutex.Lock();
492            // double buffer ... double work ...
493            {
494                std::vector<VirtualMidiDevice*>& devices =
495                    virtualMidiDevices.GetConfigForUpdate();
496                devices.erase(std::find(devices.begin(), devices.end(), pDevice));
497            }
498            {
499                std::vector<VirtualMidiDevice*>& devices =
500                    virtualMidiDevices.SwitchConfig();
501                devices.erase(std::find(devices.begin(), devices.end(), pDevice));
502            }
503            virtualMidiDevicesMutex.Unlock();
504      }      }
505    
506  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC