/[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 970 by schoenebeck, Wed Dec 6 22:28:17 2006 UTC revision 1130 by iliev, Sun Mar 25 18:59:14 2007 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 35  namespace LinuxSampler { Line 35  namespace LinuxSampler {
35          String Name;          String Name;
36      };      };
37    
38      // here we store all mappings (MIDI bank&prog) -> (Engine,File,Index)      // internal map type (MIDI bank&prog) -> (Engine,File,Index)
39      std::map<midi_prog_index_t,private_entry_t> midiMap;      class MidiInstrumentMap : public std::map<midi_prog_index_t,private_entry_t> {
40            public:
41                String name;
42        };
43    
44        // here we store all maps
45        std::map<int,MidiInstrumentMap> midiMaps;
46    
47        // for synchronization of midiMaps
48        Mutex midiMapsMutex;
49    
50    
51        ListenerList<MidiInstrumentCountListener*> MidiInstrumentMapper::llMidiInstrumentCountListeners;
52        ListenerList<MidiInstrumentInfoListener*> MidiInstrumentMapper::llMidiInstrumentInfoListeners;
53        ListenerList<MidiInstrumentMapCountListener*> MidiInstrumentMapper::llMidiInstrumentMapCountListeners;
54        ListenerList<MidiInstrumentMapInfoListener*> MidiInstrumentMapper::llMidiInstrumentMapInfoListeners;
55        
56        void MidiInstrumentMapper::AddMidiInstrumentCountListener(MidiInstrumentCountListener* l) {
57            llMidiInstrumentCountListeners.AddListener(l);
58        }
59    
60        void MidiInstrumentMapper::RemoveMidiInstrumentCountListener(MidiInstrumentCountListener* l) {
61            llMidiInstrumentCountListeners.RemoveListener(l);
62        }
63    
64        void MidiInstrumentMapper::fireMidiInstrumentCountChanged(int MapId, int NewCount) {
65            for (int i = 0; i < llMidiInstrumentCountListeners.GetListenerCount(); i++) {
66                llMidiInstrumentCountListeners.GetListener(i)->MidiInstrumentCountChanged(MapId, NewCount);
67            }
68        }
69    
70      // for synchronization of midiMap      void MidiInstrumentMapper::AddMidiInstrumentInfoListener(MidiInstrumentInfoListener* l) {
71      Mutex midiMapMutex;          llMidiInstrumentInfoListeners.AddListener(l);
72        }
73    
74        void MidiInstrumentMapper::RemoveMidiInstrumentInfoListener(MidiInstrumentInfoListener* l) {
75            llMidiInstrumentInfoListeners.RemoveListener(l);
76        }
77    
78        void MidiInstrumentMapper::fireMidiInstrumentInfoChanged(int MapId, int Bank, int Program) {
79            for (int i = 0; i < llMidiInstrumentInfoListeners.GetListenerCount(); i++) {
80                llMidiInstrumentInfoListeners.GetListener(i)->MidiInstrumentInfoChanged(MapId, Bank, Program);
81            }
82        }
83    
84        void MidiInstrumentMapper::AddMidiInstrumentMapCountListener(MidiInstrumentMapCountListener* l) {
85            llMidiInstrumentMapCountListeners.AddListener(l);
86        }
87    
88      void MidiInstrumentMapper::AddOrReplaceMapping(midi_prog_index_t Index, entry_t Entry, bool bInBackground) throw (Exception) {      void MidiInstrumentMapper::RemoveMidiInstrumentMapCountListener(MidiInstrumentMapCountListener* l) {
89            llMidiInstrumentMapCountListeners.RemoveListener(l);
90        }
91    
92        void MidiInstrumentMapper::fireMidiInstrumentMapCountChanged(int NewCount) {
93            for (int i = 0; i < llMidiInstrumentMapCountListeners.GetListenerCount(); i++) {
94                llMidiInstrumentMapCountListeners.GetListener(i)->MidiInstrumentMapCountChanged(NewCount);
95            }
96        }
97    
98        void MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(MidiInstrumentMapInfoListener* l) {
99            llMidiInstrumentMapInfoListeners.AddListener(l);
100        }
101    
102        void MidiInstrumentMapper::RemoveMidiInstrumentMapInfoListener(MidiInstrumentMapInfoListener* l) {
103            llMidiInstrumentMapInfoListeners.RemoveListener(l);
104        }
105    
106        void MidiInstrumentMapper::fireMidiInstrumentMapInfoChanged(int MapId) {
107            for (int i = 0; i < llMidiInstrumentMapInfoListeners.GetListenerCount(); i++) {
108                llMidiInstrumentMapInfoListeners.GetListener(i)->MidiInstrumentMapInfoChanged(MapId);
109            }
110        }
111    
112        void MidiInstrumentMapper::AddOrReplaceEntry(int Map, midi_prog_index_t Index, entry_t Entry, bool bInBackground) throw (Exception) {
113          if (bInBackground) {          if (bInBackground) {
114              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",
115                    Map,
116                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
117                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
118                  Entry.Volume,Entry.LoadMode)                  Entry.Volume,Entry.LoadMode)
119              );              );
120          } else {          } else {
121              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",
122                    Map,
123                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
124                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
125                  Entry.Volume,Entry.LoadMode)                  Entry.Volume,Entry.LoadMode)
126              );              );
127          }          }
128            midiMapsMutex.Lock();
129            if (midiMaps.empty()) {
130                midiMapsMutex.Unlock();
131                throw Exception("There is no MIDI instrument map, you have to add one first.");
132            }
133            midiMapsMutex.Unlock();
134          if (!Entry.InstrumentFile.size())          if (!Entry.InstrumentFile.size())
135              throw Exception("No instrument file name given");              throw Exception("No instrument file name given");
136            // TODO: an easy one - we should check here if given file exists and throw an exception if it doesn't
137          if (Entry.Volume < 0.0)          if (Entry.Volume < 0.0)
138              throw Exception("Volume may not be a negative value");              throw Exception("Volume may not be a negative value");
139          Engine* pEngine = EngineFactory::Create(Entry.EngineName);          Engine* pEngine = EngineFactory::Create(Entry.EngineName);
# Line 83  namespace LinuxSampler { Line 159  namespace LinuxSampler {
159          privateEntry.InstrumentIndex = Entry.InstrumentIndex;          privateEntry.InstrumentIndex = Entry.InstrumentIndex;
160          privateEntry.Volume          = Entry.Volume;          privateEntry.Volume          = Entry.Volume;
161          privateEntry.Name            = Entry.Name;          privateEntry.Name            = Entry.Name;
162          midiMapMutex.Lock();  
163          midiMap[Index] = privateEntry;          bool Replaced = false;
164          midiMapMutex.Unlock();          int InstrCount = 0;
165    
166            midiMapsMutex.Lock();
167            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
168            if (iterMap != midiMaps.end()) { // map found
169                Replaced = (iterMap->second.find(Index) != iterMap->second.end());
170                iterMap->second[Index] = privateEntry;
171                InstrCount = iterMap->second.size();
172            } else { // no such map
173                midiMapsMutex.Unlock();
174                EngineFactory::Destroy(pEngine);
175                throw Exception("There is no MIDI instrument map " + ToString(Map));
176            }
177            midiMapsMutex.Unlock();
178          EngineFactory::Destroy(pEngine);          EngineFactory::Destroy(pEngine);
179            
180            if (Replaced) {
181                int Bank = (int(Index.midi_bank_msb) << 7) & int(Index.midi_bank_lsb);
182                fireMidiInstrumentInfoChanged(Map, Bank, Index.midi_prog);
183            } else {
184                fireMidiInstrumentCountChanged(Map, InstrCount);
185            }
186      }      }
187    
188      void MidiInstrumentMapper::RemoveMapping(midi_prog_index_t Index) {      void MidiInstrumentMapper::RemoveEntry(int Map, midi_prog_index_t Index) {
189          midiMapMutex.Lock();          int InstrCount = -1;
190          midiMap.erase(Index);  
191          midiMapMutex.Unlock();          midiMapsMutex.Lock();
192            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
193            if (iterMap != midiMaps.end()) { // map found
194                iterMap->second.erase(Index); // remove entry
195                InstrCount = iterMap->second.size();
196            }
197            midiMapsMutex.Unlock();
198            
199            if (InstrCount != -1) {
200                fireMidiInstrumentCountChanged(Map, InstrCount);
201            }
202      }      }
203    
204      void MidiInstrumentMapper::RemoveAllMappings() {      void MidiInstrumentMapper::RemoveAllEntries(int Map) {
205          midiMapMutex.Lock();          int InstrCount = -1;
206          midiMap.clear();  
207          midiMapMutex.Unlock();          midiMapsMutex.Lock();
208            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
209            if (iterMap != midiMaps.end()) { // map found
210                iterMap->second.clear(); // clear that map
211                InstrCount = 0;
212            }
213            midiMapsMutex.Unlock();
214            
215            if (InstrCount != -1) {
216                fireMidiInstrumentCountChanged(Map, InstrCount);
217            }
218      }      }
219    
220      std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> MidiInstrumentMapper::Mappings() {      std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> MidiInstrumentMapper::Entries(int Map) throw (Exception) {
221          std::map<midi_prog_index_t,entry_t> result;          std::map<midi_prog_index_t,entry_t> result;
222    
223          // copy the internal map first          // copy the internal map first
224          midiMapMutex.Lock();          midiMapsMutex.Lock();
225          for (std::map<midi_prog_index_t,private_entry_t>::iterator iter = midiMap.begin();          std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
226               iter != midiMap.end(); iter++)          if (iterMap == midiMaps.end()) { // no such map
227                midiMapsMutex.Unlock();
228                throw Exception("There is no MIDI instrument map " + ToString(Map));
229            }
230            for (std::map<midi_prog_index_t,private_entry_t>::iterator iterEntry = iterMap->second.begin();
231                 iterEntry != iterMap->second.end(); iterEntry++)
232          {          {
233              entry_t entry;              entry_t entry;
234              entry.EngineName      = iter->second.EngineName;              entry.EngineName      = iterEntry->second.EngineName;
235              entry.InstrumentFile  = iter->second.InstrumentFile;              entry.InstrumentFile  = iterEntry->second.InstrumentFile;
236              entry.InstrumentIndex = iter->second.InstrumentIndex;              entry.InstrumentIndex = iterEntry->second.InstrumentIndex;
237              entry.Volume          = iter->second.Volume;              entry.Volume          = iterEntry->second.Volume;
238              entry.Name            = iter->second.Name;              entry.Name            = iterEntry->second.Name;
239              result[iter->first] = entry;              result[iterEntry->first] = entry;
240          }          }
241          midiMapMutex.Unlock();          midiMapsMutex.Unlock();
242    
243          // complete it with current LoadMode of each entry          // complete it with current LoadMode of each entry
244          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();
245               iter != result.end(); iter++)               iter != result.end(); iter++)
# Line 124  namespace LinuxSampler { Line 247  namespace LinuxSampler {
247              entry_t& entry = iter->second;              entry_t& entry = iter->second;
248              Engine* pEngine = EngineFactory::Create(entry.EngineName);              Engine* pEngine = EngineFactory::Create(entry.EngineName);
249              if (!pEngine) { // invalid mapping              if (!pEngine) { // invalid mapping
250                  RemoveMapping(iter->first);                  RemoveEntry(Map, iter->first);
251                  result.erase(iter);                  result.erase(iter);
252                  continue;                  continue;
253              }              }
# Line 143  namespace LinuxSampler { Line 266  namespace LinuxSampler {
266          return result;          return result;
267      }      }
268    
269      optional<MidiInstrumentMapper::entry_t> MidiInstrumentMapper::GetEntry(midi_prog_index_t Index) {      std::vector<int> MidiInstrumentMapper::Maps() {
270            std::vector<int> result;
271            midiMapsMutex.Lock();
272            for (std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.begin();
273                 iterMap != midiMaps.end(); iterMap++)
274            {
275                result.push_back(iterMap->first);
276            }
277            midiMapsMutex.Unlock();
278            return result;
279        }
280    
281        int MidiInstrumentMapper::AddMap(String MapName) throw (Exception) {
282            int ID;
283            midiMapsMutex.Lock();
284            if (midiMaps.empty()) ID = 0;
285            else {
286                // get the highest existing map ID
287                uint lastIndex = (--(midiMaps.end()))->first;
288                // check if we reached the index limit
289                if (lastIndex + 1 < lastIndex) {
290                    // search for an unoccupied map ID starting from 0
291                    for (uint i = 0; i < lastIndex; i++) {
292                        if (midiMaps.find(i) != midiMaps.end()) continue;
293                        // we found an unused ID, so insert the new map there
294                        ID = i;
295                        goto __create_map;
296                    }
297                    throw Exception("Internal error: could not find unoccupied MIDI instrument map ID.");
298                }
299                ID = lastIndex + 1;
300            }
301            __create_map:
302            midiMaps[ID].name = MapName;
303            midiMapsMutex.Unlock();
304    
305            fireMidiInstrumentMapCountChanged(Maps().size());
306            return ID;
307        }
308    
309        String MidiInstrumentMapper::MapName(int Map) throw (Exception) {
310            String result;
311            midiMapsMutex.Lock();
312            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
313            if (iterMap == midiMaps.end()) {
314                midiMapsMutex.Unlock();
315                throw Exception("There is no MIDI instrument map " + ToString(Map));
316            }
317            result = iterMap->second.name;
318            midiMapsMutex.Unlock();
319            return result;
320        }
321    
322        void MidiInstrumentMapper::RenameMap(int Map, String NewName) throw (Exception) {
323            midiMapsMutex.Lock();
324            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
325            if (iterMap == midiMaps.end()) {
326                midiMapsMutex.Unlock();
327                throw Exception("There is no MIDI instrument map " + ToString(Map));
328            }
329            iterMap->second.name = NewName;
330            midiMapsMutex.Unlock();
331            fireMidiInstrumentMapInfoChanged(Map);
332        }
333    
334        void MidiInstrumentMapper::RemoveMap(int Map) {
335            midiMapsMutex.Lock();
336            midiMaps.erase(Map);
337            midiMapsMutex.Unlock();
338            fireMidiInstrumentMapCountChanged(Maps().size());
339        }
340    
341        void MidiInstrumentMapper::RemoveAllMaps() {
342            midiMapsMutex.Lock();
343            midiMaps.clear();
344            midiMapsMutex.Unlock();
345            fireMidiInstrumentMapCountChanged(Maps().size());
346        }
347    
348        optional<MidiInstrumentMapper::entry_t> MidiInstrumentMapper::GetEntry(int Map, midi_prog_index_t Index) {
349          optional<entry_t> result;          optional<entry_t> result;
350          midiMapMutex.Lock();          midiMapsMutex.Lock();
351          std::map<midi_prog_index_t,private_entry_t>::iterator iter = midiMap.find(Index);          std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
352          if (iter != midiMap.end()) {          if (iterMap != midiMaps.end()) { // map found
353              entry_t entry;              std::map<midi_prog_index_t,private_entry_t>::iterator iterEntry = iterMap->second.find(Index);
354              entry.EngineName      = iter->second.EngineName;              if (iterEntry != iterMap->second.end()) {
355              entry.InstrumentFile  = iter->second.InstrumentFile;                  entry_t entry;
356              entry.InstrumentIndex = iter->second.InstrumentIndex;                  entry.EngineName      = iterEntry->second.EngineName;
357              entry.Volume          = iter->second.Volume;                  entry.InstrumentFile  = iterEntry->second.InstrumentFile;
358              //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;
359              result = entry;                  entry.Volume          = iterEntry->second.Volume;
360                    //TODO: for now we skip the LoadMode and Name entry here, since we don't need it in the MidiInputPort
361                    result = entry;
362                }
363          }          }
364          midiMapMutex.Unlock();          midiMapsMutex.Unlock();
365          return result;          return result;
366      }      }
367    

Legend:
Removed from v.970  
changed lines
  Added in v.1130

  ViewVC Help
Powered by ViewVC