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

Legend:
Removed from v.274  
changed lines
  Added in v.675

  ViewVC Help
Powered by ViewVC