/[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 1695 - (show annotations) (download)
Sat Feb 16 01:09:33 2008 UTC (16 years, 1 month ago) by schoenebeck
File size: 25320 byte(s)
* added new LSCP event "DEVICE_MIDI" which can be used by frontends to
  react on MIDI data arriving on certain MIDI input devices (so far only
  Note-On and Note-Off events are sent via this LSCP event)
* bumped version to 0.5.1.4cvs

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2008 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);
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);
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, 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, 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);
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);
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, 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, 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);
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);
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, 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, 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);
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);
248 }
249 MidiChannelMapReader.Unlock();
250 }
251
252 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
253 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
254 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
255 // dispatch event for engines listening to the same MIDI channel
256 {
257 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
258 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
259 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
260 }
261 // dispatch event for engines listening to ALL MIDI channels
262 {
263 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
264 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
265 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
266 }
267 MidiChannelMapReader.Unlock();
268 }
269
270 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
271 const std::set<Engine*> allEngines = SysexListenersReader.Lock();
272 // dispatch event to all engine instances
273 std::set<Engine*>::iterator engineiter = allEngines.begin();
274 std::set<Engine*>::iterator end = allEngines.end();
275 for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);
276 SysexListenersReader.Unlock();
277 }
278
279 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
280 dmsg(1,("Received MIDI program change (prog=%d,ch=%d)\n",Program,MidiChannel));
281 if (Program > 127 || MidiChannel > 16) return;
282 if (!pDevice || !pDevice->pSampler) {
283 std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
284 << "This is a bug, please report it!\n" << std::flush;
285 return;
286 }
287 std::vector<int> maps = MidiInstrumentMapper::Maps();
288 if (maps.empty()) return;
289
290 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
291 // dispatch event for engines listening to the same MIDI channel
292 {
293 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
294 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
295 for (; engineiter != end; engineiter++) {
296 (*engineiter)->SetMidiProgram(Program);
297 if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
298 if (MidiInstrumentMapper::GetMapCount() == 0) continue;
299 // retrieve the MIDI instrument map this engine channel is assigned to
300 int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
301 ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
302 // is there an entry for this MIDI bank&prog pair in that map?
303 midi_prog_index_t midiIndex;
304 midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
305 midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
306 midiIndex.midi_prog = (*engineiter)->GetMidiProgram();
307 optional<MidiInstrumentMapper::entry_t> mapping =
308 MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
309 if (mapping) { // if mapping exists ...
310 InstrumentManager::instrument_id_t id;
311 id.FileName = mapping->InstrumentFile;
312 id.Index = mapping->InstrumentIndex;
313 //TODO: we should switch the engine type here
314 InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
315 (*engineiter)->Volume(mapping->Volume);
316 }
317 }
318 }
319 // dispatch event for engines listening to ALL MIDI channels
320 {
321 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
322 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
323 for (; engineiter != end; engineiter++) {
324 (*engineiter)->SetMidiProgram(Program);
325 if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
326 if (MidiInstrumentMapper::GetMapCount() == 0) continue;
327 // retrieve the MIDI instrument map this engine channel is assigned to
328 int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
329 ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
330 // is there an entry for this MIDI bank&prog pair in that map?
331 midi_prog_index_t midiIndex;
332 midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
333 midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
334 midiIndex.midi_prog = (*engineiter)->GetMidiProgram();
335 optional<MidiInstrumentMapper::entry_t> mapping =
336 MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
337 if (mapping) { // if mapping exists ...
338 InstrumentManager::instrument_id_t id;
339 id.FileName = mapping->InstrumentFile;
340 id.Index = mapping->InstrumentIndex;
341 //TODO: we should switch the engine type here
342 InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
343 (*engineiter)->Volume(mapping->Volume);
344 }
345 }
346 }
347 MidiChannelMapReader.Unlock();
348 }
349
350 void MidiInputPort::DispatchBankSelectMsb(uint8_t BankMSB, uint MidiChannel) {
351 if (BankMSB > 127 || MidiChannel > 16) return;
352 if (!pDevice || !pDevice->pSampler) {
353 std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select MSB."
354 << "This is a bug, please report it!\n" << std::flush;
355 return;
356 }
357 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
358 // dispatch event for engines listening to the same MIDI channel
359 {
360 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
361 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
362 // according to the MIDI specs, a bank select should not alter the patch
363 for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
364 }
365 // dispatch event for engines listening to ALL MIDI channels
366 {
367 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
368 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
369 // according to the MIDI specs, a bank select should not alter the patch
370 for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankMsb(BankMSB);
371 }
372 MidiChannelMapReader.Unlock();
373 }
374
375 void MidiInputPort::DispatchBankSelectLsb(uint8_t BankLSB, uint MidiChannel) {
376 if (BankLSB > 127 || MidiChannel > 16) return;
377 if (!pDevice || !pDevice->pSampler) {
378 std::cerr << "MidiInputPort: ERROR, no sampler instance to handle bank select LSB."
379 << "This is a bug, please report it!\n" << std::flush;
380 return;
381 }
382 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
383 // dispatch event for engines listening to the same MIDI channel
384 {
385 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
386 std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
387 // according to the MIDI specs, a bank select should not alter the patch
388 for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
389 }
390 // dispatch event for engines listening to ALL MIDI channels
391 {
392 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
393 std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
394 // according to the MIDI specs, a bank select should not alter the patch
395 for (; engineiter != end; engineiter++) (*engineiter)->SetMidiBankLsb(BankLSB);
396 }
397 MidiChannelMapReader.Unlock();
398 }
399
400 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
401 if (MidiChannel < 0 || MidiChannel > 16)
402 throw MidiInputException("MIDI channel index out of bounds");
403
404 // first check if desired connection is already established
405 MidiChannelMapMutex.Lock();
406 MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
407 bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
408 MidiChannelMapMutex.Unlock();
409 if (bAlreadyDone) return;
410
411 // remove all other connections of that engine channel (if any)
412 Disconnect(pEngineChannel);
413
414 // register engine channel on the desired MIDI channel
415 MidiChannelMapMutex.Lock();
416 MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
417 MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
418 MidiChannelMapMutex.Unlock();
419
420 // inform engine channel about this connection
421 pEngineChannel->Connect(this, MidiChannel);
422
423 // mark engine channel as changed
424 pEngineChannel->StatusChanged(true);
425 }
426
427 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
428 if (!pEngineChannel) return;
429
430 bool bChannelFound = false;
431
432 // unregister engine channel from all MIDI channels
433 MidiChannelMapMutex.Lock();
434 try {
435 {
436 MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
437 for (int i = 0; i <= 16; i++) {
438 bChannelFound |= midiChannelMap[i].count(pEngineChannel);
439 midiChannelMap[i].erase(pEngineChannel);
440 }
441 }
442 // do the same update again, after switching to the other config
443 {
444 MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
445 for (int i = 0; i <= 16; i++) {
446 bChannelFound |= midiChannelMap[i].count(pEngineChannel);
447 midiChannelMap[i].erase(pEngineChannel);
448 }
449 }
450 }
451 catch(...) { /* NOOP */ }
452 MidiChannelMapMutex.Unlock();
453
454 // inform engine channel about the disconnection (if there is one)
455 if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
456
457 // mark engine channel as changed
458 pEngineChannel->StatusChanged(true);
459 }
460
461 SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
462
463 void MidiInputPort::AddSysexListener(Engine* engine) {
464 std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
465 if (p.second) SysexListeners.SwitchConfig().insert(engine);
466 }
467
468 bool MidiInputPort::RemoveSysexListener(Engine* engine) {
469 int count = SysexListeners.GetConfigForUpdate().erase(engine);
470 if (count) SysexListeners.SwitchConfig().erase(engine);
471 return count;
472 }
473
474 void MidiInputPort::Connect(VirtualMidiDevice* pDevice) {
475 virtualMidiDevicesMutex.Lock();
476 // double buffer ... double work ...
477 {
478 std::vector<VirtualMidiDevice*>& devices =
479 virtualMidiDevices.GetConfigForUpdate();
480 devices.push_back(pDevice);
481 }
482 {
483 std::vector<VirtualMidiDevice*>& devices =
484 virtualMidiDevices.SwitchConfig();
485 devices.push_back(pDevice);
486 }
487 virtualMidiDevicesMutex.Unlock();
488 }
489
490 void MidiInputPort::Disconnect(VirtualMidiDevice* pDevice) {
491 virtualMidiDevicesMutex.Lock();
492 // double buffer ... double work ...
493 {
494 std::vector<VirtualMidiDevice*>& devices =
495 virtualMidiDevices.GetConfigForUpdate();
496 devices.erase(std::find(devices.begin(), devices.end(), pDevice));
497 }
498 {
499 std::vector<VirtualMidiDevice*>& devices =
500 virtualMidiDevices.SwitchConfig();
501 devices.erase(std::find(devices.begin(), devices.end(), pDevice));
502 }
503 virtualMidiDevicesMutex.Unlock();
504 }
505
506 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC