/[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 2559 by schoenebeck, Sun May 18 17:38:25 2014 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, 2006 Christian Schoenebeck                        *   *   Copyright (C) 2005 - 2014 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 23  Line 23 
23    
24  #include "MidiInputPort.h"  #include "MidiInputPort.h"
25    
26    #include "../../common/global_private.h"
27    #include "MidiInstrumentMapper.h"
28  #include "../../Sampler.h"  #include "../../Sampler.h"
29  #include "../../engines/EngineFactory.h"  #include "../../engines/EngineFactory.h"
30    #include "VirtualMidiDevice.h"
31    
32    #include <algorithm>
33    
34  namespace LinuxSampler {  namespace LinuxSampler {
35    
# Line 71  namespace LinuxSampler { Line 76  namespace LinuxSampler {
76    
77      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
78          : MidiChannelMapReader(MidiChannelMap),          : MidiChannelMapReader(MidiChannelMap),
79            SysexListenersReader(SysexListeners) {            SysexListenersReader(SysexListeners),
80              virtualMidiDevicesReader(virtualMidiDevices),
81              noteOnVelocityFilterReader(noteOnVelocityFilter)
82        {
83          this->pDevice = pDevice;          this->pDevice = pDevice;
84          this->portNumber = portNumber;          this->portNumber = portNumber;
85            runningStatusBuf[0] = 0;
86          Parameters["NAME"] = new ParameterName(this);          Parameters["NAME"] = new ParameterName(this);
         pPreviousProgramChangeEngineChannel = NULL;  
87      }      }
88    
89      MidiInputDevice* MidiInputPort::GetDevice() {      MidiInputDevice* MidiInputPort::GetDevice() {
# Line 91  namespace LinuxSampler { Line 99  namespace LinuxSampler {
99      }      }
100    
101      void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
102            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
103            
104            // apply velocity filter (if any)
105            const std::vector<uint8_t>& velocityFilter = noteOnVelocityFilterReader.Lock();
106            if (!velocityFilter.empty()) Velocity = velocityFilter[Velocity];
107            noteOnVelocityFilterReader.Unlock();
108            
109          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
110          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
111          {          {
112              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
113              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
114              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
115          }          }
116          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
117          {          {
118              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
119              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
120              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
121          }          }
122          MidiChannelMapReader.Unlock();          MidiChannelMapReader.Unlock();
123    
124            // dispatch event to all low priority MIDI listeners
125            const std::vector<VirtualMidiDevice*>& listeners =
126                virtualMidiDevicesReader.Lock();
127            for (int i = 0; i < listeners.size(); ++i)
128                listeners[i]->SendNoteOnToDevice(Key, Velocity);
129            virtualMidiDevicesReader.Unlock();
130        }
131    
132        void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
133            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
134            
135            // apply velocity filter (if any)
136            const std::vector<uint8_t>& velocityFilter = noteOnVelocityFilterReader.Lock();
137            if (!velocityFilter.empty()) Velocity = velocityFilter[Velocity];
138            noteOnVelocityFilterReader.Unlock();
139            
140            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
141            // dispatch event for engines listening to the same MIDI channel
142            {
143                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
144                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
145                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
146            }
147            // dispatch event for engines listening to ALL MIDI channels
148            {
149                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
150                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
151                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
152            }
153            MidiChannelMapReader.Unlock();
154    
155            // dispatch event to all low priority MIDI listeners
156            const std::vector<VirtualMidiDevice*>& listeners =
157                virtualMidiDevicesReader.Lock();
158            for (int i = 0; i < listeners.size(); ++i)
159                listeners[i]->SendNoteOnToDevice(Key, Velocity);
160            virtualMidiDevicesReader.Unlock();
161      }      }
162    
163      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {      void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
164            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
165          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
166          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
167          {          {
168              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
169              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
170              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
171          }          }
172          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
173          {          {
174              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
175              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
176              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
177          }          }
178          MidiChannelMapReader.Unlock();          MidiChannelMapReader.Unlock();
179    
180            // dispatch event to all low priority MIDI listeners
181            const std::vector<VirtualMidiDevice*>& listeners =
182                virtualMidiDevicesReader.Lock();
183            for (int i = 0; i < listeners.size(); ++i)
184                listeners[i]->SendNoteOffToDevice(Key, Velocity);
185            virtualMidiDevicesReader.Unlock();
186        }
187    
188        void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
189            if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
190            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
191            // dispatch event for engines listening to the same MIDI channel
192            {
193                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
194                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
195                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
196            }
197            // dispatch event for engines listening to ALL MIDI channels
198            {
199                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
200                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
201                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
202            }
203            MidiChannelMapReader.Unlock();
204    
205            // dispatch event to all low priority MIDI listeners
206            const std::vector<VirtualMidiDevice*>& listeners =
207                virtualMidiDevicesReader.Lock();
208            for (int i = 0; i < listeners.size(); ++i)
209                listeners[i]->SendNoteOffToDevice(Key, Velocity);
210            virtualMidiDevicesReader.Unlock();
211      }      }
212    
213      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {      void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
214            if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
215            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
216            // dispatch event for engines listening to the same MIDI channel
217            {
218                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
219                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
220                for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
221            }
222            // dispatch event for engines listening to ALL MIDI channels
223            {
224                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
225                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
226                for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
227            }
228            MidiChannelMapReader.Unlock();
229        }
230    
231        void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
232            if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
233            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
234            // dispatch event for engines listening to the same MIDI channel
235            {
236                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
237                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
238                for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
239            }
240            // dispatch event for engines listening to ALL MIDI channels
241            {
242                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
243                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
244                for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
245            }
246            MidiChannelMapReader.Unlock();
247        }
248    
249        void MidiInputPort::DispatchChannelPressure(uint8_t Value, uint MidiChannel) {
250            if (Value > 127 || MidiChannel > 16) return;
251            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
252            // dispatch event for engines listening to the same MIDI channel
253            {
254                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
255                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
256                for (; engineiter != end; engineiter++) (*engineiter)->SendChannelPressure(Value, MidiChannel);
257            }
258            // dispatch event for engines listening to ALL MIDI channels
259            {
260                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
261                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
262                for (; engineiter != end; engineiter++) (*engineiter)->SendChannelPressure(Value, MidiChannel);
263            }
264            MidiChannelMapReader.Unlock();
265        }
266    
267        void MidiInputPort::DispatchChannelPressure(uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
268            if (Value > 127 || MidiChannel > 16) return;
269            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
270            // dispatch event for engines listening to the same MIDI channel
271            {
272                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
273                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
274                for (; engineiter != end; engineiter++) (*engineiter)->SendChannelPressure(Value, MidiChannel, FragmentPos);
275            }
276            // dispatch event for engines listening to ALL MIDI channels
277            {
278                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
279                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
280                for (; engineiter != end; engineiter++) (*engineiter)->SendChannelPressure(Value, MidiChannel, FragmentPos);
281            }
282            MidiChannelMapReader.Unlock();
283        }
284    
285        void MidiInputPort::DispatchPolyphonicKeyPressure(uint8_t Key, uint8_t Value, uint MidiChannel) {
286            if (Key > 127 || Value > 127 || MidiChannel > 16) return;
287            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
288            // dispatch event for engines listening to the same MIDI channel
289            {
290                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
291                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
292                for (; engineiter != end; engineiter++) (*engineiter)->SendPolyphonicKeyPressure(Key, Value, MidiChannel);
293            }
294            // dispatch event for engines listening to ALL MIDI channels
295            {
296                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
297                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
298                for (; engineiter != end; engineiter++) (*engineiter)->SendPolyphonicKeyPressure(Key, Value, MidiChannel);
299            }
300            MidiChannelMapReader.Unlock();
301        }
302    
303        void MidiInputPort::DispatchPolyphonicKeyPressure(uint8_t Key, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
304            if (Key > 127 || Value > 127 || MidiChannel > 16) return;
305          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
306          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
307          {          {
308              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
309              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
310              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPolyphonicKeyPressure(Key, Value, MidiChannel, FragmentPos);
311          }          }
312          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
313          {          {
314              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
315              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
316              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPolyphonicKeyPressure(Key, Value, MidiChannel, FragmentPos);
317          }          }
318          MidiChannelMapReader.Unlock();          MidiChannelMapReader.Unlock();
319      }      }
320    
321      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
322            if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
323          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
324          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
325          {          {
326              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
327              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
328              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
329          }          }
330          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
331          {          {
332              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
333              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
334              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
335          }          }
336          MidiChannelMapReader.Unlock();          MidiChannelMapReader.Unlock();
337            
338            // dispatch event to all low priority MIDI listeners
339            const std::vector<VirtualMidiDevice*>& listeners =
340                virtualMidiDevicesReader.Lock();
341            for (int i = 0; i < listeners.size(); ++i)
342                listeners[i]->SendCCToDevice(Controller, Value);
343            virtualMidiDevicesReader.Unlock();
344        }
345    
346        void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
347            if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
348            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
349            // dispatch event for engines listening to the same MIDI channel
350            {
351                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
352                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
353                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
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                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
360            }
361            MidiChannelMapReader.Unlock();
362            
363            // dispatch event to all low priority MIDI listeners
364            const std::vector<VirtualMidiDevice*>& listeners =
365                virtualMidiDevicesReader.Lock();
366            for (int i = 0; i < listeners.size(); ++i)
367                listeners[i]->SendCCToDevice(Controller, Value);
368            virtualMidiDevicesReader.Unlock();
369      }      }
370    
371      void MidiInputPort::DispatchSysex(void* pData, uint Size) {      void MidiInputPort::DispatchSysex(void* pData, uint Size) {
# Line 163  namespace LinuxSampler { Line 373  namespace LinuxSampler {
373          // dispatch event to all engine instances          // dispatch event to all engine instances
374          std::set<Engine*>::iterator engineiter = allEngines.begin();          std::set<Engine*>::iterator engineiter = allEngines.begin();
375          std::set<Engine*>::iterator end        = allEngines.end();          std::set<Engine*>::iterator end        = allEngines.end();
376          for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);          for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
377          SysexListenersReader.Unlock();          SysexListenersReader.Unlock();
378      }      }
379    
380      void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {      void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
381            if (Program > 127 || MidiChannel > 16) return;
382          if (!pDevice || !pDevice->pSampler) {          if (!pDevice || !pDevice->pSampler) {
383              std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."              std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
384                        << "This is a bug, please report it!\n" << std::flush;                        << "This is a bug, please report it!\n" << std::flush;
385              return;              return;
386          }          }
387    
388          Sampler*        pSampler        = (Sampler*) pDevice->pSampler;          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
389          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(Program);          // dispatch event for engines listening to the same MIDI channel
390          if (!pSamplerChannel) return;          {
391                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
392                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
393                for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
394            }
395            // dispatch event for engines listening to ALL MIDI channels
396            {
397                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
398                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
399                for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
400            }
401            MidiChannelMapReader.Unlock();
402        }
403    
404          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();      void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
405          if (!pEngineChannel) return;          if (BankMSB > 127 || MidiChannel > 16) return;
406            if (!pDevice || !pDevice->pSampler) {
407                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select MSB."
408                          << "This is a bug, please report it!\n" << std::flush;
409                return;
410            }
411            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
412            // dispatch event for engines listening to the same MIDI channel
413            {
414                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
415                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
416                // according to the MIDI specs, a bank select should not alter the patch
417                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
418            }
419            // dispatch event for engines listening to ALL MIDI channels
420            {
421                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
422                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
423                // according to the MIDI specs, a bank select should not alter the patch
424                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
425            }
426            MidiChannelMapReader.Unlock();
427        }
428    
429        void MidiInputPort::DispatchBankSelectLsb(uint8_t BankLSB, uint MidiChannel) {
430            if (BankLSB > 127 || MidiChannel > 16) return;
431            if (!pDevice || !pDevice->pSampler) {
432                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select LSB."
433                          << "This is a bug, please report it!\n" << std::flush;
434                return;
435            }
436            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
437            // dispatch event for engines listening to the same MIDI channel
438            {
439                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
440                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
441                // according to the MIDI specs, a bank select should not alter the patch
442                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
443            }
444            // dispatch event for engines listening to ALL MIDI channels
445            {
446                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
447                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
448                // according to the MIDI specs, a bank select should not alter the patch
449                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
450            }
451            MidiChannelMapReader.Unlock();
452        }
453        
454        /**
455         * Handles the so called MIDI "running status" mode, which allows devices
456         * to reduce bandwidth (data reduction).
457         *
458         * If the passed in MIDI data is regular MIDI data, this method will simply
459         * return the original data pointer and just stores the status byte for
460         * potential "running status" event eventually coming next.
461         *
462         * If the passed in MIDI data however seems to be in "running status" mode,
463         * this method will return another buffer, which allows the MIDI parser
464         * to handle the MIDI data as usually with "normal" MIDI data.
465         */
466        uint8_t* MidiInputPort::handleRunningStatus(uint8_t* pData) {
467            if ((pData[0] & 0x80) || !runningStatusBuf[0]) {
468                // store status byte for eventual "running status" in next event
469                if (pData[0] & 0x80) {
470                    if (pData[0] < 0xf0) {
471                        // "running status" is only allowed for channel messages
472                        runningStatusBuf[0] = pData[0];
473                    } else if (pData[0] < 0xf8) {
474                        // "system common" messages (0xf0..0xf7) shall reset any running
475                        // status, however "realtime" messages (0xf8..0xff) shall be
476                        // ignored here
477                        runningStatusBuf[0] = 0;
478                    }
479                }
480                // it's either a regular status byte, or some invalid "running status"
481                return pData;
482            } else { // "running status" mode ...
483                const uint8_t type = runningStatusBuf[0] & 0xf0;
484                const int size = (type == 0xc0 || type == 0xd0) ? 1 : 2; // only program change & channel pressure have 1 data bytes
485                memcpy(&runningStatusBuf[1], pData, size);
486                return runningStatusBuf;
487            }
488        }
489    
490          // disconnect from the engine channel which was connected by the last PC event      void MidiInputPort::DispatchRaw(uint8_t* pData) {
491          if (pPreviousProgramChangeEngineChannel)          pData = handleRunningStatus(pData);
492              Disconnect(pPreviousProgramChangeEngineChannel);          
493            uint8_t channel = pData[0] & 0x0f;
494            switch (pData[0] & 0xf0) {
495            case 0x80:
496                DispatchNoteOff(pData[1], pData[2], channel);
497                break;
498            case 0x90:
499                if (pData[2]) {
500                    DispatchNoteOn(pData[1], pData[2], channel);
501                } else {
502                    DispatchNoteOff(pData[1], pData[2], channel);
503                }
504                break;
505            case 0xA0:
506                DispatchPolyphonicKeyPressure(pData[1], pData[2], channel);
507                break;
508            case 0xb0:
509                if (pData[1] == 0) {
510                    DispatchBankSelectMsb(pData[2], channel);
511                } else if (pData[1] == 32) {
512                    DispatchBankSelectLsb(pData[2], channel);
513                }
514                DispatchControlChange(pData[1], pData[2], channel);
515                break;
516            case 0xc0:
517                DispatchProgramChange(pData[1], channel);
518                break;
519            case 0xd0:
520                DispatchChannelPressure(pData[1], channel);
521                break;
522            case 0xe0:
523                DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel);
524                break;
525            }
526        }
527    
528          // now connect to the new engine channel and remember it      void MidiInputPort::DispatchRaw(uint8_t* pData, int32_t FragmentPos) {
529          try {          pData = handleRunningStatus(pData);
530              Connect(pEngineChannel, (midi_chan_t) MidiChannel);          
531              pPreviousProgramChangeEngineChannel = pEngineChannel;          uint8_t channel = pData[0] & 0x0f;
532            switch (pData[0] & 0xf0) {
533            case 0x80:
534                DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
535                break;
536            case 0x90:
537                if (pData[2]) {
538                    DispatchNoteOn(pData[1], pData[2], channel, FragmentPos);
539                } else {
540                    DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
541                }
542                break;
543            case 0xA0:
544                DispatchPolyphonicKeyPressure(pData[1], pData[2], channel, FragmentPos);
545                break;
546            case 0xb0:
547                if (pData[1] == 0) {
548                    DispatchBankSelectMsb(pData[2], channel);
549                } else if (pData[1] == 32) {
550                    DispatchBankSelectLsb(pData[2], channel);
551                }
552                DispatchControlChange(pData[1], pData[2], channel, FragmentPos);
553                break;
554            case 0xc0:
555                DispatchProgramChange(pData[1], channel);
556                break;
557            case 0xd0:
558                DispatchChannelPressure(pData[1], channel, FragmentPos);
559                break;
560            case 0xe0:
561                DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel, FragmentPos);
562                break;
563            }
564        }
565        
566        void MidiInputPort::SetNoteOnVelocityFilter(const std::vector<uint8_t>& filter) {
567            if (filter.size() != 128 && filter.size() != 0)
568                throw MidiInputException("Note on velocity filter must be either of size 128 or 0");
569            
570            // check the value range of the filter
571            if (!filter.empty())
572                for (int i = 0; i < 128; i++)
573                    if (filter[i] > 127)
574                        throw MidiInputException("Invalid note on velocity filter, values must be in range 0 .. 127");
575            
576            // apply new filter ...
577            LockGuard lock(noteOnVelocityFilterMutex);
578            // double buffer ... double work ...
579            {
580                std::vector<uint8_t>& config =
581                    noteOnVelocityFilter.GetConfigForUpdate();
582                config = filter;
583            }
584            {
585                std::vector<uint8_t>& config =
586                    noteOnVelocityFilter.SwitchConfig();
587                config = filter;
588          }          }
         catch (...) { /* NOOP */ }  
589      }      }
590    
591      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
# Line 198  namespace LinuxSampler { Line 593  namespace LinuxSampler {
593              throw MidiInputException("MIDI channel index out of bounds");              throw MidiInputException("MIDI channel index out of bounds");
594    
595          // first check if desired connection is already established          // first check if desired connection is already established
596          MidiChannelMapMutex.Lock();          {
597          MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();              LockGuard lock(MidiChannelMapMutex);
598          bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);              MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
599          MidiChannelMapMutex.Unlock();              if (midiChannelMap[MidiChannel].count(pEngineChannel)) return;
600          if (bAlreadyDone) return;          }
601    
602          // remove all other connections of that engine channel (if any)          // remove all other connections of that engine channel (if any)
603          Disconnect(pEngineChannel);          Disconnect(pEngineChannel);
604    
605          // register engine channel on the desired MIDI channel          // register engine channel on the desired MIDI channel
606          MidiChannelMapMutex.Lock();          {
607          MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);              LockGuard lock(MidiChannelMapMutex);
608          MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);              MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
609          MidiChannelMapMutex.Unlock();              MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
610            }
611    
612          // inform engine channel about this connection          // inform engine channel about this connection
613          pEngineChannel->Connect(this, MidiChannel);          pEngineChannel->Connect(this);
614            if (pEngineChannel->MidiChannel() != MidiChannel)
615                pEngineChannel->SetMidiChannel(MidiChannel);
616    
617          // mark engine channel as changed          // mark engine channel as changed
618          pEngineChannel->StatusChanged(true);          pEngineChannel->StatusChanged(true);
# Line 226  namespace LinuxSampler { Line 624  namespace LinuxSampler {
624          bool bChannelFound = false;          bool bChannelFound = false;
625    
626          // unregister engine channel from all MIDI channels          // unregister engine channel from all MIDI channels
         MidiChannelMapMutex.Lock();  
627          try {          try {
628                LockGuard lock(MidiChannelMapMutex);
629              {              {
630                  MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();                  MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
631                  for (int i = 0; i <= 16; i++) {                  for (int i = 0; i <= 16; i++) {
# Line 245  namespace LinuxSampler { Line 643  namespace LinuxSampler {
643              }              }
644          }          }
645          catch(...) { /* NOOP */ }          catch(...) { /* NOOP */ }
         MidiChannelMapMutex.Unlock();  
646    
647          // inform engine channel about the disconnection (if there is one)          // inform engine channel about the disconnection (if there is one)
648          if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();          if (bChannelFound) pEngineChannel->Disconnect(this);
649    
650          // mark engine channel as changed          // mark engine channel as changed
651          pEngineChannel->StatusChanged(true);          pEngineChannel->StatusChanged(true);
# Line 267  namespace LinuxSampler { Line 664  namespace LinuxSampler {
664          return count;          return count;
665      }      }
666    
667        void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
668            LockGuard lock(virtualMidiDevicesMutex);
669            // double buffer ... double work ...
670            {
671                std::vector<VirtualMidiDevice*>& devices =
672                    virtualMidiDevices.GetConfigForUpdate();
673                devices.push_back(pDevice);
674            }
675            {
676                std::vector<VirtualMidiDevice*>& devices =
677                    virtualMidiDevices.SwitchConfig();
678                devices.push_back(pDevice);
679            }
680        }
681    
682        void MidiInputPort::Disconnect(VirtualMidiDevice* pDevice) {
683            LockGuard lock(virtualMidiDevicesMutex);
684            // double buffer ... double work ...
685            {
686                std::vector<VirtualMidiDevice*>& devices =
687                    virtualMidiDevices.GetConfigForUpdate();
688                devices.erase(std::find(devices.begin(), devices.end(), pDevice));
689            }
690            {
691                std::vector<VirtualMidiDevice*>& devices =
692                    virtualMidiDevices.SwitchConfig();
693                devices.erase(std::find(devices.begin(), devices.end(), pDevice));
694            }
695        }
696    
697        int MidiInputPort::expectedEventSize(unsigned char byte) {
698            if (!(byte & 0x80) && runningStatusBuf[0])
699                byte = runningStatusBuf[0]; // "running status" mode
700            
701            if (byte < 0x80) return -1; // not a valid status byte
702            if (byte < 0xC0) return 3; // note on/off, note pressure, control change
703            if (byte < 0xE0) return 2; // program change, channel pressure
704            if (byte < 0xF0) return 3; // pitch wheel
705            if (byte == 0xF0) return -1; // sysex message (variable size)
706            if (byte == 0xF1) return 2; // time code per quarter frame
707            if (byte == 0xF2) return 3; // sys. common song position pointer
708            if (byte == 0xF3) return 2; // sys. common song select
709            if (byte == 0xF4) return -1; // sys. common undefined / reserved
710            if (byte == 0xF5) return -1; // sys. common undefined / reserved
711            return 1; // tune request, end of SysEx, system real-time events
712        }
713    
714  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC