/[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 840 by persson, Sun Feb 26 13:00:08 2006 UTC revision 2426 by schoenebeck, Fri Mar 1 23:00:17 2013 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                              *   *   Copyright (C) 2005 - 2013 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 51  namespace LinuxSampler { Line 56  namespace LinuxSampler {
56          return std::vector<String>();          return std::vector<String>();
57      }      }
58    
59      void MidiInputPort::ParameterName::OnSetValue(String s) throw (LinuxSamplerException) {      void MidiInputPort::ParameterName::OnSetValue(String s) throw (Exception) {
60          return; /* FIXME: Nothing to do here */          return; /* FIXME: Nothing to do here */
61      }      }
62    
# Line 69  namespace LinuxSampler { Line 74  namespace LinuxSampler {
74          Parameters.clear();          Parameters.clear();
75      }      }
76    
77      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber) {      MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
78            : MidiChannelMapReader(MidiChannelMap),
79              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 89  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          const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();          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();
110            // dispatch event for engines listening to the same MIDI channel
111            {
112                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
113                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
114                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
115            }
116            // dispatch event for engines listening to ALL MIDI channels
117            {
118                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
119                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
120                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
121            }
122            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          // dispatch event for engines listening to the same MIDI channel
142          {          {
143              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
144              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
145              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
146          }          }
147          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
148          {          {
149              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
150              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
151              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
152          }          }
153          MidiChannelMap.Unlock();          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          const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();          if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
165            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
166            // dispatch event for engines listening to the same MIDI channel
167            {
168                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
169                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
170                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
171            }
172            // dispatch event for engines listening to ALL MIDI channels
173            {
174                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
175                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
176                for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
177            }
178            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          // dispatch event for engines listening to the same MIDI channel
192          {          {
193              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
194              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
195              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
196          }          }
197          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
198          {          {
199              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
200              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
201              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);              for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
202          }          }
203          MidiChannelMap.Unlock();          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          const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();          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          // dispatch event for engines listening to the same MIDI channel
217          {          {
218              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
219              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
220              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
221          }          }
222          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
223          {          {
224              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
225              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
226              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);              for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
227          }          }
228          MidiChannelMap.Unlock();          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::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {      void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
250          const MidiChannelMap_t& midiChannelMap = MidiChannelMap.Lock();          if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
251            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
252          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
253          {          {
254              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
255              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
256              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
257          }          }
258          // dispatch event for engines listening to ALL MIDI channels          // dispatch event for engines listening to ALL MIDI channels
259          {          {
260              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
261              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
262              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);              for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
263          }          }
264          MidiChannelMap.Unlock();          MidiChannelMapReader.Unlock();
265            
266            // dispatch event to all low priority MIDI listeners
267            const std::vector<VirtualMidiDevice*>& listeners =
268                virtualMidiDevicesReader.Lock();
269            for (int i = 0; i < listeners.size(); ++i)
270                listeners[i]->SendCCToDevice(Controller, Value);
271            virtualMidiDevicesReader.Unlock();
272        }
273    
274        void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
275            if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
276            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
277            // dispatch event for engines listening to the same MIDI channel
278            {
279                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
280                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
281                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
282            }
283            // dispatch event for engines listening to ALL MIDI channels
284            {
285                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
286                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
287                for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
288            }
289            MidiChannelMapReader.Unlock();
290            
291            // dispatch event to all low priority MIDI listeners
292            const std::vector<VirtualMidiDevice*>& listeners =
293                virtualMidiDevicesReader.Lock();
294            for (int i = 0; i < listeners.size(); ++i)
295                listeners[i]->SendCCToDevice(Controller, Value);
296            virtualMidiDevicesReader.Unlock();
297      }      }
298    
299      void MidiInputPort::DispatchSysex(void* pData, uint Size) {      void MidiInputPort::DispatchSysex(void* pData, uint Size) {
300            const std::set<Engine*> allEngines = SysexListenersReader.Lock();
301          // dispatch event to all engine instances          // dispatch event to all engine instances
302          std::set<Engine*>::iterator engineiter = EngineFactory::EngineInstances().begin();          std::set<Engine*>::iterator engineiter = allEngines.begin();
303          std::set<Engine*>::iterator end        = EngineFactory::EngineInstances().end();          std::set<Engine*>::iterator end        = allEngines.end();
304          for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);          for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
305            SysexListenersReader.Unlock();
306      }      }
307    
308      void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {      void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
309            if (Program > 127 || MidiChannel > 16) return;
310          if (!pDevice || !pDevice->pSampler) {          if (!pDevice || !pDevice->pSampler) {
311              std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."              std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
312                        << "This is a bug, please report it!\n" << std::flush;                        << "This is a bug, please report it!\n" << std::flush;
313              return;              return;
314          }          }
315    
316          Sampler*        pSampler        = (Sampler*) pDevice->pSampler;          const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
317          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(Program);          // dispatch event for engines listening to the same MIDI channel
318          if (!pSamplerChannel) return;          {
319                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
320                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
321                for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
322            }
323            // dispatch event for engines listening to ALL MIDI channels
324            {
325                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
326                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
327                for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
328            }
329            MidiChannelMapReader.Unlock();
330        }
331    
332          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();      void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
333          if (!pEngineChannel) return;          if (BankMSB > 127 || MidiChannel > 16) return;
334            if (!pDevice || !pDevice->pSampler) {
335                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select MSB."
336                          << "This is a bug, please report it!\n" << std::flush;
337                return;
338            }
339            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
340            // dispatch event for engines listening to the same MIDI channel
341            {
342                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
343                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
344                // according to the MIDI specs, a bank select should not alter the patch
345                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
346            }
347            // dispatch event for engines listening to ALL MIDI channels
348            {
349                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
350                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
351                // according to the MIDI specs, a bank select should not alter the patch
352                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
353            }
354            MidiChannelMapReader.Unlock();
355        }
356    
357        void MidiInputPort::DispatchBankSelectLsb(uint8_t BankLSB, uint MidiChannel) {
358            if (BankLSB > 127 || MidiChannel > 16) return;
359            if (!pDevice || !pDevice->pSampler) {
360                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select LSB."
361                          << "This is a bug, please report it!\n" << std::flush;
362                return;
363            }
364            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
365            // dispatch event for engines listening to the same MIDI channel
366            {
367                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
368                std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
369                // according to the MIDI specs, a bank select should not alter the patch
370                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
371            }
372            // dispatch event for engines listening to ALL MIDI channels
373            {
374                std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
375                std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
376                // according to the MIDI specs, a bank select should not alter the patch
377                for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
378            }
379            MidiChannelMapReader.Unlock();
380        }
381        
382        /**
383         * Handles the so called MIDI "running status" mode, which allows devices
384         * to reduce bandwidth (data reduction).
385         *
386         * If the passed in MIDI data is regular MIDI data, this method will simply
387         * return the original data pointer and just stores the status byte for
388         * potential "running status" event eventually coming next.
389         *
390         * If the passed in MIDI data however seems to be in "running status" mode,
391         * this method will return another buffer, which allows the MIDI parser
392         * to handle the MIDI data as usually with "normal" MIDI data.
393         */
394        uint8_t* MidiInputPort::handleRunningStatus(uint8_t* pData) {
395            if ((pData[0] & 0x80) || !runningStatusBuf[0]) {
396                // store status byte for eventual "running status" in next event
397                if (pData[0] & 0x80) {
398                    if (pData[0] < 0xf0) {
399                        // "running status" is only allowed for channel messages
400                        runningStatusBuf[0] = pData[0];
401                    } else if (pData[0] < 0xf8) {
402                        // "system common" messages (0xf0..0xf7) shall reset any running
403                        // status, however "realtime" messages (0xf8..0xff) shall be
404                        // ignored here
405                        runningStatusBuf[0] = 0;
406                    }
407                }
408                // it's either a regular status byte, or some invalid "running status"
409                return pData;
410            } else { // "running status" mode ...
411                const uint8_t type = runningStatusBuf[0] & 0xf0;
412                const int size = (type == 0xc0 || type == 0xd0) ? 1 : 2; // only program change & channel pressure have 1 data bytes
413                memcpy(&runningStatusBuf[1], pData, size);
414                return runningStatusBuf;
415            }
416        }
417    
418          // disconnect from the engine channel which was connected by the last PC event      void MidiInputPort::DispatchRaw(uint8_t* pData) {
419          if (pPreviousProgramChangeEngineChannel)          pData = handleRunningStatus(pData);
420              Disconnect(pPreviousProgramChangeEngineChannel);          
421            uint8_t channel = pData[0] & 0x0f;
422            switch (pData[0] & 0xf0) {
423            case 0x80:
424                DispatchNoteOff(pData[1], pData[2], channel);
425                break;
426            case 0x90:
427                if (pData[2]) {
428                    DispatchNoteOn(pData[1], pData[2], channel);
429                } else {
430                    DispatchNoteOff(pData[1], pData[2], channel);
431                }
432                break;
433            case 0xb0:
434                if (pData[1] == 0) {
435                    DispatchBankSelectMsb(pData[2], channel);
436                } else if (pData[1] == 32) {
437                    DispatchBankSelectLsb(pData[2], channel);
438                }
439                DispatchControlChange(pData[1], pData[2], channel);
440                break;
441            case 0xc0:
442                DispatchProgramChange(pData[1], channel);
443                break;
444            case 0xd0:
445                DispatchControlChange(128, pData[1], channel);
446                break;
447            case 0xe0:
448                DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel);
449                break;
450            }
451        }
452    
453          // now connect to the new engine channel and remember it      void MidiInputPort::DispatchRaw(uint8_t* pData, int32_t FragmentPos) {
454          try {          pData = handleRunningStatus(pData);
455              Connect(pEngineChannel, (midi_chan_t) MidiChannel);          
456              pPreviousProgramChangeEngineChannel = pEngineChannel;          uint8_t channel = pData[0] & 0x0f;
457            switch (pData[0] & 0xf0) {
458            case 0x80:
459                DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
460                break;
461            case 0x90:
462                if (pData[2]) {
463                    DispatchNoteOn(pData[1], pData[2], channel, FragmentPos);
464                } else {
465                    DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
466                }
467                break;
468            case 0xb0:
469                if (pData[1] == 0) {
470                    DispatchBankSelectMsb(pData[2], channel);
471                } else if (pData[1] == 32) {
472                    DispatchBankSelectLsb(pData[2], channel);
473                }
474                DispatchControlChange(pData[1], pData[2], channel, FragmentPos);
475                break;
476            case 0xc0:
477                DispatchProgramChange(pData[1], channel);
478                break;
479            case 0xd0:
480                DispatchControlChange(128, pData[1], channel, FragmentPos);
481                break;
482            case 0xe0:
483                DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel, FragmentPos);
484                break;
485            }
486        }
487        
488        void MidiInputPort::SetNoteOnVelocityFilter(const std::vector<uint8_t>& filter) {
489            if (filter.size() != 128 && filter.size() != 0)
490                throw MidiInputException("Note on velocity filter must be either of size 128 or 0");
491            
492            // check the value range of the filter
493            if (!filter.empty())
494                for (int i = 0; i < 128; i++)
495                    if (filter[i] > 127)
496                        throw MidiInputException("Invalid note on velocity filter, values must be in range 0 .. 127");
497            
498            // apply new filter ...
499            noteOnVelocityFilterMutex.Lock();
500            // double buffer ... double work ...
501            {
502                std::vector<uint8_t>& config =
503                    noteOnVelocityFilter.GetConfigForUpdate();
504                config = filter;
505          }          }
506          catch (...) { /* NOOP */ }          {
507                std::vector<uint8_t>& config =
508                    noteOnVelocityFilter.SwitchConfig();
509                config = filter;
510            }
511            noteOnVelocityFilterMutex.Unlock();
512      }      }
513    
514      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
# Line 250  namespace LinuxSampler { Line 572  namespace LinuxSampler {
572          pEngineChannel->StatusChanged(true);          pEngineChannel->StatusChanged(true);
573      }      }
574    
575        SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
576    
577        void MidiInputPort::AddSysexListener(Engine* engine) {
578            std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
579            if (p.second) SysexListeners.SwitchConfig().insert(engine);
580        }
581    
582        bool MidiInputPort::RemoveSysexListener(Engine* engine) {
583            int count = SysexListeners.GetConfigForUpdate().erase(engine);
584            if (count) SysexListeners.SwitchConfig().erase(engine);
585            return count;
586        }
587    
588        void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
589            virtualMidiDevicesMutex.Lock();
590            // double buffer ... double work ...
591            {
592                std::vector<VirtualMidiDevice*>& devices =
593                    virtualMidiDevices.GetConfigForUpdate();
594                devices.push_back(pDevice);
595            }
596            {
597                std::vector<VirtualMidiDevice*>& devices =
598                    virtualMidiDevices.SwitchConfig();
599                devices.push_back(pDevice);
600            }
601            virtualMidiDevicesMutex.Unlock();
602        }
603    
604        void MidiInputPort::Disconnect(VirtualMidiDevice* pDevice) {
605            virtualMidiDevicesMutex.Lock();
606            // double buffer ... double work ...
607            {
608                std::vector<VirtualMidiDevice*>& devices =
609                    virtualMidiDevices.GetConfigForUpdate();
610                devices.erase(std::find(devices.begin(), devices.end(), pDevice));
611            }
612            {
613                std::vector<VirtualMidiDevice*>& devices =
614                    virtualMidiDevices.SwitchConfig();
615                devices.erase(std::find(devices.begin(), devices.end(), pDevice));
616            }
617            virtualMidiDevicesMutex.Unlock();
618        }
619    
620  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.840  
changed lines
  Added in v.2426

  ViewVC Help
Powered by ViewVC