/[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 880 by schoenebeck, Tue Jun 27 22:57:37 2006 UTC revision 973 by schoenebeck, Fri Dec 15 21:40:27 2006 UTC
# Line 23  Line 23 
23    
24  #include "MidiInputPort.h"  #include "MidiInputPort.h"
25    
26    #include "MidiInstrumentMapper.h"
27  #include "../../Sampler.h"  #include "../../Sampler.h"
28  #include "../../engines/EngineFactory.h"  #include "../../engines/EngineFactory.h"
29    
# Line 75  namespace LinuxSampler { Line 76  namespace LinuxSampler {
76          this->pDevice = pDevice;          this->pDevice = pDevice;
77          this->portNumber = portNumber;          this->portNumber = portNumber;
78          Parameters["NAME"] = new ParameterName(this);          Parameters["NAME"] = new ParameterName(this);
         pPreviousProgramChangeEngineChannel = NULL;  
79      }      }
80    
81      MidiInputDevice* MidiInputPort::GetDevice() {      MidiInputDevice* MidiInputPort::GetDevice() {
# Line 91  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();          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          {          {
# Line 107  namespace LinuxSampler { Line 108  namespace LinuxSampler {
108          MidiChannelMapReader.Unlock();          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();          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          {          {
# Line 124  namespace LinuxSampler { Line 144  namespace LinuxSampler {
144          MidiChannelMapReader.Unlock();          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();          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          {          {
# Line 141  namespace LinuxSampler { Line 180  namespace LinuxSampler {
180          MidiChannelMapReader.Unlock();          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();          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          {          {
# Line 158  namespace LinuxSampler { Line 216  namespace LinuxSampler {
216          MidiChannelMapReader.Unlock();          MidiChannelMapReader.Unlock();
217      }      }
218    
219        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
223            {
224                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
225                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
226                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
227            }
228            // dispatch event for engines listening to ALL MIDI channels
229            {
230                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
231                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
232                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
233            }
234            MidiChannelMapReader.Unlock();
235        }
236    
237      void MidiInputPort::DispatchSysex(void* pData, uint Size) {      void MidiInputPort::DispatchSysex(void* pData, uint Size) {
238          const std::set<Engine*> allEngines = SysexListenersReader.Lock();          const std::set<Engine*> allEngines = SysexListenersReader.Lock();
239          // dispatch event to all engine instances          // dispatch event to all engine instances
# Line 168  namespace LinuxSampler { Line 244  namespace LinuxSampler {
244      }      }
245    
246      void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {      void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
247            dmsg(1,("Received MIDI program change (prog=%d,ch=%d)\n",Program,MidiChannel));
248            if (Program > 127 || MidiChannel > 16) return;
249          if (!pDevice || !pDevice->pSampler) {          if (!pDevice || !pDevice->pSampler) {
250              std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."              std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
251                        << "This is a bug, please report it!\n" << std::flush;                        << "This is a bug, please report it!\n" << std::flush;
252              return;              return;
253          }          }
254            std::vector<int> maps = MidiInstrumentMapper::Maps();
255            if (maps.empty()) return;
256    
257            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
258            // dispatch event for engines listening to the same MIDI channel
259            {
260                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
261                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
262                for (; engineiter != end; engineiter++) {
263                    (*engineiter)->SetMidiProgram(Program);
264                    if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
265                    // retrieve the MIDI instrument map this engine channel is assigned to
266                    int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
267                        ? maps[0] /*default*/ : (*engineiter)->GetMidiInstrumentMap();
268                    // is there an entry for this MIDI bank&prog pair in that map?
269                    midi_prog_index_t midiIndex;
270                    midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
271                    midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
272                    midiIndex.midi_prog     = (*engineiter)->GetMidiProgram();
273                    optional<MidiInstrumentMapper::entry_t> mapping =
274                        MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
275                    if (mapping) { // if mapping exists ...
276                        InstrumentManager::instrument_id_t id;
277                        id.FileName = mapping->InstrumentFile;
278                        id.Index    = mapping->InstrumentIndex;
279                        //TODO: we should switch the engine type here
280                        InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
281                        (*engineiter)->Volume(mapping->Volume);
282                    }
283                }
284            }
285            // dispatch event for engines listening to ALL MIDI channels
286            {
287                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
288                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
289                for (; engineiter != end; engineiter++) {
290                    (*engineiter)->SetMidiProgram(Program);
291                    if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
292                    // retrieve the MIDI instrument map this engine channel is assigned to
293                    int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
294                        ? maps[0] /*default*/ : (*engineiter)->GetMidiInstrumentMap();
295                    // is there an entry for this MIDI bank&prog pair in that map?
296                    midi_prog_index_t midiIndex;
297                    midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
298                    midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
299                    midiIndex.midi_prog     = (*engineiter)->GetMidiProgram();
300                    optional<MidiInstrumentMapper::entry_t> mapping =
301                        MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
302                    if (mapping) { // if mapping exists ...
303                        InstrumentManager::instrument_id_t id;
304                        id.FileName = mapping->InstrumentFile;
305                        id.Index    = mapping->InstrumentIndex;
306                        //TODO: we should switch the engine type here
307                        InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
308                        (*engineiter)->Volume(mapping->Volume);
309                    }
310                }
311            }
312            MidiChannelMapReader.Unlock();
313        }
314    
315          Sampler*        pSampler        = (Sampler*) pDevice->pSampler;      void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
316          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(Program);          if (BankMSB > 127 || MidiChannel > 16) return;
317          if (!pSamplerChannel) return;          if (!pDevice || !pDevice->pSampler) {
318                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select MSB."
319          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();                        << "This is a bug, please report it!\n" << std::flush;
320          if (!pEngineChannel) return;              return;
   
         // disconnect from the engine channel which was connected by the last PC event  
         if (pPreviousProgramChangeEngineChannel)  
             Disconnect(pPreviousProgramChangeEngineChannel);  
   
         // now connect to the new engine channel and remember it  
         try {  
             Connect(pEngineChannel, (midi_chan_t) MidiChannel);  
             pPreviousProgramChangeEngineChannel = pEngineChannel;  
321          }          }
322          catch (...) { /* NOOP */ }          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
323            // dispatch event for engines listening to the same MIDI channel
324            {
325                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
326                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
327                // according to the MIDI specs, a bank select should not alter the patch
328                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
329            }
330            // dispatch event for engines listening to ALL MIDI channels
331            {
332                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
333                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
334                // according to the MIDI specs, a bank select should not alter the patch
335                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
336            }
337            MidiChannelMapReader.Unlock();
338        }
339    
340        void MidiInputPort::DispatchBankSelectLsb(uint8_t BankLSB, uint MidiChannel) {
341            if (BankLSB > 127 || MidiChannel > 16) return;
342            if (!pDevice || !pDevice->pSampler) {
343                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select LSB."
344                          << "This is a bug, please report it!\n" << std::flush;
345                return;
346            }
347            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
348            // dispatch event for engines listening to the same MIDI channel
349            {
350                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
351                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
352                // according to the MIDI specs, a bank select should not alter the patch
353                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
354            }
355            // dispatch event for engines listening to ALL MIDI channels
356            {
357                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
358                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
359                // according to the MIDI specs, a bank select should not alter the patch
360                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
361            }
362            MidiChannelMapReader.Unlock();
363      }      }
364    
365      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {

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

  ViewVC Help
Powered by ViewVC