/[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 221 by schoenebeck, Fri Aug 20 17:25:19 2004 UTC revision 840 by persson, Sun Feb 26 13:00: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                              *
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 22  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 59  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 84  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          std::set<Engine*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();
93          std::set<Engine*>::iterator end        = MidiChannelMap[MidiChannel].end();          // dispatch event for engines listening to the same MIDI channel
94          for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);          {
95                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
96                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
97                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
98            }
99            // dispatch event for engines listening to ALL MIDI channels
100            {
101                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
102                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
103                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          std::set<Engine*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();
110          std::set<Engine*>::iterator end        = MidiChannelMap[MidiChannel].end();          // dispatch event for engines listening to the same MIDI channel
111          for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);          {
112                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
113                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
114                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
115            }
116            // dispatch event for engines listening to ALL MIDI channels
117            {
118                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
119                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
120                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          std::set<Engine*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();
127          std::set<Engine*>::iterator end        = MidiChannelMap[MidiChannel].end();          // dispatch event for engines listening to the same MIDI channel
128          for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);          {
129                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
130                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
131                for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
132            }
133            // dispatch event for engines listening to ALL MIDI channels
134            {
135                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
136                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
137                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          std::set<Engine*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();
144          std::set<Engine*>::iterator end        = MidiChannelMap[MidiChannel].end();          // dispatch event for engines listening to the same MIDI channel
145          for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);          {
146                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
147                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
148                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
149            }
150            // dispatch event for engines listening to ALL MIDI channels
151            {
152                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
153                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
154                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
155            }
156            MidiChannelMap.Unlock();
157        }
158    
159        void MidiInputPort::DispatchSysex(void* pData, uint Size) {
160            // dispatch event to all engine instances
161            std::set<Engine*>::iterator engineiter = EngineFactory::EngineInstances().begin();
162            std::set<Engine*>::iterator end        = EngineFactory::EngineInstances().end();
163            for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);
164        }
165    
166        void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
167            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    
173            Sampler*        pSampler        = (Sampler*) pDevice->pSampler;
174            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(Program);
175            if (!pSamplerChannel) return;
176    
177            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
178            if (!pEngineChannel) return;
179    
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(Engine* pEngine, 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");
         Disconnect(pEngine);  
         MidiChannelMap[MidiChannel].insert(pEngine);  
     }  
195    
196      void MidiInputPort::Disconnect(Engine* pEngine) {          // first check if desired connection is already established
197          try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngine); }          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);
205    
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) {
220            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.221  
changed lines
  Added in v.840

  ViewVC Help
Powered by ViewVC