/[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 675 by schoenebeck, Wed Jun 22 22:09:28 2005 UTC revision 880 by schoenebeck, Tue Jun 27 22:57:37 2006 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, 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 24  Line 24 
24  #include "MidiInputPort.h"  #include "MidiInputPort.h"
25    
26  #include "../../Sampler.h"  #include "../../Sampler.h"
27    #include "../../engines/EngineFactory.h"
28    
29  namespace LinuxSampler {  namespace LinuxSampler {
30    
# Line 50  namespace LinuxSampler { Line 51  namespace LinuxSampler {
51          return std::vector<String>();          return std::vector<String>();
52      }      }
53    
54      void MidiInputPort::ParameterName::OnSetValue(String s) throw (LinuxSamplerException) {      void MidiInputPort::ParameterName::OnSetValue(String s) throw (Exception) {
55          return; /* FIXME: Nothing to do here */          return; /* FIXME: Nothing to do here */
56      }      }
57    
# Line 62  namespace LinuxSampler { Line 63  namespace LinuxSampler {
63      MidiInputPort::~MidiInputPort() {      MidiInputPort::~MidiInputPort() {
64          std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();          std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();
65          while (iter != Parameters.end()) {          while (iter != Parameters.end()) {
             Parameters.erase(iter);  
66              delete iter->second;              delete iter->second;
67              iter++;              iter++;
68          }          }
69            Parameters.clear();
70      }      }
71    
72      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber) {      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
73            : MidiChannelMapReader(MidiChannelMap),
74              SysexListenersReader(SysexListeners) {
75          this->pDevice = pDevice;          this->pDevice = pDevice;
76          this->portNumber = portNumber;          this->portNumber = portNumber;
77          Parameters["NAME"] = new ParameterName(this);          Parameters["NAME"] = new ParameterName(this);
# Line 88  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            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
95          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
96          {          {
97              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
98              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
99              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
100          }          }
101          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
102          {          {
103              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
104              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
105              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
106          }          }
107            MidiChannelMapReader.Unlock();
108      }      }
109    
110      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
111            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
112          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
113          {          {
114              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
115              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
116              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
117          }          }
118          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
119          {          {
120              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
121              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
122              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
123          }          }
124            MidiChannelMapReader.Unlock();
125      }      }
126    
127      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
128            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
129          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
130          {          {
131              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
132              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
133              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
134          }          }
135          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
136          {          {
137              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
138              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
139              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
140          }          }
141            MidiChannelMapReader.Unlock();
142      }      }
143    
144      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
145            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
146          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
147          {          {
148              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
149              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
150              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
151          }          }
152          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
153          {          {
154              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
155              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
156              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
157          }          }
158            MidiChannelMapReader.Unlock();
159      }      }
160    
161      void MidiInputPort::DispatchSysex(void* pData, uint Size) {      void MidiInputPort::DispatchSysex(void* pData, uint Size) {
162          // dispatch event for engines listening to the same MIDI channel          const std::set<Engine*> allEngines = SysexListenersReader.Lock();
163          {          // dispatch event to all engine instances
164              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {          std::set<Engine*>::iterator engineiter = allEngines.begin();
165                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          std::set<Engine*>::iterator end        = allEngines.end();
166                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();          for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);
167                  for (; engineiter != end; engineiter++) {          SysexListenersReader.Unlock();
                     Engine* pEngine = (*engineiter)->GetEngine();  
                     if (pEngine) pEngine->SendSysex(pData, Size);  
                 }  
             }  
         }  
         // dispatch event for engines listening to ALL MIDI channels  
         {  
             for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {  
                 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();  
                 std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();  
                 for (; engineiter != end; engineiter++) {  
                     Engine* pEngine = (*engineiter)->GetEngine();  
                     if (pEngine) pEngine->SendSysex(pData, Size);  
                 }  
             }  
         }  
168      }      }
169    
170      void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {      void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
# Line 202  namespace LinuxSampler { Line 197  namespace LinuxSampler {
197          if (MidiChannel < 0 || MidiChannel > 16)          if (MidiChannel < 0 || MidiChannel > 16)
198              throw MidiInputException("MIDI channel index out of bounds");              throw MidiInputException("MIDI channel index out of bounds");
199    
200          // firt check if desired connection is already established          // first check if desired connection is already established
201          MidiChannelMapMutex.Lock();          MidiChannelMapMutex.Lock();
202          bool bAlreadyDone = MidiChannelMap[MidiChannel].count(pEngineChannel);          MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
203            bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
204          MidiChannelMapMutex.Unlock();          MidiChannelMapMutex.Unlock();
205          if (bAlreadyDone) return;          if (bAlreadyDone) return;
206    
# Line 213  namespace LinuxSampler { Line 209  namespace LinuxSampler {
209    
210          // register engine channel on the desired MIDI channel          // register engine channel on the desired MIDI channel
211          MidiChannelMapMutex.Lock();          MidiChannelMapMutex.Lock();
212          MidiChannelMap[MidiChannel].insert(pEngineChannel);          MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
213            MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
214          MidiChannelMapMutex.Unlock();          MidiChannelMapMutex.Unlock();
215    
216          // inform engine channel about this connection          // inform engine channel about this connection
# Line 231  namespace LinuxSampler { Line 228  namespace LinuxSampler {
228          // unregister engine channel from all MIDI channels          // unregister engine channel from all MIDI channels
229          MidiChannelMapMutex.Lock();          MidiChannelMapMutex.Lock();
230          try {          try {
231              for (int i = 0; i <= 16; i++) {              {
232                  bChannelFound |= MidiChannelMap[i].count(pEngineChannel);                  MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
233                  MidiChannelMap[i].erase(pEngineChannel);                  for (int i = 0; i <= 16; i++) {
234                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
235                        midiChannelMap[i].erase(pEngineChannel);
236                    }
237                }
238                // do the same update again, after switching to the other config
239                {
240                    MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
241                    for (int i = 0; i <= 16; i++) {
242                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
243                        midiChannelMap[i].erase(pEngineChannel);
244                    }
245              }              }
246          }          }
247          catch(...) { /* NOOP */ }          catch(...) { /* NOOP */ }
# Line 246  namespace LinuxSampler { Line 254  namespace LinuxSampler {
254          pEngineChannel->StatusChanged(true);          pEngineChannel->StatusChanged(true);
255      }      }
256    
257        SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
258    
259        void MidiInputPort::AddSysexListener(Engine* engine) {
260            std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
261            if (p.second) SysexListeners.SwitchConfig().insert(engine);
262        }
263    
264        bool MidiInputPort::RemoveSysexListener(Engine* engine) {
265            int count = SysexListeners.GetConfigForUpdate().erase(engine);
266            if (count) SysexListeners.SwitchConfig().erase(engine);
267            return count;
268        }
269    
270  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.675  
changed lines
  Added in v.880

  ViewVC Help
Powered by ViewVC