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

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

  ViewVC Help
Powered by ViewVC