/[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 2317 - (show annotations) (download)
Sun Feb 19 12:13:19 2012 UTC (12 years, 1 month ago) by persson
File size: 25465 byte(s)
* sfz engine bugfix: looping was disabled if loop_start was set to 0
* sfz engine: allow regions with end=-1 to turn off other regions
  using the group and off_by opcodes (#168)
* sfz engine: made end=0 play the whole sample
* sfz engine: fixed support for lochan and hichan opcodes (#155)
* bumped version to 1.0.0.svn17

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

  ViewVC Help
Powered by ViewVC