/[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 244 by schoenebeck, Fri Sep 17 01:01:11 2004 UTC revision 836 by persson, Wed Feb 8 20:28:46 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();          // dispatch event for engines listening to the same MIDI channel
93          std::set<Engine*>::iterator end        = MidiChannelMap[MidiChannel].end();          {
94          for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
95                std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();
96                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
97            }
98            // dispatch event for engines listening to ALL MIDI channels
99            {
100                std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
101                std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();
102                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
103            }
104      }      }
105    
106      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
107          std::set<Engine*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          // dispatch event for engines listening to the same MIDI channel
108          std::set<Engine*>::iterator end        = MidiChannelMap[MidiChannel].end();          {
109          for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
110                std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();
111                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
112            }
113            // dispatch event for engines listening to ALL MIDI channels
114            {
115                std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
116                std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();
117                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
118            }
119      }      }
120    
121      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
122          std::set<Engine*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          // dispatch event for engines listening to the same MIDI channel
123          std::set<Engine*>::iterator end        = MidiChannelMap[MidiChannel].end();          {
124          for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
125                std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();
126                for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
127            }
128            // dispatch event for engines listening to ALL MIDI channels
129            {
130                std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
131                std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();
132                for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
133            }
134      }      }
135    
136      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
137          std::set<Engine*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          // dispatch event for engines listening to the same MIDI channel
138          std::set<Engine*>::iterator end        = MidiChannelMap[MidiChannel].end();          {
139          for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
140                std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();
141                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
142            }
143            // dispatch event for engines listening to ALL MIDI channels
144            {
145                std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
146                std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();
147                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
148            }
149      }      }
150    
151      void MidiInputPort::DispatchSysex(void* pData, uint Size) {      void MidiInputPort::DispatchSysex(void* pData, uint Size) {
152          for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {          // dispatch event to all engine instances
153              std::set<Engine*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();          std::set<Engine*>::iterator engineiter = EngineFactory::EngineInstances().begin();
154              std::set<Engine*>::iterator end        = MidiChannelMap[MidiChannel].end();          std::set<Engine*>::iterator end        = EngineFactory::EngineInstances().end();
155              for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);          for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);
156        }
157    
158        void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
159            if (!pDevice || !pDevice->pSampler) {
160                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
161                          << "This is a bug, please report it!\n" << std::flush;
162                return;
163            }
164    
165            Sampler*        pSampler        = (Sampler*) pDevice->pSampler;
166            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(Program);
167            if (!pSamplerChannel) return;
168    
169            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
170            if (!pEngineChannel) return;
171    
172            // disconnect from the engine channel which was connected by the last PC event
173            if (pPreviousProgramChangeEngineChannel)
174                Disconnect(pPreviousProgramChangeEngineChannel);
175    
176            // now connect to the new engine channel and remember it
177            try {
178                Connect(pEngineChannel, (midi_chan_t) MidiChannel);
179                pPreviousProgramChangeEngineChannel = pEngineChannel;
180          }          }
181            catch (...) { /* NOOP */ }
182      }      }
183    
184      void MidiInputPort::Connect(Engine* pEngine, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
185          if (MidiChannel < 0 || MidiChannel > 16)          if (MidiChannel < 0 || MidiChannel > 16)
186              throw MidiInputException("MIDI channel index out of bounds");              throw MidiInputException("MIDI channel index out of bounds");
         Disconnect(pEngine);  
         MidiChannelMap[MidiChannel].insert(pEngine);  
     }  
187    
188      void MidiInputPort::Disconnect(Engine* pEngine) {          // firt check if desired connection is already established
189          try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngine); }          MidiChannelMapMutex.Lock();
190            bool bAlreadyDone = MidiChannelMap[MidiChannel].count(pEngineChannel);
191            MidiChannelMapMutex.Unlock();
192            if (bAlreadyDone) return;
193    
194            // remove all other connections of that engine channel (if any)
195            Disconnect(pEngineChannel);
196    
197            // register engine channel on the desired MIDI channel
198            MidiChannelMapMutex.Lock();
199            MidiChannelMap[MidiChannel].insert(pEngineChannel);
200            MidiChannelMapMutex.Unlock();
201    
202            // inform engine channel about this connection
203            pEngineChannel->Connect(this, MidiChannel);
204    
205            // mark engine channel as changed
206            pEngineChannel->StatusChanged(true);
207        }
208    
209        void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
210            if (!pEngineChannel) return;
211    
212            bool bChannelFound = false;
213    
214            // unregister engine channel from all MIDI channels
215            MidiChannelMapMutex.Lock();
216            try {
217                for (int i = 0; i <= 16; i++) {
218                    bChannelFound |= MidiChannelMap[i].count(pEngineChannel);
219                    MidiChannelMap[i].erase(pEngineChannel);
220                }
221            }
222          catch(...) { /* NOOP */ }          catch(...) { /* NOOP */ }
223            MidiChannelMapMutex.Unlock();
224    
225            // inform engine channel about the disconnection (if there is one)
226            if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
227    
228            // mark engine channel as changed
229            pEngineChannel->StatusChanged(true);
230      }      }
231    
232  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.244  
changed lines
  Added in v.836

  ViewVC Help
Powered by ViewVC