/[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 2380 - (show annotations) (download)
Wed Nov 21 21:52:15 2012 UTC (11 years, 4 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 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2012 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 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 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
102
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 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
109 // dispatch event for engines listening to the same MIDI channel
110 {
111 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
112 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
113 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
114 }
115 // dispatch event for engines listening to ALL MIDI channels
116 {
117 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
118 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
119 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
120 }
121 MidiChannelMapReader.Unlock();
122
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 }
130
131 void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
132 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
133
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 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 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
145 }
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 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
151 }
152 MidiChannelMapReader.Unlock();
153
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 }
161
162 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
163 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
164 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
165 // dispatch event for engines listening to the same MIDI channel
166 {
167 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
168 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
169 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
170 }
171 // dispatch event for engines listening to ALL MIDI channels
172 {
173 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
174 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
175 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
176 }
177 MidiChannelMapReader.Unlock();
178
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 }
186
187 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
188 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
189 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 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
195 }
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 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
201 }
202 MidiChannelMapReader.Unlock();
203
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 }
211
212 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
213 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
214 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
215 // dispatch event for engines listening to the same MIDI channel
216 {
217 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
218 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
219 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
220 }
221 // dispatch event for engines listening to ALL MIDI channels
222 {
223 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
224 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
225 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
226 }
227 MidiChannelMapReader.Unlock();
228 }
229
230 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
231 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
232 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 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
238 }
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 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
244 }
245 MidiChannelMapReader.Unlock();
246 }
247
248 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
249 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
250 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
251 // dispatch event for engines listening to the same MIDI channel
252 {
253 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
254 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
255 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
256 }
257 // dispatch event for engines listening to ALL MIDI channels
258 {
259 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
260 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
261 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
262 }
263 MidiChannelMapReader.Unlock();
264
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 }
272
273 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
274 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
275 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 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
281 }
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 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
287 }
288 MidiChannelMapReader.Unlock();
289
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 }
297
298 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
299 const std::set<Engine*> allEngines = SysexListenersReader.Lock();
300 // dispatch event to all engine instances
301 std::set<Engine*>::iterator engineiter = allEngines.begin();
302 std::set<Engine*>::iterator end = allEngines.end();
303 for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
304 SysexListenersReader.Unlock();
305 }
306
307 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
308 if (Program > 127 || MidiChannel > 16) return;
309 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
315 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 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
321 }
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 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
327 }
328 MidiChannelMapReader.Unlock();
329 }
330
331 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
356 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 }
363 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 }
380
381 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 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 DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel, FragmentPos);
443 break;
444 }
445 }
446
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
473 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
474 if (MidiChannel < 0 || MidiChannel > 16)
475 throw MidiInputException("MIDI channel index out of bounds");
476
477 // first check if desired connection is already established
478 MidiChannelMapMutex.Lock();
479 MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
480 bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
481 MidiChannelMapMutex.Unlock();
482 if (bAlreadyDone) return;
483
484 // remove all other connections of that engine channel (if any)
485 Disconnect(pEngineChannel);
486
487 // register engine channel on the desired MIDI channel
488 MidiChannelMapMutex.Lock();
489 MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
490 MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
491 MidiChannelMapMutex.Unlock();
492
493 // inform engine channel about this connection
494 pEngineChannel->Connect(this, MidiChannel);
495
496 // mark engine channel as changed
497 pEngineChannel->StatusChanged(true);
498 }
499
500 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
501 if (!pEngineChannel) return;
502
503 bool bChannelFound = false;
504
505 // unregister engine channel from all MIDI channels
506 MidiChannelMapMutex.Lock();
507 try {
508 {
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 }
515 // 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 }
524 catch(...) { /* NOOP */ }
525 MidiChannelMapMutex.Unlock();
526
527 // inform engine channel about the disconnection (if there is one)
528 if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
529
530 // mark engine channel as changed
531 pEngineChannel->StatusChanged(true);
532 }
533
534 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 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 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC