/[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 906 by schoenebeck, Sun Jul 23 16:44:08 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 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 48  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 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            : 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);
78            pPreviousProgramChangeEngineChannel = NULL;
79      }      }
80    
81      MidiInputDevice* MidiInputPort::GetDevice() {      MidiInputDevice* MidiInputPort::GetDevice() {
# Line 85  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::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
111            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
112            // dispatch event for engines listening to the same MIDI channel
113            {
114                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
115                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
116                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, FragmentPos);
117            }
118            // dispatch event for engines listening to ALL MIDI channels
119            {
120                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
121                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
122                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, FragmentPos);
123            }
124            MidiChannelMapReader.Unlock();
125      }      }
126    
127      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, 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)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
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)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
140          }          }
141            MidiChannelMapReader.Unlock();
142        }
143    
144        void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
145            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
146            // dispatch event for engines listening to the same MIDI channel
147            {
148                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
149                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
150                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, FragmentPos);
151            }
152            // dispatch event for engines listening to ALL MIDI channels
153            {
154                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
155                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
156                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, FragmentPos);
157            }
158            MidiChannelMapReader.Unlock();
159      }      }
160    
161      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
162            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
163          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
164          {          {
165              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
166              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
167              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
168          }          }
169          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
170          {          {
171              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
172              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
173              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
174          }          }
175            MidiChannelMapReader.Unlock();
176        }
177    
178        void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
179            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
180            // dispatch event for engines listening to the same MIDI channel
181            {
182                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
183                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
184                for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, FragmentPos);
185            }
186            // dispatch event for engines listening to ALL MIDI channels
187            {
188                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
189                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
190                for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, FragmentPos);
191            }
192            MidiChannelMapReader.Unlock();
193      }      }
194    
195      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
196            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
197          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
198          {          {
199              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
200              std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
201              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
202          }          }
203          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
204          {          {
205              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
206              std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
207              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
208          }          }
209            MidiChannelMapReader.Unlock();
210      }      }
211    
212      void MidiInputPort::DispatchSysex(void* pData, uint Size) {      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
213            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
214          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
215          {          {
216              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
217                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
218                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
                 for (; engineiter != end; engineiter++) {  
                     Engine* pEngine = (*engineiter)->GetEngine();  
                     if (pEngine) pEngine->SendSysex(pData, Size);  
                 }  
             }  
219          }          }
220          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
221          {          {
222              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
223                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
224                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
225                  for (; engineiter != end; engineiter++) {          }
226                      Engine* pEngine = (*engineiter)->GetEngine();          MidiChannelMapReader.Unlock();
227                      if (pEngine) pEngine->SendSysex(pData, Size);      }
228                  }  
229              }      void MidiInputPort::DispatchSysex(void* pData, uint Size) {
230            const std::set<Engine*> allEngines = SysexListenersReader.Lock();
231            // dispatch event to all engine instances
232            std::set<Engine*>::iterator engineiter = allEngines.begin();
233            std::set<Engine*>::iterator end        = allEngines.end();
234            for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);
235            SysexListenersReader.Unlock();
236        }
237    
238        void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
239            if (!pDevice || !pDevice->pSampler) {
240                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
241                          << "This is a bug, please report it!\n" << std::flush;
242                return;
243            }
244    
245            Sampler*        pSampler        = (Sampler*) pDevice->pSampler;
246            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(Program);
247            if (!pSamplerChannel) return;
248    
249            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
250            if (!pEngineChannel) return;
251    
252            // disconnect from the engine channel which was connected by the last PC event
253            if (pPreviousProgramChangeEngineChannel)
254                Disconnect(pPreviousProgramChangeEngineChannel);
255    
256            // now connect to the new engine channel and remember it
257            try {
258                Connect(pEngineChannel, (midi_chan_t) MidiChannel);
259                pPreviousProgramChangeEngineChannel = pEngineChannel;
260          }          }
261            catch (...) { /* NOOP */ }
262      }      }
263    
264      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
265          if (MidiChannel < 0 || MidiChannel > 16)          if (MidiChannel < 0 || MidiChannel > 16)
266              throw MidiInputException("MIDI channel index out of bounds");              throw MidiInputException("MIDI channel index out of bounds");
267    
268            // first check if desired connection is already established
269            MidiChannelMapMutex.Lock();
270            MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
271            bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
272            MidiChannelMapMutex.Unlock();
273            if (bAlreadyDone) return;
274    
275            // remove all other connections of that engine channel (if any)
276          Disconnect(pEngineChannel);          Disconnect(pEngineChannel);
277          MidiChannelMap[MidiChannel].insert(pEngineChannel);  
278            // register engine channel on the desired MIDI channel
279            MidiChannelMapMutex.Lock();
280            MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
281            MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
282            MidiChannelMapMutex.Unlock();
283    
284            // inform engine channel about this connection
285            pEngineChannel->Connect(this, MidiChannel);
286    
287            // mark engine channel as changed
288            pEngineChannel->StatusChanged(true);
289      }      }
290    
291      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
292          try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngineChannel); }          if (!pEngineChannel) return;
293    
294            bool bChannelFound = false;
295    
296            // unregister engine channel from all MIDI channels
297            MidiChannelMapMutex.Lock();
298            try {
299                {
300                    MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
301                    for (int i = 0; i <= 16; i++) {
302                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
303                        midiChannelMap[i].erase(pEngineChannel);
304                    }
305                }
306                // do the same update again, after switching to the other config
307                {
308                    MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
309                    for (int i = 0; i <= 16; i++) {
310                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
311                        midiChannelMap[i].erase(pEngineChannel);
312                    }
313                }
314            }
315          catch(...) { /* NOOP */ }          catch(...) { /* NOOP */ }
316            MidiChannelMapMutex.Unlock();
317    
318            // inform engine channel about the disconnection (if there is one)
319            if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
320    
321            // mark engine channel as changed
322            pEngineChannel->StatusChanged(true);
323        }
324    
325        SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
326    
327        void MidiInputPort::AddSysexListener(Engine* engine) {
328            std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
329            if (p.second) SysexListeners.SwitchConfig().insert(engine);
330        }
331    
332        bool MidiInputPort::RemoveSysexListener(Engine* engine) {
333            int count = SysexListeners.GetConfigForUpdate().erase(engine);
334            if (count) SysexListeners.SwitchConfig().erase(engine);
335            return count;
336      }      }
337    
338  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC