/[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 3054 - (hide annotations) (download)
Thu Dec 15 12:47:45 2016 UTC (7 years, 4 months ago) by schoenebeck
File size: 34480 byte(s)
* Fixed numerous compiler warnings.
* Bumped version (2.0.0.svn32).

1 schoenebeck 221 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 3054 * Copyright (C) 2005 - 2016 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 schoenebeck 3054 size_t count = SysexListeners.GetConfigForUpdate().erase(engine);
663 persson 846 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