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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3054 - (show 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 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2016 Christian Schoenebeck *
7 * *
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 #include "../../common/global_private.h"
27 #include "MidiInstrumentMapper.h"
28 #include "../../Sampler.h"
29 #include "../../engines/EngineFactory.h"
30 #include "VirtualMidiDevice.h"
31
32 #include <algorithm>
33
34 namespace LinuxSampler {
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 void MidiInputPort::ParameterName::OnSetValue(String s) throw (Exception) {
60 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 Parameters.clear();
75 }
76
77 MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
78 : MidiChannelMapReader(MidiChannelMap),
79 SysexListenersReader(SysexListeners),
80 virtualMidiDevicesReader(virtualMidiDevices),
81 noteOnVelocityFilterReader(noteOnVelocityFilter)
82 {
83 this->pDevice = pDevice;
84 this->portNumber = portNumber;
85 runningStatusBuf[0] = 0;
86 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 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
103
104 // apply velocity filter (if any)
105 const std::vector<uint8_t>& velocityFilter = noteOnVelocityFilterReader.Lock();
106 if (!velocityFilter.empty()) Velocity = velocityFilter[Velocity];
107 noteOnVelocityFilterReader.Unlock();
108
109 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
110 // dispatch event for engines listening to the same MIDI channel
111 {
112 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
113 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
114 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
115 }
116 // dispatch event for engines listening to ALL MIDI channels
117 {
118 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
119 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
120 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
121 }
122 MidiChannelMapReader.Unlock();
123
124 // dispatch event to all low priority MIDI listeners
125 const std::vector<VirtualMidiDevice*>& listeners =
126 virtualMidiDevicesReader.Lock();
127 for (int i = 0; i < listeners.size(); ++i)
128 listeners[i]->SendNoteOnToDevice(Key, Velocity);
129 virtualMidiDevicesReader.Unlock();
130 }
131
132 void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
133 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
134
135 // apply velocity filter (if any)
136 const std::vector<uint8_t>& velocityFilter = noteOnVelocityFilterReader.Lock();
137 if (!velocityFilter.empty()) Velocity = velocityFilter[Velocity];
138 noteOnVelocityFilterReader.Unlock();
139
140 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
141 // dispatch event for engines listening to the same MIDI channel
142 {
143 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
144 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
145 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
146 }
147 // dispatch event for engines listening to ALL MIDI channels
148 {
149 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
150 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
151 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
152 }
153 MidiChannelMapReader.Unlock();
154
155 // dispatch event to all low priority MIDI listeners
156 const std::vector<VirtualMidiDevice*>& listeners =
157 virtualMidiDevicesReader.Lock();
158 for (int i = 0; i < listeners.size(); ++i)
159 listeners[i]->SendNoteOnToDevice(Key, Velocity);
160 virtualMidiDevicesReader.Unlock();
161 }
162
163 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
164 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
165 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
166 // dispatch event for engines listening to the same MIDI channel
167 {
168 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
169 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
170 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
171 }
172 // dispatch event for engines listening to ALL MIDI channels
173 {
174 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
175 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
176 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
177 }
178 MidiChannelMapReader.Unlock();
179
180 // dispatch event to all low priority MIDI listeners
181 const std::vector<VirtualMidiDevice*>& listeners =
182 virtualMidiDevicesReader.Lock();
183 for (int i = 0; i < listeners.size(); ++i)
184 listeners[i]->SendNoteOffToDevice(Key, Velocity);
185 virtualMidiDevicesReader.Unlock();
186 }
187
188 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
189 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
190 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
191 // dispatch event for engines listening to the same MIDI channel
192 {
193 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
194 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
195 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
196 }
197 // dispatch event for engines listening to ALL MIDI channels
198 {
199 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
200 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
201 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
202 }
203 MidiChannelMapReader.Unlock();
204
205 // dispatch event to all low priority MIDI listeners
206 const std::vector<VirtualMidiDevice*>& listeners =
207 virtualMidiDevicesReader.Lock();
208 for (int i = 0; i < listeners.size(); ++i)
209 listeners[i]->SendNoteOffToDevice(Key, Velocity);
210 virtualMidiDevicesReader.Unlock();
211 }
212
213 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
214 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
215 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
216 // dispatch event for engines listening to the same MIDI channel
217 {
218 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
219 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
220 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
221 }
222 // dispatch event for engines listening to ALL MIDI channels
223 {
224 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
225 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
226 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
227 }
228 MidiChannelMapReader.Unlock();
229 }
230
231 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
232 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
233 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
234 // dispatch event for engines listening to the same MIDI channel
235 {
236 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
237 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
238 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
239 }
240 // dispatch event for engines listening to ALL MIDI channels
241 {
242 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
243 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
244 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
245 }
246 MidiChannelMapReader.Unlock();
247 }
248
249 void MidiInputPort::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 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
322 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
323 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
324 // dispatch event for engines listening to the same MIDI channel
325 {
326 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
327 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
328 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
329 }
330 // dispatch event for engines listening to ALL MIDI channels
331 {
332 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
333 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
334 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
335 }
336 MidiChannelMapReader.Unlock();
337
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 }
345
346 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
347 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
348 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 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
354 }
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 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
360 }
361 MidiChannelMapReader.Unlock();
362
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 }
370
371 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
372 const std::set<Engine*> allEngines = SysexListenersReader.Lock();
373 // dispatch event to all engine instances
374 std::set<Engine*>::iterator engineiter = allEngines.begin();
375 std::set<Engine*>::iterator end = allEngines.end();
376 for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
377 SysexListenersReader.Unlock();
378 }
379
380 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
381 if (Program > 127 || MidiChannel > 16) return;
382 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
388 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 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
394 }
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 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
400 }
401 MidiChannelMapReader.Unlock();
402 }
403
404 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
429 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 }
436 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 }
453
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
490 void MidiInputPort::DispatchRaw(uint8_t* pData) {
491 pData = handleRunningStatus(pData);
492
493 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 case 0xA0:
506 DispatchPolyphonicKeyPressure(pData[1], pData[2], channel);
507 break;
508 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 DispatchChannelPressure(pData[1], channel);
521 break;
522 case 0xe0:
523 DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel);
524 break;
525 }
526 }
527
528 void MidiInputPort::DispatchRaw(uint8_t* pData, int32_t FragmentPos) {
529 pData = handleRunningStatus(pData);
530
531 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 case 0xA0:
544 DispatchPolyphonicKeyPressure(pData[1], pData[2], channel, FragmentPos);
545 break;
546 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 DispatchChannelPressure(pData[1], channel, FragmentPos);
559 break;
560 case 0xe0:
561 DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel, FragmentPos);
562 break;
563 }
564 }
565
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 LockGuard lock(noteOnVelocityFilterMutex);
578 // 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
591 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
592 if (MidiChannel < 0 || MidiChannel > 16)
593 throw MidiInputException("MIDI channel index out of bounds");
594
595 // first check if desired connection is already established
596 {
597 LockGuard lock(MidiChannelMapMutex);
598 MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
599 if (midiChannelMap[MidiChannel].count(pEngineChannel)) return;
600 }
601
602 // remove all other connections of that engine channel (if any)
603 Disconnect(pEngineChannel);
604
605 // register engine channel on the desired MIDI channel
606 {
607 LockGuard lock(MidiChannelMapMutex);
608 MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
609 MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
610 }
611
612 // inform engine channel about this connection
613 pEngineChannel->Connect(this);
614 if (pEngineChannel->MidiChannel() != MidiChannel)
615 pEngineChannel->SetMidiChannel(MidiChannel);
616
617 // mark engine channel as changed
618 pEngineChannel->StatusChanged(true);
619 }
620
621 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
622 if (!pEngineChannel) return;
623
624 bool bChannelFound = false;
625
626 // unregister engine channel from all MIDI channels
627 try {
628 LockGuard lock(MidiChannelMapMutex);
629 {
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 }
636 // 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 }
645 catch(...) { /* NOOP */ }
646
647 // inform engine channel about the disconnection (if there is one)
648 if (bChannelFound) pEngineChannel->Disconnect(this);
649
650 // mark engine channel as changed
651 pEngineChannel->StatusChanged(true);
652 }
653
654 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 size_t count = SysexListeners.GetConfigForUpdate().erase(engine);
663 if (count) SysexListeners.SwitchConfig().erase(engine);
664 return count;
665 }
666
667 void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
668 LockGuard lock(virtualMidiDevicesMutex);
669 // 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 LockGuard lock(virtualMidiDevicesMutex);
684 // 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 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 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC