/[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 1040 by schoenebeck, Wed Feb 7 15:41:31 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 23  Line 23 
23  #include "../../common/Mutex.h"  #include "../../common/Mutex.h"
24  #include "../../engines/EngineFactory.h"  #include "../../engines/EngineFactory.h"
25  #include "../../engines/Engine.h"  #include "../../engines/Engine.h"
26    #include "../../network/lscpserver.h"
27    
28  namespace LinuxSampler {  namespace LinuxSampler {
29    
# 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 midiMap      // for synchronization of midiMaps
49      Mutex midiMapMutex;      Mutex midiMapsMutex;
50    
51    
52      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) {
53          if (bInBackground) {          if (bInBackground) {
54              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",
55                    Map,
56                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
57                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
58                  Entry.Volume,Entry.LoadMode)                  Entry.Volume,Entry.LoadMode)
59              );              );
60          } else {          } else {
61              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",
62                    Map,
63                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,                  Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
64                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,                  Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
65                  Entry.Volume,Entry.LoadMode)                  Entry.Volume,Entry.LoadMode)
66              );              );
67          }          }
68            midiMapsMutex.Lock();
69            if (midiMaps.empty()) {
70                midiMapsMutex.Unlock();
71                throw Exception("There is no MIDI instrument map, you have to add one first.");
72            }
73            midiMapsMutex.Unlock();
74            if (!Entry.InstrumentFile.size())
75                throw Exception("No instrument file name given");
76            // TODO: an easy one - we should check here if given file exists and throw an exception if it doesn't
77          if (Entry.Volume < 0.0)          if (Entry.Volume < 0.0)
78              throw Exception("Volume may not be a negative value");              throw Exception("Volume may not be a negative value");
79          Engine* pEngine = EngineFactory::Create(Entry.EngineName);          Engine* pEngine = EngineFactory::Create(Entry.EngineName);
# Line 81  namespace LinuxSampler { Line 99  namespace LinuxSampler {
99          privateEntry.InstrumentIndex = Entry.InstrumentIndex;          privateEntry.InstrumentIndex = Entry.InstrumentIndex;
100          privateEntry.Volume          = Entry.Volume;          privateEntry.Volume          = Entry.Volume;
101          privateEntry.Name            = Entry.Name;          privateEntry.Name            = Entry.Name;
102          midiMapMutex.Lock();  
103          midiMap[Index] = privateEntry;          bool Replaced = false;
104          midiMapMutex.Unlock();          int InstrCount = 0;
105    
106            midiMapsMutex.Lock();
107            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
108            if (iterMap != midiMaps.end()) { // map found
109                Replaced = (iterMap->second.find(Index) != iterMap->second.end());
110                iterMap->second[Index] = privateEntry;
111                InstrCount = iterMap->second.size();
112            } else { // no such map
113                midiMapsMutex.Unlock();
114                EngineFactory::Destroy(pEngine);
115                throw Exception("There is no MIDI instrument map " + ToString(Map));
116            }
117            midiMapsMutex.Unlock();
118          EngineFactory::Destroy(pEngine);          EngineFactory::Destroy(pEngine);
119            
120            if (Replaced) {
121                int Bank = (int(Index.midi_bank_msb) << 7) & int(Index.midi_bank_lsb);
122                LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_info, Map, Bank, Index.midi_prog));
123            } else {
124                LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, Map, InstrCount));
125            }
126      }      }
127    
128      void MidiInstrumentMapper::RemoveMapping(midi_prog_index_t Index) {      void MidiInstrumentMapper::RemoveEntry(int Map, midi_prog_index_t Index) {
129          midiMapMutex.Lock();          int InstrCount = -1;
130          midiMap.erase(Index);  
131          midiMapMutex.Unlock();          midiMapsMutex.Lock();
132            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
133            if (iterMap != midiMaps.end()) { // map found
134                iterMap->second.erase(Index); // remove entry
135                InstrCount = iterMap->second.size();
136            }
137            midiMapsMutex.Unlock();
138            
139            if (InstrCount != -1) {
140                LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, Map, InstrCount));
141            }
142      }      }
143    
144      void MidiInstrumentMapper::RemoveAllMappings() {      void MidiInstrumentMapper::RemoveAllEntries(int Map) {
145          midiMapMutex.Lock();          int InstrCount = -1;
146          midiMap.clear();  
147          midiMapMutex.Unlock();          midiMapsMutex.Lock();
148            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
149            if (iterMap != midiMaps.end()) { // map found
150                iterMap->second.clear(); // clear that map
151                InstrCount = 0;
152            }
153            midiMapsMutex.Unlock();
154            
155            if (InstrCount != -1) {
156                LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, Map, InstrCount));
157            }
158      }      }
159    
160      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) {
161          std::map<midi_prog_index_t,entry_t> result;          std::map<midi_prog_index_t,entry_t> result;
162    
163          // copy the internal map first          // copy the internal map first
164          midiMapMutex.Lock();          midiMapsMutex.Lock();
165          for (std::map<midi_prog_index_t,private_entry_t>::iterator iter = midiMap.begin();          std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
166               iter != midiMap.end(); iter++)          if (iterMap == midiMaps.end()) { // no such map
167                midiMapsMutex.Unlock();
168                throw Exception("There is no MIDI instrument map " + ToString(Map));
169            }
170            for (std::map<midi_prog_index_t,private_entry_t>::iterator iterEntry = iterMap->second.begin();
171                 iterEntry != iterMap->second.end(); iterEntry++)
172          {          {
173              entry_t entry;              entry_t entry;
174              entry.EngineName      = iter->second.EngineName;              entry.EngineName      = iterEntry->second.EngineName;
175              entry.InstrumentFile  = iter->second.InstrumentFile;              entry.InstrumentFile  = iterEntry->second.InstrumentFile;
176              entry.InstrumentIndex = iter->second.InstrumentIndex;              entry.InstrumentIndex = iterEntry->second.InstrumentIndex;
177              entry.Volume          = iter->second.Volume;              entry.Volume          = iterEntry->second.Volume;
178              entry.Name            = iter->second.Name;              entry.Name            = iterEntry->second.Name;
179              result[iter->first] = entry;              result[iterEntry->first] = entry;
180          }          }
181          midiMapMutex.Unlock();          midiMapsMutex.Unlock();
182    
183          // complete it with current LoadMode of each entry          // complete it with current LoadMode of each entry
184          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();
185               iter != result.end(); iter++)               iter != result.end(); iter++)
# Line 122  namespace LinuxSampler { Line 187  namespace LinuxSampler {
187              entry_t& entry = iter->second;              entry_t& entry = iter->second;
188              Engine* pEngine = EngineFactory::Create(entry.EngineName);              Engine* pEngine = EngineFactory::Create(entry.EngineName);
189              if (!pEngine) { // invalid mapping              if (!pEngine) { // invalid mapping
190                  RemoveMapping(iter->first);                  RemoveEntry(Map, iter->first);
191                  result.erase(iter);                  result.erase(iter);
192                  continue;                  continue;
193              }              }
# Line 141  namespace LinuxSampler { Line 206  namespace LinuxSampler {
206          return result;          return result;
207      }      }
208    
209      optional<MidiInstrumentMapper::entry_t> MidiInstrumentMapper::GetEntry(midi_prog_index_t Index) {      std::vector<int> MidiInstrumentMapper::Maps() {
210            std::vector<int> result;
211            midiMapsMutex.Lock();
212            for (std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.begin();
213                 iterMap != midiMaps.end(); iterMap++)
214            {
215                result.push_back(iterMap->first);
216            }
217            midiMapsMutex.Unlock();
218            return result;
219        }
220    
221        int MidiInstrumentMapper::AddMap(String MapName) throw (Exception) {
222            int ID;
223            midiMapsMutex.Lock();
224            if (midiMaps.empty()) ID = 0;
225            else {
226                // get the highest existing map ID
227                uint lastIndex = (--(midiMaps.end()))->first;
228                // check if we reached the index limit
229                if (lastIndex + 1 < lastIndex) {
230                    // search for an unoccupied map ID starting from 0
231                    for (uint i = 0; i < lastIndex; i++) {
232                        if (midiMaps.find(i) != midiMaps.end()) continue;
233                        // we found an unused ID, so insert the new map there
234                        ID = i;
235                        goto __create_map;
236                    }
237                    throw Exception("Internal error: could not find unoccupied MIDI instrument map ID.");
238                }
239                ID = lastIndex + 1;
240            }
241            __create_map:
242            midiMaps[ID].name = MapName;
243            midiMapsMutex.Unlock();
244    
245            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, Maps().size()));
246            return ID;
247        }
248    
249        String MidiInstrumentMapper::MapName(int Map) throw (Exception) {
250            String result;
251            midiMapsMutex.Lock();
252            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
253            if (iterMap == midiMaps.end()) {
254                midiMapsMutex.Unlock();
255                throw Exception("There is no MIDI instrument map " + ToString(Map));
256            }
257            result = iterMap->second.name;
258            midiMapsMutex.Unlock();
259            return result;
260        }
261    
262        void MidiInstrumentMapper::RenameMap(int Map, String NewName) throw (Exception) {
263            midiMapsMutex.Lock();
264            std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
265            if (iterMap == midiMaps.end()) {
266                midiMapsMutex.Unlock();
267                throw Exception("There is no MIDI instrument map " + ToString(Map));
268            }
269            iterMap->second.name = NewName;
270            midiMapsMutex.Unlock();
271            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_info, Map));
272        }
273    
274        void MidiInstrumentMapper::RemoveMap(int Map) {
275            midiMapsMutex.Lock();
276            midiMaps.erase(Map);
277            midiMapsMutex.Unlock();
278            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, Maps().size()));
279        }
280    
281        void MidiInstrumentMapper::RemoveAllMaps() {
282            midiMapsMutex.Lock();
283            midiMaps.clear();
284            midiMapsMutex.Unlock();
285            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, Maps().size()));
286        }
287    
288        optional<MidiInstrumentMapper::entry_t> MidiInstrumentMapper::GetEntry(int Map, midi_prog_index_t Index) {
289          optional<entry_t> result;          optional<entry_t> result;
290          midiMapMutex.Lock();          midiMapsMutex.Lock();
291          std::map<midi_prog_index_t,private_entry_t>::iterator iter = midiMap.find(Index);          std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
292          if (iter != midiMap.end()) {          if (iterMap != midiMaps.end()) { // map found
293              entry_t entry;              std::map<midi_prog_index_t,private_entry_t>::iterator iterEntry = iterMap->second.find(Index);
294              entry.EngineName      = iter->second.EngineName;              if (iterEntry != iterMap->second.end()) {
295              entry.InstrumentFile  = iter->second.InstrumentFile;                  entry_t entry;
296              entry.InstrumentIndex = iter->second.InstrumentIndex;                  entry.EngineName      = iterEntry->second.EngineName;
297              entry.Volume          = iter->second.Volume;                  entry.InstrumentFile  = iterEntry->second.InstrumentFile;
298              //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;
299              result = entry;                  entry.Volume          = iterEntry->second.Volume;
300                    //TODO: for now we skip the LoadMode and Name entry here, since we don't need it in the MidiInputPort
301                    result = entry;
302                }
303          }          }
304          midiMapMutex.Unlock();          midiMapsMutex.Unlock();
305          return result;          return result;
306      }      }
307    

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

  ViewVC Help
Powered by ViewVC