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

Diff of /linuxsampler/trunk/src/drivers/midi/MidiInstrumentMapper.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 958 by schoenebeck, Wed Nov 29 19:48:38 2006 UTC revision 1763 by iliev, Wed Sep 3 17:18:51 2008 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2006 Christian Schoenebeck                              *   *   Copyright (C) 2006 - 2007 Christian Schoenebeck                       *
4   *                                                                         *   *                                                                         *
5   *   This library is free software; you can redistribute it and/or modify  *   *   This library is free software; you can redistribute it and/or modify  *
6   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 20  Line 20 
20    
21  #include "MidiInstrumentMapper.h"  #include "MidiInstrumentMapper.h"
22    
23    #include "../../common/global_private.h"
24  #include "../../common/Mutex.h"  #include "../../common/Mutex.h"
25  #include "../../engines/EngineFactory.h"  #include "../../engines/EngineFactory.h"
26  #include "../../engines/Engine.h"  #include "../../engines/Engine.h"
# Line 35  namespace LinuxSampler { Line 36  namespace LinuxSampler {
36          String Name;          String Name;
37      };      };
38    
39      // here we store all mappings (MIDI bank&prog) -> (Engine,File,Index)      // internal map type (MIDI bank&prog) -> (Engine,File,Index)
40      std::map<midi_prog_index_t,private_entry_t> midiMap;      class MidiInstrumentMap : public std::map<midi_prog_index_t,private_entry_t> {
41            public:
42                String name;
43        };
44    
45        // here we store all maps
46        std::map<int,MidiInstrumentMap> midiMaps;
47    
48        // for synchronization of midiMaps
49        Mutex midiMapsMutex;
50    
51        ListenerList<MidiInstrumentCountListener*> MidiInstrumentMapper::llMidiInstrumentCountListeners;
52        ListenerList<MidiInstrumentInfoListener*> MidiInstrumentMapper::llMidiInstrumentInfoListeners;
53        ListenerList<MidiInstrumentMapCountListener*> MidiInstrumentMapper::llMidiInstrumentMapCountListeners;
54        ListenerList<MidiInstrumentMapInfoListener*> MidiInstrumentMapper::llMidiInstrumentMapInfoListeners;
55        int MidiInstrumentMapper::DefaultMap;
56        
57        void MidiInstrumentMapper::AddMidiInstrumentCountListener(MidiInstrumentCountListener* l) {
58            llMidiInstrumentCountListeners.AddListener(l);
59        }
60    
61        void MidiInstrumentMapper::RemoveMidiInstrumentCountListener(MidiInstrumentCountListener* l) {
62            llMidiInstrumentCountListeners.RemoveListener(l);
63        }
64    
65        void MidiInstrumentMapper::fireMidiInstrumentCountChanged(int MapId, int NewCount) {
66            for (int i = 0; i < llMidiInstrumentCountListeners.GetListenerCount(); i++) {
67                llMidiInstrumentCountListeners.GetListener(i)->MidiInstrumentCountChanged(MapId, NewCount);
68            }
69        }
70    
71        void MidiInstrumentMapper::AddMidiInstrumentInfoListener(MidiInstrumentInfoListener* l) {
72            llMidiInstrumentInfoListeners.AddListener(l);
73        }
74    
75        void MidiInstrumentMapper::RemoveMidiInstrumentInfoListener(MidiInstrumentInfoListener* l) {
76            llMidiInstrumentInfoListeners.RemoveListener(l);
77        }
78    
79        void MidiInstrumentMapper::fireMidiInstrumentInfoChanged(int MapId, int Bank, int Program) {
80            for (int i = 0; i < llMidiInstrumentInfoListeners.GetListenerCount(); i++) {
81                llMidiInstrumentInfoListeners.GetListener(i)->MidiInstrumentInfoChanged(MapId, Bank, Program);
82            }
83        }
84    
85        void MidiInstrumentMapper::AddMidiInstrumentMapCountListener(MidiInstrumentMapCountListener* l) {
86            llMidiInstrumentMapCountListeners.AddListener(l);
87        }
88    
89        void MidiInstrumentMapper::RemoveMidiInstrumentMapCountListener(MidiInstrumentMapCountListener* l) {
90            llMidiInstrumentMapCountListeners.RemoveListener(l);
91        }
92    
93        void MidiInstrumentMapper::fireMidiInstrumentMapCountChanged(int NewCount) {
94            for (int i = 0; i < llMidiInstrumentMapCountListeners.GetListenerCount(); i++) {
95                llMidiInstrumentMapCountListeners.GetListener(i)->MidiInstrumentMapCountChanged(NewCount);
96            }
97        }
98    
99        void MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(MidiInstrumentMapInfoListener* l) {
100            llMidiInstrumentMapInfoListeners.AddListener(l);
101        }
102    
103      // for synchronization of midiMap      void MidiInstrumentMapper::RemoveMidiInstrumentMapInfoListener(MidiInstrumentMapInfoListener* l) {
104      Mutex midiMapMutex;          llMidiInstrumentMapInfoListeners.RemoveListener(l);
105        }
106    
107        void MidiInstrumentMapper::fireMidiInstrumentMapInfoChanged(int MapId) {
108            for (int i = 0; i < llMidiInstrumentMapInfoListeners.GetListenerCount(); i++) {
109                llMidiInstrumentMapInfoListeners.GetListener(i)->MidiInstrumentMapInfoChanged(MapId);
110            }
111        }
112    
113      void MidiInstrumentMapper::AddOrReplaceMapping(midi_prog_index_t Index, entry_t Entry, bool bInBackground) throw (Exception) {      void MidiInstrumentMapper::AddOrReplaceEntry(int Map, midi_prog_index_t Index, entry_t Entry, bool bInBackground) throw (Exception) {
114          if (bInBackground) {          if (bInBackground) {
115              dmsg(3,("MidiInstrumentMapper: updating mapping (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d in background\n",              dmsg(3,("MidiInstrumentMapper: updating mapping %d (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d in background\n",
116                    Map,
117                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
118                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
119                  Entry.Volume,Entry.LoadMode)                  Entry.Volume,Entry.LoadMode)
120              );              );
121          } else {          } else {
122              dmsg(3,("MidiInstrumentMapper: updating mapping (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d\n",              dmsg(3,("MidiInstrumentMapper: updating mapping %d (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d\n",
123                    Map,
124                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
125                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
126                  Entry.Volume,Entry.LoadMode)                  Entry.Volume,Entry.LoadMode)
127              );              );
128          }          }
129            midiMapsMutex.Lock();
130            if (midiMaps.empty()) {
131                midiMapsMutex.Unlock();
132                throw Exception("There is no MIDI instrument map, you have to add one first.");
133            }
134            midiMapsMutex.Unlock();
135            if (!Entry.InstrumentFile.size())
136                throw Exception("No instrument file name given");
137            // TODO: an easy one - we should check here if given file exists and throw an exception if it doesn't
138          if (Entry.Volume < 0.0)          if (Entry.Volume < 0.0)
139              throw Exception("Volume may not be a negative value");              throw Exception("Volume may not be a negative value");
140          Engine* pEngine = EngineFactory::Create(Entry.EngineName);          Engine* pEngine = EngineFactory::Create(Entry.EngineName);
# Line 66  namespace LinuxSampler { Line 145  namespace LinuxSampler {
145              InstrumentManager::instrument_id_t id;              InstrumentManager::instrument_id_t id;
146              id.FileName = Entry.InstrumentFile;              id.FileName = Entry.InstrumentFile;
147              id.Index    = Entry.InstrumentIndex;              id.Index    = Entry.InstrumentIndex;
148              if (Entry.LoadMode != VOID) {              if (Entry.LoadMode != DONTCARE) {
149                  if (bInBackground)                  if (bInBackground)
150                      pEngine->GetInstrumentManager()->SetModeInBackground(id, static_cast<InstrumentManager::mode_t>(Entry.LoadMode));                      pEngine->GetInstrumentManager()->SetModeInBackground(id, static_cast<InstrumentManager::mode_t>(Entry.LoadMode));
151                  else                  else
# Line 81  namespace LinuxSampler { Line 160  namespace LinuxSampler {
160          privateEntry.InstrumentIndex = Entry.InstrumentIndex;          privateEntry.InstrumentIndex = Entry.InstrumentIndex;
161          privateEntry.Volume          = Entry.Volume;          privateEntry.Volume          = Entry.Volume;
162          privateEntry.Name            = Entry.Name;          privateEntry.Name            = Entry.Name;
163          midiMapMutex.Lock();  
164          midiMap[Index] = privateEntry;          bool Replaced = false;
165          midiMapMutex.Unlock();          int InstrCount = 0;
166    
167            midiMapsMutex.Lock();
168            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
169            if (iterMap != midiMaps.end()) { // map found
170                Replaced = (iterMap->second.find(Index) != iterMap->second.end());
171                iterMap->second[Index] = privateEntry;
172                InstrCount = iterMap->second.size();
173            } else { // no such map
174                midiMapsMutex.Unlock();
175                EngineFactory::Destroy(pEngine);
176                throw Exception("There is no MIDI instrument map " + ToString(Map));
177            }
178            midiMapsMutex.Unlock();
179          EngineFactory::Destroy(pEngine);          EngineFactory::Destroy(pEngine);
180            
181            if (Replaced) {
182                int Bank = (int(Index.midi_bank_msb) << 7) | int(Index.midi_bank_lsb);
183                fireMidiInstrumentInfoChanged(Map, Bank, Index.midi_prog);
184            } else {
185                fireMidiInstrumentCountChanged(Map, InstrCount);
186            }
187      }      }
188    
189      void MidiInstrumentMapper::RemoveMapping(midi_prog_index_t Index) {      void MidiInstrumentMapper::SetLoadMode(entry_t* pEntry) {
190          midiMapMutex.Lock();          Engine* pEngine = EngineFactory::Create(pEntry->EngineName);
191          midiMap.erase(Index);          if (!pEngine) { // invalid mapping
192          midiMapMutex.Unlock();              throw Exception("Invalid mapping");
193            }
194    
195            InstrumentManager* pManager = pEngine->GetInstrumentManager();
196            if (pManager) { // engine provides an InstrumentManager
197                InstrumentManager::instrument_id_t id;
198                id.FileName = pEntry->InstrumentFile;
199                id.Index    = pEntry->InstrumentIndex;
200                pEntry->LoadMode = static_cast<mode_t>(pManager->GetMode(id));
201            } else { // engine does not provide an InstrumentManager
202                // use default value
203                pEntry->LoadMode = ON_DEMAND;
204            }
205    
206            EngineFactory::Destroy(pEngine);
207      }      }
208    
209      void MidiInstrumentMapper::RemoveAllMappings() {      MidiInstrumentMapper::entry_t MidiInstrumentMapper::GetEntry(int Map, uint MidiBank, uint MidiProg) {
210          midiMapMutex.Lock();          midiMapsMutex.Lock();
211          midiMap.clear();          std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
212          midiMapMutex.Unlock();          if (iterMap == midiMaps.end()) { // no such map
213                midiMapsMutex.Unlock();
214                throw Exception("There is no MIDI instrument map " + ToString(Map));
215            }
216    
217            midi_prog_index_t idx;
218            idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
219            idx.midi_bank_lsb = MidiBank & 0x7f;
220            idx.midi_prog     = MidiProg;
221    
222            std::map<midi_prog_index_t,private_entry_t>::iterator iterEntry = iterMap->second.find(idx);
223            if (iterEntry == iterMap->second.end()) {
224                midiMapsMutex.Unlock();
225                throw Exception("There is no map entry with that index");
226            }
227    
228            entry_t entry;
229            entry.EngineName      = iterEntry->second.EngineName;
230            entry.InstrumentFile  = iterEntry->second.InstrumentFile;
231            entry.InstrumentIndex = iterEntry->second.InstrumentIndex;
232            entry.Volume          = iterEntry->second.Volume;
233            entry.Name            = iterEntry->second.Name;
234    
235            try {
236                SetLoadMode(&entry);
237            } catch(Exception e) {
238                midiMapsMutex.Unlock();
239                throw e;
240            }
241    
242            midiMapsMutex.Unlock();
243            
244            return entry;
245      }      }
246    
247      std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> MidiInstrumentMapper::Mappings() {      void MidiInstrumentMapper::RemoveEntry(int Map, midi_prog_index_t Index) {
248            int InstrCount = -1;
249    
250            midiMapsMutex.Lock();
251            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
252            if (iterMap != midiMaps.end()) { // map found
253                iterMap->second.erase(Index); // remove entry
254                InstrCount = iterMap->second.size();
255            }
256            midiMapsMutex.Unlock();
257            
258            if (InstrCount != -1) {
259                fireMidiInstrumentCountChanged(Map, InstrCount);
260            }
261        }
262    
263        void MidiInstrumentMapper::RemoveAllEntries(int Map) {
264            int InstrCount = -1;
265    
266            midiMapsMutex.Lock();
267            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
268            if (iterMap != midiMaps.end()) { // map found
269                iterMap->second.clear(); // clear that map
270                InstrCount = 0;
271            }
272            midiMapsMutex.Unlock();
273            
274            if (InstrCount != -1) {
275                fireMidiInstrumentCountChanged(Map, InstrCount);
276            }
277        }
278    
279        std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> MidiInstrumentMapper::Entries(int Map) throw (Exception) {
280          std::map<midi_prog_index_t,entry_t> result;          std::map<midi_prog_index_t,entry_t> result;
281    
282          // copy the internal map first          // copy the internal map first
283          midiMapMutex.Lock();          midiMapsMutex.Lock();
284          for (std::map<midi_prog_index_t,private_entry_t>::iterator iter = midiMap.begin();          std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
285               iter != midiMap.end(); iter++)          if (iterMap == midiMaps.end()) { // no such map
286                midiMapsMutex.Unlock();
287                throw Exception("There is no MIDI instrument map " + ToString(Map));
288            }
289            for (std::map<midi_prog_index_t,private_entry_t>::iterator iterEntry = iterMap->second.begin();
290                 iterEntry != iterMap->second.end(); iterEntry++)
291          {          {
292              entry_t entry;              entry_t entry;
293              entry.EngineName      = iter->second.EngineName;              entry.EngineName      = iterEntry->second.EngineName;
294              entry.InstrumentFile  = iter->second.InstrumentFile;              entry.InstrumentFile  = iterEntry->second.InstrumentFile;
295              entry.InstrumentIndex = iter->second.InstrumentIndex;              entry.InstrumentIndex = iterEntry->second.InstrumentIndex;
296              entry.Volume          = iter->second.Volume;              entry.Volume          = iterEntry->second.Volume;
297              entry.Name            = iter->second.Name;              entry.Name            = iterEntry->second.Name;
298              result[iter->first] = entry;              result[iterEntry->first] = entry;
299          }          }
300          midiMapMutex.Unlock();          midiMapsMutex.Unlock();
301    
302          // complete it with current LoadMode of each entry          // complete it with current LoadMode of each entry
303          for (std::map<midi_prog_index_t,entry_t>::iterator iter = result.begin();          for (std::map<midi_prog_index_t,entry_t>::iterator iter = result.begin();
304               iter != result.end(); iter++)               iter != result.end(); iter++)
305          {          {
306              entry_t& entry = iter->second;              try {
307              Engine* pEngine = EngineFactory::Create(entry.EngineName);                  SetLoadMode(&(iter->second));
308              if (!pEngine) { // invalid mapping              } catch(Exception e) {
309                  RemoveMapping(iter->first);                  RemoveEntry(Map, iter->first);
310                  result.erase(iter);                  result.erase(iter);
                 continue;  
311              }              }
312              InstrumentManager* pManager = pEngine->GetInstrumentManager();          }
313              if (pManager) { // engine provides an InstrumentManager          return result;
314                  InstrumentManager::instrument_id_t id;      }
315                  id.FileName = entry.InstrumentFile;  
316                  id.Index    = entry.InstrumentIndex;      std::vector<int> MidiInstrumentMapper::Maps() {
317                  entry.LoadMode = static_cast<mode_t>(pManager->GetMode(id));          std::vector<int> result;
318              } else { // engine does not provide an InstrumentManager          midiMapsMutex.Lock();
319                  // use default value          for (std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.begin();
320                  entry.LoadMode = ON_DEMAND;               iterMap != midiMaps.end(); iterMap++)
321            {
322                result.push_back(iterMap->first);
323            }
324            midiMapsMutex.Unlock();
325            return result;
326        }
327    
328        int MidiInstrumentMapper::GetMapCount() {
329            midiMapsMutex.Lock();
330            int i = midiMaps.size();
331            midiMapsMutex.Unlock();
332            return i;
333        }
334    
335        int MidiInstrumentMapper::GetInstrumentCount(int Map) {
336            midiMapsMutex.Lock();
337            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
338            if (iterMap == midiMaps.end()) { // no such map
339                midiMapsMutex.Unlock();
340                throw Exception("There is no MIDI instrument map " + ToString(Map));
341            }
342    
343            int i = iterMap->second.size();
344            midiMapsMutex.Unlock();
345            return i;
346        }
347    
348        int MidiInstrumentMapper::GetInstrumentCount() {
349            int count = 0;
350    
351            midiMapsMutex.Lock();
352            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.begin();
353            for (;iterMap != midiMaps.end(); iterMap++) {
354                count += iterMap->second.size();
355            }
356            midiMapsMutex.Unlock();
357    
358            return count;
359        }
360    
361        int MidiInstrumentMapper::AddMap(String MapName) throw (Exception) {
362            int ID;
363            midiMapsMutex.Lock();
364            if (midiMaps.empty()) ID = 0;
365            else {
366                // get the highest existing map ID
367                uint lastIndex = (--(midiMaps.end()))->first;
368                // check if we reached the index limit
369                if (lastIndex + 1 < lastIndex) {
370                    // search for an unoccupied map ID starting from 0
371                    for (uint i = 0; i < lastIndex; i++) {
372                        if (midiMaps.find(i) != midiMaps.end()) continue;
373                        // we found an unused ID, so insert the new map there
374                        ID = i;
375                        goto __create_map;
376                    }
377                    throw Exception("Internal error: could not find unoccupied MIDI instrument map ID.");
378              }              }
379              EngineFactory::Destroy(pEngine);              ID = lastIndex + 1;
380            }
381            __create_map:
382            midiMaps[ID].name = MapName;
383            
384            fireMidiInstrumentMapCountChanged(Maps().size());
385            // If there were no maps until now we must set a default map.
386            if (midiMaps.size() == 1) SetDefaultMap(ID);
387            midiMapsMutex.Unlock();
388            
389            return ID;
390        }
391    
392        String MidiInstrumentMapper::MapName(int Map) throw (Exception) {
393            String result;
394            midiMapsMutex.Lock();
395            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
396            if (iterMap == midiMaps.end()) {
397                midiMapsMutex.Unlock();
398                throw Exception("There is no MIDI instrument map " + ToString(Map));
399          }          }
400            result = iterMap->second.name;
401            midiMapsMutex.Unlock();
402          return result;          return result;
403      }      }
404    
405      optional<MidiInstrumentMapper::entry_t> MidiInstrumentMapper::GetEntry(midi_prog_index_t Index) {      void MidiInstrumentMapper::RenameMap(int Map, String NewName) throw (Exception) {
406            midiMapsMutex.Lock();
407            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
408            if (iterMap == midiMaps.end()) {
409                midiMapsMutex.Unlock();
410                throw Exception("There is no MIDI instrument map " + ToString(Map));
411            }
412            iterMap->second.name = NewName;
413            midiMapsMutex.Unlock();
414            fireMidiInstrumentMapInfoChanged(Map);
415        }
416    
417        void MidiInstrumentMapper::RemoveMap(int Map) {
418            midiMapsMutex.Lock();
419            midiMaps.erase(Map);
420            if(Map == GetDefaultMap()) {
421                SetDefaultMap(midiMaps.empty() ? -1 : (*(midiMaps.begin())).first);
422            }
423            fireMidiInstrumentMapCountChanged(Maps().size());
424            midiMapsMutex.Unlock();
425        }
426    
427        void MidiInstrumentMapper::RemoveAllMaps() {
428            midiMapsMutex.Lock();
429            midiMaps.clear();
430            SetDefaultMap(-1);
431            fireMidiInstrumentMapCountChanged(Maps().size());
432            midiMapsMutex.Unlock();
433        }
434    
435        int MidiInstrumentMapper::GetDefaultMap() {
436            midiMapsMutex.Lock();
437            int i = DefaultMap;
438            midiMapsMutex.Unlock();
439            return i;
440        }
441    
442        void MidiInstrumentMapper::SetDefaultMap(int MapId) {
443            midiMapsMutex.Lock();
444            DefaultMap = MapId;
445            midiMapsMutex.Unlock();
446            
447            if (MapId != -1) fireMidiInstrumentMapInfoChanged(MapId);
448        }
449    
450        optional<MidiInstrumentMapper::entry_t> MidiInstrumentMapper::GetEntry(int Map, midi_prog_index_t Index) {
451          optional<entry_t> result;          optional<entry_t> result;
452          midiMapMutex.Lock();          midiMapsMutex.Lock();
453          std::map<midi_prog_index_t,private_entry_t>::iterator iter = midiMap.find(Index);          std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
454          if (iter != midiMap.end()) {          if (iterMap != midiMaps.end()) { // map found
455              entry_t entry;              std::map<midi_prog_index_t,private_entry_t>::iterator iterEntry = iterMap->second.find(Index);
456              entry.EngineName      = iter->second.EngineName;              if (iterEntry != iterMap->second.end()) {
457              entry.InstrumentFile  = iter->second.InstrumentFile;                  entry_t entry;
458              entry.InstrumentIndex = iter->second.InstrumentIndex;                  entry.EngineName      = iterEntry->second.EngineName;
459              entry.Volume          = iter->second.Volume;                  entry.InstrumentFile  = iterEntry->second.InstrumentFile;
460              //TODO: for now we skip the LoadMode and Name entry here, since we don't need it in the MidiInputPort                  entry.InstrumentIndex = iterEntry->second.InstrumentIndex;
461              result = entry;                  entry.Volume          = iterEntry->second.Volume;
462                    //TODO: for now we skip the LoadMode and Name entry here, since we don't need it in the MidiInputPort
463                    result = entry;
464                }
465          }          }
466          midiMapMutex.Unlock();          midiMapsMutex.Unlock();
467          return result;          return result;
468      }      }
469    

Legend:
Removed from v.958  
changed lines
  Added in v.1763

  ViewVC Help
Powered by ViewVC