/[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 2317 - (hide annotations) (download)
Sun Feb 19 12:13:19 2012 UTC (12 years, 2 months 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 schoenebeck 221 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 persson 2317 * Copyright (C) 2005 - 2012 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 1424 #include "../../common/global_private.h"
27 schoenebeck 947 #include "MidiInstrumentMapper.h"
28 schoenebeck 551 #include "../../Sampler.h"
29 schoenebeck 775 #include "../../engines/EngineFactory.h"
30 schoenebeck 1695 #include "VirtualMidiDevice.h"
31 schoenebeck 551
32 schoenebeck 1695 #include <algorithm>
33    
34 schoenebeck 221 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 schoenebeck 880 void MidiInputPort::ParameterName::OnSetValue(String s) throw (Exception) {
60 schoenebeck 221 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 persson 836 Parameters.clear();
75 schoenebeck 221 }
76    
77 persson 846 MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber)
78     : MidiChannelMapReader(MidiChannelMap),
79 schoenebeck 1695 SysexListenersReader(SysexListeners),
80     virtualMidiDevicesReader(virtualMidiDevices) {
81 schoenebeck 221 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 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
100 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
101 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
102     {
103 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
104     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
105 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
106 schoenebeck 274 }
107     // dispatch event for engines listening to ALL MIDI channels
108     {
109 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
110     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
111 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel);
112 schoenebeck 274 }
113 persson 846 MidiChannelMapReader.Unlock();
114 schoenebeck 1695
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 schoenebeck 221 }
122    
123 schoenebeck 906 void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
124 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
125 schoenebeck 906 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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
131 schoenebeck 906 }
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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity, MidiChannel, FragmentPos);
137 schoenebeck 906 }
138     MidiChannelMapReader.Unlock();
139 schoenebeck 1695
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 schoenebeck 906 }
147    
148 schoenebeck 221 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
149 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
150 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
151 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
152     {
153 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
154     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
155 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
156 schoenebeck 274 }
157     // dispatch event for engines listening to ALL MIDI channels
158     {
159 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
160     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
161 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel);
162 schoenebeck 274 }
163 persson 846 MidiChannelMapReader.Unlock();
164 schoenebeck 1695
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 schoenebeck 221 }
172    
173 schoenebeck 906 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel, int32_t FragmentPos) {
174 persson 922 if (Key > 127 || Velocity > 127 || MidiChannel > 16) return;
175 schoenebeck 906 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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
181 schoenebeck 906 }
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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity, MidiChannel, FragmentPos);
187 schoenebeck 906 }
188     MidiChannelMapReader.Unlock();
189 schoenebeck 1695
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 schoenebeck 906 }
197    
198 schoenebeck 221 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
199 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
200 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
201 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
202     {
203 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
204     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
205 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
206 schoenebeck 274 }
207     // dispatch event for engines listening to ALL MIDI channels
208     {
209 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
210     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
211 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel);
212 schoenebeck 274 }
213 persson 846 MidiChannelMapReader.Unlock();
214 schoenebeck 221 }
215    
216 schoenebeck 906 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel, int32_t FragmentPos) {
217 persson 922 if (Pitch < -8192 || Pitch > 8191 || MidiChannel > 16) return;
218 schoenebeck 906 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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
224 schoenebeck 906 }
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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch, MidiChannel, FragmentPos);
230 schoenebeck 906 }
231     MidiChannelMapReader.Unlock();
232     }
233    
234 schoenebeck 221 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
235 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
236 persson 846 const MidiChannelMap_t& midiChannelMap = MidiChannelMapReader.Lock();
237 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
238     {
239 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[MidiChannel].begin();
240     std::set<EngineChannel*>::iterator end = midiChannelMap[MidiChannel].end();
241 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
242 schoenebeck 274 }
243     // dispatch event for engines listening to ALL MIDI channels
244     {
245 persson 840 std::set<EngineChannel*>::iterator engineiter = midiChannelMap[midi_chan_all].begin();
246     std::set<EngineChannel*>::iterator end = midiChannelMap[midi_chan_all].end();
247 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel);
248 schoenebeck 274 }
249 persson 846 MidiChannelMapReader.Unlock();
250 schoenebeck 2025
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 schoenebeck 221 }
258    
259 schoenebeck 906 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel, int32_t FragmentPos) {
260 persson 922 if (Controller > 128 || Value > 127 || MidiChannel > 16) return;
261 schoenebeck 906 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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
267 schoenebeck 906 }
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 persson 2317 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value, MidiChannel, FragmentPos);
273 schoenebeck 906 }
274     MidiChannelMapReader.Unlock();
275 schoenebeck 2025
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 schoenebeck 906 }
283    
284 schoenebeck 244 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
285 persson 846 const std::set<Engine*> allEngines = SysexListenersReader.Lock();
286 schoenebeck 775 // dispatch event to all engine instances
287 persson 846 std::set<Engine*>::iterator engineiter = allEngines.begin();
288     std::set<Engine*>::iterator end = allEngines.end();
289 schoenebeck 1751 for (; engineiter != end; engineiter++) (*engineiter)->SendSysex(pData, Size, this);
290 persson 846 SysexListenersReader.Unlock();
291 schoenebeck 244 }
292    
293 schoenebeck 670 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
294 persson 922 if (Program > 127 || MidiChannel > 16) return;
295 schoenebeck 551 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 schoenebeck 973
301 schoenebeck 947 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 persson 1924 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
307 schoenebeck 947 }
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 persson 1924 for (; engineiter != end; engineiter++) (*engineiter)->SendProgramChange(Program);
313 schoenebeck 947 }
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 persson 1887 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 persson 1765 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 persson 1887 DispatchPitchbend((pData[1] | pData[2] << 7) - 8192, channel, FragmentPos);
429 persson 1765 break;
430     }
431     }
432    
433 schoenebeck 411 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
434 schoenebeck 221 if (MidiChannel < 0 || MidiChannel > 16)
435     throw MidiInputException("MIDI channel index out of bounds");
436 schoenebeck 670
437 persson 840 // first check if desired connection is already established
438 schoenebeck 675 MidiChannelMapMutex.Lock();
439 persson 840 MidiChannelMap_t& midiChannelMap = MidiChannelMap.GetConfigForUpdate();
440     bool bAlreadyDone = midiChannelMap[MidiChannel].count(pEngineChannel);
441 schoenebeck 675 MidiChannelMapMutex.Unlock();
442     if (bAlreadyDone) return;
443    
444     // remove all other connections of that engine channel (if any)
445 schoenebeck 411 Disconnect(pEngineChannel);
446 schoenebeck 670
447 schoenebeck 675 // register engine channel on the desired MIDI channel
448 schoenebeck 551 MidiChannelMapMutex.Lock();
449 persson 840 MidiChannelMap.GetConfigForUpdate()[MidiChannel].insert(pEngineChannel);
450     MidiChannelMap.SwitchConfig()[MidiChannel].insert(pEngineChannel);
451 schoenebeck 551 MidiChannelMapMutex.Unlock();
452 schoenebeck 670
453 schoenebeck 675 // inform engine channel about this connection
454     pEngineChannel->Connect(this, MidiChannel);
455    
456 schoenebeck 670 // mark engine channel as changed
457     pEngineChannel->StatusChanged(true);
458 schoenebeck 221 }
459    
460 schoenebeck 411 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
461 schoenebeck 675 if (!pEngineChannel) return;
462    
463     bool bChannelFound = false;
464    
465     // unregister engine channel from all MIDI channels
466 schoenebeck 551 MidiChannelMapMutex.Lock();
467 schoenebeck 675 try {
468 persson 840 {
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 schoenebeck 675 }
475 persson 840 // 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 schoenebeck 675 }
484 schoenebeck 221 catch(...) { /* NOOP */ }
485 schoenebeck 551 MidiChannelMapMutex.Unlock();
486 schoenebeck 675
487     // inform engine channel about the disconnection (if there is one)
488     if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
489    
490 schoenebeck 670 // mark engine channel as changed
491     pEngineChannel->StatusChanged(true);
492 schoenebeck 221 }
493    
494 persson 846 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 schoenebeck 1695 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 schoenebeck 221 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC