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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1135 - (hide annotations) (download)
Thu Mar 29 09:40:45 2007 UTC (12 years, 11 months ago) by iliev
File size: 22735 byte(s)
* Added new LSCP command - SET FX_SEND NAME
* The default map is now the first available map

1 schoenebeck 221 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 880 * Copyright (C) 2005, 2006 Christian Schoenebeck *
7 schoenebeck 221 * *
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 schoenebeck 947 #include "MidiInstrumentMapper.h"
27 schoenebeck 551 #include "../../Sampler.h"
28 schoenebeck 775 #include "../../engines/EngineFactory.h"
29 schoenebeck 551
30 schoenebeck 221 namespace LinuxSampler {
31    
32     // *************** ParameterName ***************
33     // *
34    
35     MidiInputPort::ParameterName::ParameterName(MidiInputPort* pPort) : DeviceRuntimeParameterString("Port " + ToString(pPort->GetPortNumber())) {
36     this->pPort = pPort;
37     }
38    
39     MidiInputPort::ParameterName::ParameterName(MidiInputPort* pPort, String val) : DeviceRuntimeParameterString(val) {
40     this->pPort = pPort;
41     }
42    
43     String MidiInputPort::ParameterName::Description() {
44     return "Name for this port";
45     }
46    
47     bool MidiInputPort::ParameterName::Fix() {
48     return false;
49     }
50    
51     std::vector<String> MidiInputPort::ParameterName::PossibilitiesAsString() {
52     return std::vector<String>();
53     }
54    
55 schoenebeck 880 void MidiInputPort::ParameterName::OnSetValue(String s) throw (Exception) {
56 schoenebeck 221 return; /* FIXME: Nothing to do here */
57     }
58    
59    
60    
61     // *************** MidiInputPort ***************
62     // *
63    
64     MidiInputPort::~MidiInputPort() {
65     std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();
66     while (iter != Parameters.end()) {
67     delete iter->second;
68     iter++;
69     }
70 persson 836 Parameters.clear();
71 schoenebeck 221 }
72    
73 persson 846 MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
74     : MidiChannelMapReader(MidiChannelMap),
75     SysexListenersReader(SysexListeners) {
76 schoenebeck 221 this->pDevice = pDevice;
77     this->portNumber = portNumber;
78     Parameters["NAME"] = new ParameterName(this);
79     }
80    
81     MidiInputDevice* MidiInputPort::GetDevice() {
82     return pDevice;
83     }
84    
85     uint MidiInputPort::GetPortNumber() {
86     return portNumber;
87     }
88    
89     std::map<String,DeviceRuntimeParameter*> MidiInputPort::PortParameters() {
90     return Parameters;
91     }
92    
93     void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
94 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
95 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
96 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
97     {
98 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
99     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
100 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
101     }
102     // dispatch event for engines listening to ALL MIDI channels
103     {
104 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
105     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
106 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
107     }
108 persson 846 MidiChannelMapReader.Unlock();
109 schoenebeck 221 }
110    
111 schoenebeck 906 void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
112 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
113 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
114     // dispatch event for engines listening to the same MIDI channel
115     {
116     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
117     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
118     for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, FragmentPos);
119     }
120     // dispatch event for engines listening to ALL MIDI channels
121     {
122     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
123     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
124     for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, FragmentPos);
125     }
126     MidiChannelMapReader.Unlock();
127     }
128    
129 schoenebeck 221 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
130 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
131 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
132 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
133     {
134 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
135     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
136 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
137     }
138     // dispatch event for engines listening to ALL MIDI channels
139     {
140 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
141     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
142 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
143     }
144 persson 846 MidiChannelMapReader.Unlock();
145 schoenebeck 221 }
146    
147 schoenebeck 906 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
148 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
149 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
150     // dispatch event for engines listening to the same MIDI channel
151     {
152     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
153     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
154     for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, FragmentPos);
155     }
156     // dispatch event for engines listening to ALL MIDI channels
157     {
158     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
159     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
160     for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, FragmentPos);
161     }
162     MidiChannelMapReader.Unlock();
163     }
164    
165 schoenebeck 221 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
166 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
167 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
168 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
169     {
170 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
171     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
172 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
173     }
174     // dispatch event for engines listening to ALL MIDI channels
175     {
176 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
177     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
178 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
179     }
180 persson 846 MidiChannelMapReader.Unlock();
181 schoenebeck 221 }
182    
183 schoenebeck 906 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
184 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
185 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
186     // dispatch event for engines listening to the same MIDI channel
187     {
188     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
189     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
190     for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, FragmentPos);
191     }
192     // dispatch event for engines listening to ALL MIDI channels
193     {
194     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
195     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
196     for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, FragmentPos);
197     }
198     MidiChannelMapReader.Unlock();
199     }
200    
201 schoenebeck 221 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
202 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
203 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
204 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
205     {
206 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
207     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
208 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
209     }
210     // dispatch event for engines listening to ALL MIDI channels
211     {
212 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
213     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
214 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
215     }
216 persson 846 MidiChannelMapReader.Unlock();
217 schoenebeck 221 }
218    
219 schoenebeck 906 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
220 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
221 schoenebeck 906 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
222     // dispatch event for engines listening to the same MIDI channel
223     {
224     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
225     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
226     for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
227     }
228     // dispatch event for engines listening to ALL MIDI channels
229     {
230     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
231     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
232     for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, FragmentPos);
233     }
234     MidiChannelMapReader.Unlock();
235     }
236    
237 schoenebeck 244 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
238 persson 846 const std::set<Engine*> allEngines = SysexListenersReader.Lock();
239 schoenebeck 775 // dispatch event to all engine instances
240 persson 846 std::set<Engine*>::iterator engineiter = allEngines.begin();
241     std::set<Engine*>::iterator end = allEngines.end();
242 schoenebeck 775 for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size);
243 persson 846 SysexListenersReader.Unlock();
244 schoenebeck 244 }
245    
246 schoenebeck 670 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
247 schoenebeck 947 dmsg(1,("Received MIDI program change (prog=%d,ch=%d)\n",Program,MidiChannel));
248 persson 922 if (Program > 127 || MidiChannel > 16) return;
249 schoenebeck 551 if (!pDevice || !pDevice->pSampler) {
250     std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
251     << "This is a bug, please report it!\n" << std::flush;
252     return;
253     }
254 schoenebeck 973 std::vector<int> maps = MidiInstrumentMapper::Maps();
255     if (maps.empty()) return;
256    
257 schoenebeck 947 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
258     // dispatch event for engines listening to the same MIDI channel
259     {
260     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
261     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
262     for (; engineiter != end; engineiter++) {
263     (*engineiter)->SetMidiProgram(Program);
264 schoenebeck 973 if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
265 iliev 1135 if (MidiInstrumentMapper::GetMapCount() == 0) continue;
266 schoenebeck 973 // retrieve the MIDI instrument map this engine channel is assigned to
267     int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
268 iliev 1135 ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
269 schoenebeck 973 // is there an entry for this MIDI bank&prog pair in that map?
270 schoenebeck 947 midi_prog_index_t midiIndex;
271     midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
272     midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
273     midiIndex.midi_prog = (*engineiter)->GetMidiProgram();
274     optional<MidiInstrumentMapper::entry_t> mapping =
275 schoenebeck 973 MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
276 schoenebeck 947 if (mapping) { // if mapping exists ...
277     InstrumentManager::instrument_id_t id;
278     id.FileName = mapping->InstrumentFile;
279     id.Index = mapping->InstrumentIndex;
280     //TODO: we should switch the engine type here
281     InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
282     (*engineiter)->Volume(mapping->Volume);
283     }
284     }
285     }
286     // dispatch event for engines listening to ALL MIDI channels
287     {
288     std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
289     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
290     for (; engineiter != end; engineiter++) {
291     (*engineiter)->SetMidiProgram(Program);
292 schoenebeck 973 if ((*engineiter)->UsesNoMidiInstrumentMap()) continue;
293 iliev 1135 if (MidiInstrumentMapper::GetMapCount() == 0) continue;
294 schoenebeck 973 // retrieve the MIDI instrument map this engine channel is assigned to
295     int iMapID = ((*engineiter)->UsesDefaultMidiInstrumentMap())
296 iliev 1135 ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : (*engineiter)->GetMidiInstrumentMap();
297 schoenebeck 973 // is there an entry for this MIDI bank&prog pair in that map?
298 schoenebeck 947 midi_prog_index_t midiIndex;
299     midiIndex.midi_bank_msb = (*engineiter)->GetMidiBankMsb();
300     midiIndex.midi_bank_lsb = (*engineiter)->GetMidiBankLsb();
301     midiIndex.midi_prog = (*engineiter)->GetMidiProgram();
302     optional<MidiInstrumentMapper::entry_t> mapping =
303 schoenebeck 973 MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
304 schoenebeck 947 if (mapping) { // if mapping exists ...
305     InstrumentManager::instrument_id_t id;
306     id.FileName = mapping->InstrumentFile;
307     id.Index = mapping->InstrumentIndex;
308     //TODO: we should switch the engine type here
309     InstrumentManager::LoadInstrumentInBackground(id, *engineiter);
310     (*engineiter)->Volume(mapping->Volume);
311     }
312     }
313     }
314     MidiChannelMapReader.Unlock();
315     }
316 schoenebeck 551
317 schoenebeck 947 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 schoenebeck 551
342 schoenebeck 947 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 schoenebeck 551 }
349 schoenebeck 947 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 schoenebeck 551 }
366    
367 schoenebeck 411 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
368 schoenebeck 221 if (MidiChannel < 0 || MidiChannel > 16)
369     throw MidiInputException("MIDI channel index out of bounds");
370 schoenebeck 670
371 persson 840 // first check if desired connection is already established
372 schoenebeck 675 MidiChannelMapMutex.Lock();
373 persson 840 MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
374     bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
375 schoenebeck 675 MidiChannelMapMutex.Unlock();
376     if (bAlreadyDone) return;
377    
378     // remove all other connections of that engine channel (if any)
379 schoenebeck 411 Disconnect(pEngineChannel);
380 schoenebeck 670
381 schoenebeck 675 // register engine channel on the desired MIDI channel
382 schoenebeck 551 MidiChannelMapMutex.Lock();
383 persson 840 MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
384     MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
385 schoenebeck 551 MidiChannelMapMutex.Unlock();
386 schoenebeck 670
387 schoenebeck 675 // inform engine channel about this connection
388     pEngineChannel->Connect(this, MidiChannel);
389    
390 schoenebeck 670 // mark engine channel as changed
391     pEngineChannel->StatusChanged(true);
392 schoenebeck 221 }
393    
394 schoenebeck 411 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
395 schoenebeck 675 if (!pEngineChannel) return;
396    
397     bool bChannelFound = false;
398    
399     // unregister engine channel from all MIDI channels
400 schoenebeck 551 MidiChannelMapMutex.Lock();
401 schoenebeck 675 try {
402 persson 840 {
403     MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
404     for (int i = 0; i <= 16; i++) {
405     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
406     midiChannelMap[i].erase(pEngineChannel);
407     }
408 schoenebeck 675 }
409 persson 840 // do the same update again, after switching to the other config
410     {
411     MidiChannelMap_t& midiChannelMap = MidiChannelMap.SwitchConfig();
412     for (int i = 0; i <= 16; i++) {
413     bChannelFound |= midiChannelMap[i].count(pEngineChannel);
414     midiChannelMap[i].erase(pEngineChannel);
415     }
416     }
417 schoenebeck 675 }
418 schoenebeck 221 catch(...) { /* NOOP */ }
419 schoenebeck 551 MidiChannelMapMutex.Unlock();
420 schoenebeck 675
421     // inform engine channel about the disconnection (if there is one)
422     if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
423    
424 schoenebeck 670 // mark engine channel as changed
425     pEngineChannel->StatusChanged(true);
426 schoenebeck 221 }
427    
428 persson 846 SynchronizedConfig<std::set<LinuxSampler::Engine*> > MidiInputPort::SysexListeners;
429    
430     void MidiInputPort::AddSysexListener(Engine* engine) {
431     std::pair<std::set<Engine*>::iterator, bool> p = SysexListeners.GetConfigForUpdate().insert(engine);
432     if (p.second) SysexListeners.SwitchConfig().insert(engine);
433     }
434    
435     bool MidiInputPort::RemoveSysexListener(Engine* engine) {
436     int count = SysexListeners.GetConfigForUpdate().erase(engine);
437     if (count) SysexListeners.SwitchConfig().erase(engine);
438     return count;
439     }
440    
441 schoenebeck 221 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC