/[svn]/linuxsampler/trunk/src/drivers/midi/MidiInputPort.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/drivers/midi/MidiInputPort.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2559 - (hide annotations) (download)
Sun May 18 17:38:25 2014 UTC (10 years ago) by schoenebeck
File size: 34477 byte(s)
* Aftertouch: extended API to explicitly handle channel pressure and
  polyphonic key pressure events (so far polyphonic pressure was not
  supported at all, and channel pressure was rerouted as CC128 but not
  used so far).
* Gig Engine: Fixed support for 'aftertouch' attenuation controller.
* Bumped version (1.0.0.svn39).

1 schoenebeck 221 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 2500 * Copyright (C) 2005 - 2014 Christian Schoenebeck *
7 schoenebeck 221 * *
8     * 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 *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13     * This program is distributed in the hope that it will be useful, *
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19     * along with this program; if not, write to the Free Software *
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24     #include "MidiInputPort.h"
25    
26 schoenebeck 1424 #include "../../common/global_private.h"
27 schoenebeck 947 #include "MidiInstrumentMapper.h"
28 schoenebeck 551 #include "../../Sampler.h"
29 schoenebeck 775 #include "../../engines/EngineFactory.h"
30 schoenebeck 1695 #include "VirtualMidiDevice.h"
31 schoenebeck 551
32 schoenebeck 1695 #include <algorithm>
33    
34 schoenebeck 221 namespace LinuxSampler {
35    
36     // *************** ParameterName ***************
37     // *
38    
39     MidiInputPort::ParameterName::ParameterName(MidiInputPort* pPort) : DeviceRuntimeParameterString("Port " + ToString(pPort->GetPortNumber())) {
40     this->pPort = pPort;
41     }
42    
43     MidiInputPort::ParameterName::ParameterName(MidiInputPort* pPort, String val) : DeviceRuntimeParameterString(val) {
44     this->pPort = pPort;
45     }
46    
47     String MidiInputPort::ParameterName::Description() {
48     return "Name for this port";
49     }
50    
51     bool MidiInputPort::ParameterName::Fix() {
52     return false;
53     }
54    
55     std::vector<String> MidiInputPort::ParameterName::PossibilitiesAsString() {
56     return std::vector<String>();
57     }
58    
59 schoenebeck 880 void MidiInputPort::ParameterName::OnSetValue(String s) throw (Exception) {
60 schoenebeck 221 return; /* FIXME: Nothing to do here */
61     }
62    
63    
64    
65     // *************** MidiInputPort ***************
66     // *
67    
68     MidiInputPort::~MidiInputPort() {
69     std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();
70     while (iter != Parameters.end()) {
71     delete iter->second;
72     iter++;
73     }
74 persson 836 Parameters.clear();
75 schoenebeck 221 }
76    
77 persson 846 MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
78     : MidiChannelMapReader(MidiChannelMap),
79 schoenebeck 1695 SysexListenersReader(SysexListeners),
80 schoenebeck 2380 virtualMidiDevicesReader(virtualMidiDevices),
81     noteOnVelocityFilterReader(noteOnVelocityFilter)
82     {
83 schoenebeck 221 this->pDevice = pDevice;
84     this->portNumber = portNumber;
85 schoenebeck 2426 runningStatusBuf[0] = 0;
86 schoenebeck 221 Parameters["NAME"] = new ParameterName(this);
87     }
88    
89     MidiInputDevice* MidiInputPort::GetDevice() {
90     return pDevice;
91     }
92    
93     uint MidiInputPort::GetPortNumber() {
94     return portNumber;
95     }
96    
97     std::map<String,DeviceRuntimeParameter*> MidiInputPort::PortParameters() {
98     return Parameters;
99     }
100    
101     void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
102 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
103 schoenebeck 2380
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 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
110 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
111     {
112 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
113     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
114 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
115 schoenebeck 274 }
116     // dispatch event for engines listening to ALL MIDI channels
117     {
118 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
119     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
120 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
121 schoenebeck 274 }
122 persson 846 MidiChannelMapReader.Unlock();
123 schoenebeck 1695
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 schoenebeck 221 }
131    
132 schoenebeck 906 void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
133 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
134 schoenebeck 2380
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 schoenebeck 906 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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
146 schoenebeck 906 }
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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
152 schoenebeck 906 }
153     MidiChannelMapReader.Unlock();
154 schoenebeck 1695
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 schoenebeck 906 }
162    
163 schoenebeck 221 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
164 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
165 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
166 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
167     {
168 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
169     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
170 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
171 schoenebeck 274 }
172     // dispatch event for engines listening to ALL MIDI channels
173     {
174 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
175     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
176 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
177 schoenebeck 274 }
178 persson 846 MidiChannelMapReader.Unlock();
179 schoenebeck 1695
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 schoenebeck 221 }
187    
188 schoenebeck 906 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
189 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
190 schoenebeck 906 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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
196 schoenebeck 906 }
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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
202 schoenebeck 906 }
203     MidiChannelMapReader.Unlock();
204 schoenebeck 1695
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 schoenebeck 906 }
212    
213 schoenebeck 221 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
214 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
215 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
216 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
217     {
218 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
219     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
220 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
221 schoenebeck 274 }
222     // dispatch event for engines listening to ALL MIDI channels
223     {
224 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
225     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
226 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
227 schoenebeck 274 }
228 persson 846 MidiChannelMapReader.Unlock();
229 schoenebeck 221 }
230    
231 schoenebeck 906 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
232 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
233 schoenebeck 906 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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
239 schoenebeck 906 }
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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
245 schoenebeck 906 }
246     MidiChannelMapReader.Unlock();
247     }
248    
249 schoenebeck 2559 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();
306     // dispatch event for engines listening to the same MIDI channel
307     {
308     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
309     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
310     for (; engineiter != end; engineiter++) (*engineiter)->SendPolyphonicKeyPressure(Key, Value, MidiChannel, FragmentPos);
311     }
312     // dispatch event for engines listening to ALL MIDI channels
313     {
314     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
315     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
316     for (; engineiter != end; engineiter++) (*engineiter)->SendPolyphonicKeyPressure(Key, Value, MidiChannel, FragmentPos);
317     }
318     MidiChannelMapReader.Unlock();
319     }
320    
321 schoenebeck 221 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
322 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
323 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
324 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
325     {
326 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
327     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
328 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
329 schoenebeck 274 }
330     // dispatch event for engines listening to ALL MIDI channels
331     {
332 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
333     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
334 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
335 schoenebeck 274 }
336 persson 846 MidiChannelMapReader.Unlock();
337 schoenebeck 2025
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 schoenebeck 221 }
345    
346 schoenebeck 906 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
347 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
348 schoenebeck 906 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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
354 schoenebeck 906 }
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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
360 schoenebeck 906 }
361     MidiChannelMapReader.Unlock();
362 schoenebeck 2025
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 schoenebeck 906 }
370    
371 schoenebeck 244 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
372 persson 846 const std::set<Engine*> allEngines = SysexListenersReader.Lock();
373 schoenebeck 775 // dispatch event to all engine instances
374 persson 846 std::set<Engine*>::iterator engineiter = allEngines.begin();
375     std::set<Engine*>::iterator end = allEngines.end();
376 schoenebeck 1751 for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
377 persson 846 SysexListenersReader.Unlock();
378 schoenebeck 244 }
379    
380 schoenebeck 670 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
381 persson 922 if (Program > 127 || MidiChannel > 16) return;
382 schoenebeck 551 if (!pDevice || !pDevice->pSampler) {
383     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
384     << "This is a bug, please report it!\n" << std::flush;
385     return;
386     }
387 schoenebeck 973
388 schoenebeck 947 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
389     // dispatch event for engines listening to the same MIDI channel
390     {
391     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
392     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
393 persson 1924 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
394 schoenebeck 947 }
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 persson 1924 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
400 schoenebeck 947 }
401     MidiChannelMapReader.Unlock();
402     }
403 schoenebeck 551
404 schoenebeck 947 void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
405     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 schoenebeck 551
429 schoenebeck 947 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 schoenebeck 551 }
436 schoenebeck 947 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 schoenebeck 551 }
453 schoenebeck 2426
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 schoenebeck 551
490 persson 1887 void MidiInputPort::DispatchRaw(uint8_t* pData) {
491 schoenebeck 2426 pData = handleRunningStatus(pData);
492    
493 persson 1887 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 schoenebeck 2559 case 0xA0:
506     DispatchPolyphonicKeyPressure(pData[1], pData[2], channel);
507     break;
508 persson 1887 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 schoenebeck 2559 DispatchChannelPressure(pData[1], channel);
521 persson 1887 break;
522     case 0xe0:
523     DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel);
524     break;
525     }
526     }
527    
528 persson 1765 void MidiInputPort::DispatchRaw(uint8_t* pData, int32_t FragmentPos) {
529 schoenebeck 2426 pData = handleRunningStatus(pData);
530    
531 persson 1765 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 schoenebeck 2559 case 0xA0:
544     DispatchPolyphonicKeyPressure(pData[1], pData[2], channel, FragmentPos);
545     break;
546 persson 1765 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 schoenebeck 2559 DispatchChannelPressure(pData[1], channel, FragmentPos);
559 persson 1765 break;
560     case 0xe0:
561 persson 1887 DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel, FragmentPos);
562 persson 1765 break;
563     }
564     }
565 schoenebeck 2380
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 persson 2427 LockGuard lock(noteOnVelocityFilterMutex);
578 schoenebeck 2380 // 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     }
589     }
590 persson 1765
591 schoenebeck 411 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
592 schoenebeck 221 if (MidiChannel < 0 || MidiChannel > 16)
593     throw MidiInputException("MIDI channel index out of bounds");
594 schoenebeck 670
595 persson 840 // first check if desired connection is already established
596 persson 2427 {
597     LockGuard lock(MidiChannelMapMutex);
598     MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
599     if (midiChannelMap[MidiChannel].count(pEngineChannel)) return;
600     }
601 schoenebeck 675
602     // remove all other connections of that engine channel (if any)
603 schoenebeck 411 Disconnect(pEngineChannel);
604 schoenebeck 670
605 schoenebeck 675 // register engine channel on the desired MIDI channel
606 persson 2427 {
607     LockGuard lock(MidiChannelMapMutex);
608     MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
609     MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
610     }
611 schoenebeck 670
612 schoenebeck 675 // inform engine channel about this connection
613 schoenebeck 2500 pEngineChannel->Connect(this);
614     if (pEngineChannel->MidiChannel() != MidiChannel)
615     pEngineChannel->SetMidiChannel(MidiChannel);
616 schoenebeck 675
617 schoenebeck 670 // mark engine channel as changed
618     pEngineChannel->StatusChanged(true);
619 schoenebeck 221 }
620    
621 schoenebeck 411 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
622 schoenebeck 675 if (!pEngineChannel) return;
623    
624     bool bChannelFound = false;
625    
626     // unregister engine channel from all MIDI channels
627     try {
628 persson 2427 LockGuard lock(MidiChannelMapMutex);
629 persson 840 {
630     MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
631     for (int i = 0; i <= 16; i++) {
632     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
633     midiChannelMap[i].erase(pEngineChannel);
634     }
635 schoenebeck 675 }
636 persson 840 // do the same update again, after switching to the other config
637     {
638     MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
639     for (int i = 0; i <= 16; i++) {
640     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
641     midiChannelMap[i].erase(pEngineChannel);
642     }
643     }
644 schoenebeck 675 }
645 schoenebeck 221 catch(...) { /* NOOP */ }
646 schoenebeck 675
647     // inform engine channel about the disconnection (if there is one)
648 schoenebeck 2500 if (bChannelFound) pEngineChannel->Disconnect(this);
649 schoenebeck 675
650 schoenebeck 670 // mark engine channel as changed
651     pEngineChannel->StatusChanged(true);
652 schoenebeck 221 }
653    
654 persson 846 SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
655    
656     void MidiInputPort::AddSysexListener(Engine* engine) {
657     std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
658     if (p.second) SysexListeners.SwitchConfig().insert(engine);
659     }
660    
661     bool MidiInputPort::RemoveSysexListener(Engine* engine) {
662     int count = SysexListeners.GetConfigForUpdate().erase(engine);
663     if (count) SysexListeners.SwitchConfig().erase(engine);
664     return count;
665     }
666    
667 schoenebeck 1695 void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
668 persson 2427 LockGuard lock(virtualMidiDevicesMutex);
669 schoenebeck 1695 // 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 persson 2427 LockGuard lock(virtualMidiDevicesMutex);
684 schoenebeck 1695 // 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 schoenebeck 2431 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 schoenebeck 221 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC