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

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2014 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 int 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