/[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 840 by persson, Sun Feb 26 13:00:08 2006 UTC
# Line 23  Line 23 
23    
24  #include "MidiInputPort.h"  #include "MidiInputPort.h"
25    
26    #include "../../Sampler.h"
27    #include "../../engines/EngineFactory.h"
28    
29  namespace LinuxSampler {  namespace LinuxSampler {
30    
31  // *************** ParameterName ***************  // *************** ParameterName ***************
# Line 60  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          this->pDevice = pDevice;          this->pDevice = pDevice;
74          this->portNumber = portNumber;          this->portNumber = portNumber;
75          Parameters["NAME"] = new ParameterName(this);          Parameters["NAME"] = new ParameterName(this);
76            pPreviousProgramChangeEngineChannel = NULL;
77      }      }
78    
79      MidiInputDevice* MidiInputPort::GetDevice() {      MidiInputDevice* MidiInputPort::GetDevice() {
# Line 85  namespace LinuxSampler { Line 89  namespace LinuxSampler {
89      }      }
90    
91      void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
92            const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();
93          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
94          {          {
95              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
96              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
97              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
98          }          }
99          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
100          {          {
101              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
102              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
103              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
104          }          }
105            MidiChannelMap.Unlock();
106      }      }
107    
108      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
109            const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();
110          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
111          {          {
112              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
113              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
114              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
115          }          }
116          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
117          {          {
118              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
119              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
120              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
121          }          }
122            MidiChannelMap.Unlock();
123      }      }
124    
125      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
126            const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();
127          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
128          {          {
129              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
130              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
131              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
132          }          }
133          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
134          {          {
135              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
136              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
137              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
138          }          }
139            MidiChannelMap.Unlock();
140      }      }
141    
142      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
143            const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();
144          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
145          {          {
146              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
147              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
148              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
149          }          }
150          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
151          {          {
152              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
153              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
154              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
155          }          }
156            MidiChannelMap.Unlock();
157      }      }
158    
159      void MidiInputPort::DispatchSysex(void* pData, uint Size) {      void MidiInputPort::DispatchSysex(void* pData, uint Size) {
160          // dispatch event for engines listening to the same MIDI channel          // dispatch event to all engine instances
161          {          std::set<Engine*>::iterator engineiter = EngineFactory::EngineInstances().begin();
162              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {          std::set<Engine*>::iterator end        = EngineFactory::EngineInstances().end();
163                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);
164                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();      }
165                  for (; engineiter != end; engineiter++) {  
166                      Engine* pEngine = (*engineiter)->GetEngine();      void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
167                      if (pEngine) pEngine->SendSysex(pData, Size);          if (!pDevice || !pDevice->pSampler) {
168                  }              std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
169              }                        << "This is a bug, please report it!\n" << std::flush;
170                return;
171          }          }
172          // dispatch event for engines listening to ALL MIDI channels  
173          {          Sampler*        pSampler        = (Sampler*) pDevice->pSampler;
174              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(Program);
175                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();          if (!pSamplerChannel) return;
176                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();  
177                  for (; engineiter != end; engineiter++) {          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
178                      Engine* pEngine = (*engineiter)->GetEngine();          if (!pEngineChannel) return;
179                      if (pEngine) pEngine->SendSysex(pData, Size);  
180                  }          // disconnect from the engine channel which was connected by the last PC event
181              }          if (pPreviousProgramChangeEngineChannel)
182                Disconnect(pPreviousProgramChangeEngineChannel);
183    
184            // now connect to the new engine channel and remember it
185            try {
186                Connect(pEngineChannel, (midi_chan_t) MidiChannel);
187                pPreviousProgramChangeEngineChannel = pEngineChannel;
188          }          }
189            catch (...) { /* NOOP */ }
190      }      }
191    
192      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
193          if (MidiChannel < 0 || MidiChannel > 16)          if (MidiChannel < 0 || MidiChannel > 16)
194              throw MidiInputException("MIDI channel index out of bounds");              throw MidiInputException("MIDI channel index out of bounds");
195    
196            // first check if desired connection is already established
197            MidiChannelMapMutex.Lock();
198            MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
199            bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
200            MidiChannelMapMutex.Unlock();
201            if (bAlreadyDone) return;
202    
203            // remove all other connections of that engine channel (if any)
204          Disconnect(pEngineChannel);          Disconnect(pEngineChannel);
205          MidiChannelMap[MidiChannel].insert(pEngineChannel);  
206            // register engine channel on the desired MIDI channel
207            MidiChannelMapMutex.Lock();
208            MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
209            MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
210            MidiChannelMapMutex.Unlock();
211    
212            // inform engine channel about this connection
213            pEngineChannel->Connect(this, MidiChannel);
214    
215            // mark engine channel as changed
216            pEngineChannel->StatusChanged(true);
217      }      }
218    
219      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
220          try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngineChannel); }          if (!pEngineChannel) return;
221    
222            bool bChannelFound = false;
223    
224            // unregister engine channel from all MIDI channels
225            MidiChannelMapMutex.Lock();
226            try {
227                {
228                    MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
229                    for (int i = 0; i <= 16; i++) {
230                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
231                        midiChannelMap[i].erase(pEngineChannel);
232                    }
233                }
234                // do the same update again, after switching to the other config
235                {
236                    MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
237                    for (int i = 0; i <= 16; i++) {
238                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
239                        midiChannelMap[i].erase(pEngineChannel);
240                    }
241                }
242            }
243          catch(...) { /* NOOP */ }          catch(...) { /* NOOP */ }
244            MidiChannelMapMutex.Unlock();
245    
246            // inform engine channel about the disconnection (if there is one)
247            if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
248    
249            // mark engine channel as changed
250            pEngineChannel->StatusChanged(true);
251      }      }
252    
253  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC