/[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 411 by schoenebeck, Sat Feb 26 02:01:14 2005 UTC revision 2431 by schoenebeck, Mon Mar 4 15:12:48 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"
29    #include "../../engines/EngineFactory.h"
30    #include "VirtualMidiDevice.h"
31    
32    #include <algorithm>
33    
34  namespace LinuxSampler {  namespace LinuxSampler {
35    
36  // *************** ParameterName ***************  // *************** ParameterName ***************
# Line 48  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 60  namespace LinuxSampler { Line 68  namespace LinuxSampler {
68      MidiInputPort::~MidiInputPort() {      MidiInputPort::~MidiInputPort() {
69          std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();          std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();
70          while (iter != Parameters.end()) {          while (iter != Parameters.end()) {
             Parameters.erase(iter);  
71              delete iter->second;              delete iter->second;
72              iter++;              iter++;
73          }          }
74            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);
87      }      }
88    
# Line 85  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();
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();
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();
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();
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          // 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            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            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            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
302            std::set<Engine*>::iterator engineiter = allEngines.begin();
303            std::set<Engine*>::iterator end        = allEngines.end();
304            for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
305            SysexListenersReader.Unlock();
306        }
307    
308        void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
309            if (Program > 127 || MidiChannel > 16) return;
310            if (!pDevice || !pDevice->pSampler) {
311                std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
312                          << "This is a bug, please report it!\n" << std::flush;
313                return;
314            }
315    
316            const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
317          // dispatch event for engines listening to the same MIDI channel          // dispatch event for engines listening to the same MIDI channel
318          {          {
319              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
320                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();              std::set<EngineChannel*>::iterator end        = midiChannelMap[MidiChannel].end();
321                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[MidiChannel].end();              for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
322                  for (; engineiter != end; engineiter++) {          }
323                      Engine* pEngine = (*engineiter)->GetEngine();          // dispatch event for engines listening to ALL MIDI channels
324                      if (pEngine) pEngine->SendSysex(pData, Size);          {
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        void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
333            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          // dispatch event for engines listening to ALL MIDI channels
348          {          {
349              for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {              std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
350                  std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();              std::set<EngineChannel*>::iterator end        = midiChannelMap[midi_chan_all].end();
351                  std::set<EngineChannel*>::iterator end        = MidiChannelMap[midi_chan_all].end();              // according to the MIDI specs, a bank select should not alter the patch
352                  for (; engineiter != end; engineiter++) {              for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
353                      Engine* pEngine = (*engineiter)->GetEngine();          }
354                      if (pEngine) pEngine->SendSysex(pData, Size);          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        void MidiInputPort::DispatchRaw(uint8_t* pData) {
419            pData = handleRunningStatus(pData);
420            
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        void MidiInputPort::DispatchRaw(uint8_t* pData, int32_t FragmentPos) {
454            pData = handleRunningStatus(pData);
455            
456            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            LockGuard lock(noteOnVelocityFilterMutex);
500            // double buffer ... double work ...
501            {
502                std::vector<uint8_t>& config =
503                    noteOnVelocityFilter.GetConfigForUpdate();
504                config = filter;
505            }
506            {
507                std::vector<uint8_t>& config =
508                    noteOnVelocityFilter.SwitchConfig();
509                config = filter;
510          }          }
511      }      }
512    
513      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {      void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
514          if (MidiChannel < 0 || MidiChannel > 16)          if (MidiChannel < 0 || MidiChannel > 16)
515              throw MidiInputException("MIDI channel index out of bounds");              throw MidiInputException("MIDI channel index out of bounds");
516    
517            // first check if desired connection is already established
518            {
519                LockGuard lock(MidiChannelMapMutex);
520                MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
521                if (midiChannelMap[MidiChannel].count(pEngineChannel)) return;
522            }
523    
524            // remove all other connections of that engine channel (if any)
525          Disconnect(pEngineChannel);          Disconnect(pEngineChannel);
526          MidiChannelMap[MidiChannel].insert(pEngineChannel);  
527            // register engine channel on the desired MIDI channel
528            {
529                LockGuard lock(MidiChannelMapMutex);
530                MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
531                MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
532            }
533    
534            // inform engine channel about this connection
535            pEngineChannel->Connect(this, MidiChannel);
536    
537            // mark engine channel as changed
538            pEngineChannel->StatusChanged(true);
539      }      }
540    
541      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {      void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
542          try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngineChannel); }          if (!pEngineChannel) return;
543    
544            bool bChannelFound = false;
545    
546            // unregister engine channel from all MIDI channels
547            try {
548                LockGuard lock(MidiChannelMapMutex);
549                {
550                    MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
551                    for (int i = 0; i <= 16; i++) {
552                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
553                        midiChannelMap[i].erase(pEngineChannel);
554                    }
555                }
556                // do the same update again, after switching to the other config
557                {
558                    MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
559                    for (int i = 0; i <= 16; i++) {
560                        bChannelFound |= midiChannelMap[i].count(pEngineChannel);
561                        midiChannelMap[i].erase(pEngineChannel);
562                    }
563                }
564            }
565          catch(...) { /* NOOP */ }          catch(...) { /* NOOP */ }
566    
567            // inform engine channel about the disconnection (if there is one)
568            if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
569    
570            // mark engine channel as changed
571            pEngineChannel->StatusChanged(true);
572        }
573    
574        SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
575    
576        void MidiInputPort::AddSysexListener(Engine* engine) {
577            std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
578            if (p.second) SysexListeners.SwitchConfig().insert(engine);
579        }
580    
581        bool MidiInputPort::RemoveSysexListener(Engine* engine) {
582            int count = SysexListeners.GetConfigForUpdate().erase(engine);
583            if (count) SysexListeners.SwitchConfig().erase(engine);
584            return count;
585        }
586    
587        void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
588            LockGuard lock(virtualMidiDevicesMutex);
589            // double buffer ... double work ...
590            {
591                std::vector<VirtualMidiDevice*>& devices =
592                    virtualMidiDevices.GetConfigForUpdate();
593                devices.push_back(pDevice);
594            }
595            {
596                std::vector<VirtualMidiDevice*>& devices =
597                    virtualMidiDevices.SwitchConfig();
598                devices.push_back(pDevice);
599            }
600        }
601    
602        void MidiInputPort::Disconnect(VirtualMidiDevice* pDevice) {
603            LockGuard lock(virtualMidiDevicesMutex);
604            // double buffer ... double work ...
605            {
606                std::vector<VirtualMidiDevice*>& devices =
607                    virtualMidiDevices.GetConfigForUpdate();
608                devices.erase(std::find(devices.begin(), devices.end(), pDevice));
609            }
610            {
611                std::vector<VirtualMidiDevice*>& devices =
612                    virtualMidiDevices.SwitchConfig();
613                devices.erase(std::find(devices.begin(), devices.end(), pDevice));
614            }
615        }
616    
617        int MidiInputPort::expectedEventSize(unsigned char byte) {
618            if (!(byte & 0x80) && runningStatusBuf[0])
619                byte = runningStatusBuf[0]; // "running status" mode
620            
621            if (byte < 0x80) return -1; // not a valid status byte
622            if (byte < 0xC0) return 3; // note on/off, note pressure, control change
623            if (byte < 0xE0) return 2; // program change, channel pressure
624            if (byte < 0xF0) return 3; // pitch wheel
625            if (byte == 0xF0) return -1; // sysex message (variable size)
626            if (byte == 0xF1) return 2; // time code per quarter frame
627            if (byte == 0xF2) return 3; // sys. common song position pointer
628            if (byte == 0xF3) return 2; // sys. common song select
629            if (byte == 0xF4) return -1; // sys. common undefined / reserved
630            if (byte == 0xF5) return -1; // sys. common undefined / reserved
631            return 1; // tune request, end of SysEx, system real-time events
632      }      }
633    
634  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.411  
changed lines
  Added in v.2431

  ViewVC Help
Powered by ViewVC