/[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 922 by persson, Mon Oct 2 18:40:10 2006 UTC revision 1135 by iliev, Thu Mar 29 09:40:45 2007 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 244  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;          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          Sampler*        pSampler        = (Sampler*) pDevice->pSampler;          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
258          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(Program);          // dispatch event for engines listening to the same MIDI channel
259          if (!pSamplerChannel) return;          {
260                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
261          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
262          if (!pEngineChannel) return;              for (; engineiter != end; engineiter++) {
263                    (*engineiter)->SetMidiProgram(Program);
264          // disconnect from the engine channel which was connected by the last PC event                  if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
265          if (pPreviousProgramChangeEngineChannel)                  if (MidiInstrumentMapper::GetMapCount() == 0) continue;
266              Disconnect(pPreviousProgramChangeEngineChannel);                  // retrieve the MIDI instrument map this engine channel is assigned to
267                    int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
268          // now connect to the new engine channel and remember it                      ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
269          try {                  // is there an entry for this MIDI bank&prog pair in that map?
270              Connect(pEngineChannel, (midi_chan_t) MidiChannel);                  midi_prog_index_t midiIndex;
271              pPreviousProgramChangeEngineChannel = pEngineChannel;                  midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
272                    midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
273                    midiIndex.midi_prog     = (*engineiter)->GetMidiProgram();
274                    optional<MidiInstrumentMapper::entry_t> mapping =
275                        MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
276                    if (mapping) { // if mapping exists ...
277                        InstrumentManager::instrument_id_t id;
278                        id.FileName = mapping->InstrumentFile;
279                        id.Index    = mapping->InstrumentIndex;
280                        //TODO: we should switch the engine type here
281                        InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
282                        (*engineiter)->Volume(mapping->Volume);
283                    }
284                }
285            }
286            // dispatch event for engines listening to ALL MIDI channels
287            {
288                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
289                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
290                for (; engineiter != end; engineiter++) {
291                    (*engineiter)->SetMidiProgram(Program);
292                    if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
293                    if (MidiInstrumentMapper::GetMapCount() == 0) continue;
294                    // retrieve the MIDI instrument map this engine channel is assigned to
295                    int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
296                        ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
297                    // is there an entry for this MIDI bank&prog pair in that map?
298                    midi_prog_index_t midiIndex;
299                    midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
300                    midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
301                    midiIndex.midi_prog     = (*engineiter)->GetMidiProgram();
302                    optional<MidiInstrumentMapper::entry_t> mapping =
303                        MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
304                    if (mapping) { // if mapping exists ...
305                        InstrumentManager::instrument_id_t id;
306                        id.FileName = mapping->InstrumentFile;
307                        id.Index    = mapping->InstrumentIndex;
308                        //TODO: we should switch the engine type here
309                        InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
310                        (*engineiter)->Volume(mapping->Volume);
311                    }
312                }
313            }
314            MidiChannelMapReader.Unlock();
315        }
316    
317        void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
318            if (BankMSB > 127 || MidiChannel > 16) return;
319            if (!pDevice || !pDevice->pSampler) {
320                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select MSB."
321                          << "This is a bug, please report it!\n" << std::flush;
322                return;
323            }
324            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
325            // dispatch event for engines listening to the same MIDI channel
326            {
327                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
328                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
329                // according to the MIDI specs, a bank select should not alter the patch
330                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
331          }          }
332          catch (...) { /* NOOP */ }          // dispatch event for engines listening to ALL MIDI channels
333            {
334                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
335                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
336                // according to the MIDI specs, a bank select should not alter the patch
337                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
338            }
339            MidiChannelMapReader.Unlock();
340        }
341    
342        void MidiInputPort::DispatchBankSelectLsb(uint8_t BankLSB, uint MidiChannel) {
343            if (BankLSB > 127 || MidiChannel > 16) return;
344            if (!pDevice || !pDevice->pSampler) {
345                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select LSB."
346                          << "This is a bug, please report it!\n" << std::flush;
347                return;
348            }
349            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
350            // dispatch event for engines listening to the same MIDI channel
351            {
352                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
353                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
354                // according to the MIDI specs, a bank select should not alter the patch
355                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
356            }
357            // dispatch event for engines listening to ALL MIDI channels
358            {
359                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
360                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
361                // according to the MIDI specs, a bank select should not alter the patch
362                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
363            }
364            MidiChannelMapReader.Unlock();
365      }      }
366    
367      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {

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

  ViewVC Help
Powered by ViewVC