/[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 2380 - (hide annotations) (download)
Wed Nov 21 21:52:15 2012 UTC (11 years, 5 months ago) by schoenebeck
File size: 27060 byte(s)
* Added support for MIDI note on velocity filter
* Bumped version to 1.0.0.svn20

1 schoenebeck 221 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 persson 2317 * Copyright (C) 2005 - 2012 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     Parameters["NAME"] = new ParameterName(this);
86     }
87    
88     MidiInputDevice* MidiInputPort::GetDevice() {
89     return pDevice;
90     }
91    
92     uint MidiInputPort::GetPortNumber() {
93     return portNumber;
94     }
95    
96     std::map<String,DeviceRuntimeParameter*> MidiInputPort::PortParameters() {
97     return Parameters;
98     }
99    
100     void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
101 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
102 schoenebeck 2380
103     // apply velocity filter (if any)
104     const std::vector<uint8_t>& velocityFilter = noteOnVelocityFilterReader.Lock();
105     if (!velocityFilter.empty()) Velocity = velocityFilter[Velocity];
106     noteOnVelocityFilterReader.Unlock();
107    
108 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
109 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
110     {
111 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
112     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
113 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
114 schoenebeck 274 }
115     // dispatch event for engines listening to ALL MIDI channels
116     {
117 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
118     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
119 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
120 schoenebeck 274 }
121 persson 846 MidiChannelMapReader.Unlock();
122 schoenebeck 1695
123     // dispatch event to all low priority MIDI listeners
124     const std::vector<VirtualMidiDevice*>& listeners =
125     virtualMidiDevicesReader.Lock();
126     for (int i = 0; i < listeners.size(); ++i)
127     listeners[i]->SendNoteOnToDevice(Key, Velocity);
128     virtualMidiDevicesReader.Unlock();
129 schoenebeck 221 }
130    
131 schoenebeck 906 void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
132 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
133 schoenebeck 2380
134     // apply velocity filter (if any)
135     const std::vector<uint8_t>& velocityFilter = noteOnVelocityFilterReader.Lock();
136     if (!velocityFilter.empty()) Velocity = velocityFilter[Velocity];
137     noteOnVelocityFilterReader.Unlock();
138    
139 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
140     // dispatch event for engines listening to the same MIDI channel
141     {
142     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
143     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
144 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
145 schoenebeck 906 }
146     // dispatch event for engines listening to ALL MIDI channels
147     {
148     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
149     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
150 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
151 schoenebeck 906 }
152     MidiChannelMapReader.Unlock();
153 schoenebeck 1695
154     // dispatch event to all low priority MIDI listeners
155     const std::vector<VirtualMidiDevice*>& listeners =
156     virtualMidiDevicesReader.Lock();
157     for (int i = 0; i < listeners.size(); ++i)
158     listeners[i]->SendNoteOnToDevice(Key, Velocity);
159     virtualMidiDevicesReader.Unlock();
160 schoenebeck 906 }
161    
162 schoenebeck 221 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
163 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
164 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
165 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
166     {
167 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
168     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
169 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
170 schoenebeck 274 }
171     // dispatch event for engines listening to ALL MIDI channels
172     {
173 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
174     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
175 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
176 schoenebeck 274 }
177 persson 846 MidiChannelMapReader.Unlock();
178 schoenebeck 1695
179     // dispatch event to all low priority MIDI listeners
180     const std::vector<VirtualMidiDevice*>& listeners =
181     virtualMidiDevicesReader.Lock();
182     for (int i = 0; i < listeners.size(); ++i)
183     listeners[i]->SendNoteOffToDevice(Key, Velocity);
184     virtualMidiDevicesReader.Unlock();
185 schoenebeck 221 }
186    
187 schoenebeck 906 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
188 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
189 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
190     // dispatch event for engines listening to the same MIDI channel
191     {
192     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
193     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
194 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
195 schoenebeck 906 }
196     // dispatch event for engines listening to ALL MIDI channels
197     {
198     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
199     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
200 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
201 schoenebeck 906 }
202     MidiChannelMapReader.Unlock();
203 schoenebeck 1695
204     // dispatch event to all low priority MIDI listeners
205     const std::vector<VirtualMidiDevice*>& listeners =
206     virtualMidiDevicesReader.Lock();
207     for (int i = 0; i < listeners.size(); ++i)
208     listeners[i]->SendNoteOffToDevice(Key, Velocity);
209     virtualMidiDevicesReader.Unlock();
210 schoenebeck 906 }
211    
212 schoenebeck 221 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
213 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
214 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
215 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
216     {
217 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
218     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
219 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
220 schoenebeck 274 }
221     // dispatch event for engines listening to ALL MIDI channels
222     {
223 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
224     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
225 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
226 schoenebeck 274 }
227 persson 846 MidiChannelMapReader.Unlock();
228 schoenebeck 221 }
229    
230 schoenebeck 906 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
231 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
232 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
233     // dispatch event for engines listening to the same MIDI channel
234     {
235     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
236     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
237 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
238 schoenebeck 906 }
239     // dispatch event for engines listening to ALL MIDI channels
240     {
241     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
242     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
243 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
244 schoenebeck 906 }
245     MidiChannelMapReader.Unlock();
246     }
247    
248 schoenebeck 221 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
249 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
250 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
251 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
252     {
253 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
254     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
255 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
256 schoenebeck 274 }
257     // dispatch event for engines listening to ALL MIDI channels
258     {
259 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
260     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
261 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
262 schoenebeck 274 }
263 persson 846 MidiChannelMapReader.Unlock();
264 schoenebeck 2025
265     // dispatch event to all low priority MIDI listeners
266     const std::vector<VirtualMidiDevice*>& listeners =
267     virtualMidiDevicesReader.Lock();
268     for (int i = 0; i < listeners.size(); ++i)
269     listeners[i]->SendCCToDevice(Controller, Value);
270     virtualMidiDevicesReader.Unlock();
271 schoenebeck 221 }
272    
273 schoenebeck 906 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
274 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
275 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
276     // dispatch event for engines listening to the same MIDI channel
277     {
278     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
279     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
280 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
281 schoenebeck 906 }
282     // dispatch event for engines listening to ALL MIDI channels
283     {
284     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
285     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
286 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
287 schoenebeck 906 }
288     MidiChannelMapReader.Unlock();
289 schoenebeck 2025
290     // dispatch event to all low priority MIDI listeners
291     const std::vector<VirtualMidiDevice*>& listeners =
292     virtualMidiDevicesReader.Lock();
293     for (int i = 0; i < listeners.size(); ++i)
294     listeners[i]->SendCCToDevice(Controller, Value);
295     virtualMidiDevicesReader.Unlock();
296 schoenebeck 906 }
297    
298 schoenebeck 244 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
299 persson 846 const std::set<Engine*> allEngines = SysexListenersReader.Lock();
300 schoenebeck 775 // dispatch event to all engine instances
301 persson 846 std::set<Engine*>::iterator engineiter = allEngines.begin();
302     std::set<Engine*>::iterator end = allEngines.end();
303 schoenebeck 1751 for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
304 persson 846 SysexListenersReader.Unlock();
305 schoenebeck 244 }
306    
307 schoenebeck 670 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
308 persson 922 if (Program > 127 || MidiChannel > 16) return;
309 schoenebeck 551 if (!pDevice || !pDevice->pSampler) {
310     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
311     << "This is a bug, please report it!\n" << std::flush;
312     return;
313     }
314 schoenebeck 973
315 schoenebeck 947 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
316     // dispatch event for engines listening to the same MIDI channel
317     {
318     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
319     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
320 persson 1924 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
321 schoenebeck 947 }
322     // dispatch event for engines listening to ALL MIDI channels
323     {
324     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
325     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
326 persson 1924 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
327 schoenebeck 947 }
328     MidiChannelMapReader.Unlock();
329     }
330 schoenebeck 551
331 schoenebeck 947 void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
332     if (BankMSB > 127 || MidiChannel > 16) return;
333     if (!pDevice || !pDevice->pSampler) {
334     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select MSB."
335     << "This is a bug, please report it!\n" << std::flush;
336     return;
337     }
338     const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
339     // dispatch event for engines listening to the same MIDI channel
340     {
341     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
342     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
343     // according to the MIDI specs, a bank select should not alter the patch
344     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
345     }
346     // dispatch event for engines listening to ALL MIDI channels
347     {
348     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
349     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
350     // according to the MIDI specs, a bank select should not alter the patch
351     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
352     }
353     MidiChannelMapReader.Unlock();
354     }
355 schoenebeck 551
356 schoenebeck 947 void MidiInputPort::DispatchBankSelectLsb(uint8_t BankLSB, uint MidiChannel) {
357     if (BankLSB > 127 || MidiChannel > 16) return;
358     if (!pDevice || !pDevice->pSampler) {
359     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select LSB."
360     << "This is a bug, please report it!\n" << std::flush;
361     return;
362 schoenebeck 551 }
363 schoenebeck 947 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
364     // dispatch event for engines listening to the same MIDI channel
365     {
366     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
367     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
368     // according to the MIDI specs, a bank select should not alter the patch
369     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
370     }
371     // dispatch event for engines listening to ALL MIDI channels
372     {
373     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
374     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
375     // according to the MIDI specs, a bank select should not alter the patch
376     for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
377     }
378     MidiChannelMapReader.Unlock();
379 schoenebeck 551 }
380    
381 persson 1887 void MidiInputPort::DispatchRaw(uint8_t* pData) {
382     uint8_t channel = pData[0] & 0x0f;
383     switch (pData[0] & 0xf0) {
384     case 0x80:
385     DispatchNoteOff(pData[1], pData[2], channel);
386     break;
387     case 0x90:
388     if (pData[2]) {
389     DispatchNoteOn(pData[1], pData[2], channel);
390     } else {
391     DispatchNoteOff(pData[1], pData[2], channel);
392     }
393     break;
394     case 0xb0:
395     if (pData[1] == 0) {
396     DispatchBankSelectMsb(pData[2], channel);
397     } else if (pData[1] == 32) {
398     DispatchBankSelectLsb(pData[2], channel);
399     }
400     DispatchControlChange(pData[1], pData[2], channel);
401     break;
402     case 0xc0:
403     DispatchProgramChange(pData[1], channel);
404     break;
405     case 0xd0:
406     DispatchControlChange(128, pData[1], channel);
407     break;
408     case 0xe0:
409     DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel);
410     break;
411     }
412     }
413    
414 persson 1765 void MidiInputPort::DispatchRaw(uint8_t* pData, int32_t FragmentPos) {
415     uint8_t channel = pData[0] & 0x0f;
416     switch (pData[0] & 0xf0) {
417     case 0x80:
418     DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
419     break;
420     case 0x90:
421     if (pData[2]) {
422     DispatchNoteOn(pData[1], pData[2], channel, FragmentPos);
423     } else {
424     DispatchNoteOff(pData[1], pData[2], channel, FragmentPos);
425     }
426     break;
427     case 0xb0:
428     if (pData[1] == 0) {
429     DispatchBankSelectMsb(pData[2], channel);
430     } else if (pData[1] == 32) {
431     DispatchBankSelectLsb(pData[2], channel);
432     }
433     DispatchControlChange(pData[1], pData[2], channel, FragmentPos);
434     break;
435     case 0xc0:
436     DispatchProgramChange(pData[1], channel);
437     break;
438     case 0xd0:
439     DispatchControlChange(128, pData[1], channel, FragmentPos);
440     break;
441     case 0xe0:
442 persson 1887 DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel, FragmentPos);
443 persson 1765 break;
444     }
445     }
446 schoenebeck 2380
447     void MidiInputPort::SetNoteOnVelocityFilter(const std::vector<uint8_t>& filter) {
448     if (filter.size() != 128 && filter.size() != 0)
449     throw MidiInputException("Note on velocity filter must be either of size 128 or 0");
450    
451     // check the value range of the filter
452     if (!filter.empty())
453     for (int i = 0; i < 128; i++)
454     if (filter[i] > 127)
455     throw MidiInputException("Invalid note on velocity filter, values must be in range 0 .. 127");
456    
457     // apply new filter ...
458     noteOnVelocityFilterMutex.Lock();
459     // double buffer ... double work ...
460     {
461     std::vector<uint8_t>& config =
462     noteOnVelocityFilter.GetConfigForUpdate();
463     config = filter;
464     }
465     {
466     std::vector<uint8_t>& config =
467     noteOnVelocityFilter.SwitchConfig();
468     config = filter;
469     }
470     noteOnVelocityFilterMutex.Unlock();
471     }
472 persson 1765
473 schoenebeck 411 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
474 schoenebeck 221 if (MidiChannel < 0 || MidiChannel > 16)
475     throw MidiInputException("MIDI channel index out of bounds");
476 schoenebeck 670
477 persson 840 // first check if desired connection is already established
478 schoenebeck 675 MidiChannelMapMutex.Lock();
479 persson 840 MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
480     bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
481 schoenebeck 675 MidiChannelMapMutex.Unlock();
482     if (bAlreadyDone) return;
483    
484     // remove all other connections of that engine channel (if any)
485 schoenebeck 411 Disconnect(pEngineChannel);
486 schoenebeck 670
487 schoenebeck 675 // register engine channel on the desired MIDI channel
488 schoenebeck 551 MidiChannelMapMutex.Lock();
489 persson 840 MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
490     MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
491 schoenebeck 551 MidiChannelMapMutex.Unlock();
492 schoenebeck 670
493 schoenebeck 675 // inform engine channel about this connection
494     pEngineChannel->Connect(this, MidiChannel);
495    
496 schoenebeck 670 // mark engine channel as changed
497     pEngineChannel->StatusChanged(true);
498 schoenebeck 221 }
499    
500 schoenebeck 411 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
501 schoenebeck 675 if (!pEngineChannel) return;
502    
503     bool bChannelFound = false;
504    
505     // unregister engine channel from all MIDI channels
506 schoenebeck 551 MidiChannelMapMutex.Lock();
507 schoenebeck 675 try {
508 persson 840 {
509     MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
510     for (int i = 0; i <= 16; i++) {
511     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
512     midiChannelMap[i].erase(pEngineChannel);
513     }
514 schoenebeck 675 }
515 persson 840 // do the same update again, after switching to the other config
516     {
517     MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
518     for (int i = 0; i <= 16; i++) {
519     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
520     midiChannelMap[i].erase(pEngineChannel);
521     }
522     }
523 schoenebeck 675 }
524 schoenebeck 221 catch(...) { /* NOOP */ }
525 schoenebeck 551 MidiChannelMapMutex.Unlock();
526 schoenebeck 675
527     // inform engine channel about the disconnection (if there is one)
528     if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
529    
530 schoenebeck 670 // mark engine channel as changed
531     pEngineChannel->StatusChanged(true);
532 schoenebeck 221 }
533    
534 persson 846 SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
535    
536     void MidiInputPort::AddSysexListener(Engine* engine) {
537     std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
538     if (p.second) SysexListeners.SwitchConfig().insert(engine);
539     }
540    
541     bool MidiInputPort::RemoveSysexListener(Engine* engine) {
542     int count = SysexListeners.GetConfigForUpdate().erase(engine);
543     if (count) SysexListeners.SwitchConfig().erase(engine);
544     return count;
545     }
546    
547 schoenebeck 1695 void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
548     virtualMidiDevicesMutex.Lock();
549     // double buffer ... double work ...
550     {
551     std::vector<VirtualMidiDevice*>& devices =
552     virtualMidiDevices.GetConfigForUpdate();
553     devices.push_back(pDevice);
554     }
555     {
556     std::vector<VirtualMidiDevice*>& devices =
557     virtualMidiDevices.SwitchConfig();
558     devices.push_back(pDevice);
559     }
560     virtualMidiDevicesMutex.Unlock();
561     }
562    
563     void MidiInputPort::Disconnect(VirtualMidiDevice* pDevice) {
564     virtualMidiDevicesMutex.Lock();
565     // double buffer ... double work ...
566     {
567     std::vector<VirtualMidiDevice*>& devices =
568     virtualMidiDevices.GetConfigForUpdate();
569     devices.erase(std::find(devices.begin(), devices.end(), pDevice));
570     }
571     {
572     std::vector<VirtualMidiDevice*>& devices =
573     virtualMidiDevices.SwitchConfig();
574     devices.erase(std::find(devices.begin(), devices.end(), pDevice));
575     }
576     virtualMidiDevicesMutex.Unlock();
577     }
578    
579 schoenebeck 221 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC