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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 976 - (hide annotations) (download)
Sun Dec 17 10:43:22 2006 UTC (13 years, 11 months ago) by iliev
File size: 11876 byte(s)
* fixed bug on adding MIDI instrument maps

1 schoenebeck 947 /***************************************************************************
2     * *
3     * Copyright (C) 2006 Christian Schoenebeck *
4     * *
5     * 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 *
7     * the Free Software Foundation; either version 2 of the License, or *
8     * (at your option) any later version. *
9     * *
10     * This library is distributed in the hope that it will be useful, *
11     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13     * GNU General Public License for more details. *
14     * *
15     * You should have received a copy of the GNU General Public License *
16     * along with this library; if not, write to the Free Software *
17     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
18     * MA 02111-1307 USA *
19     ***************************************************************************/
20    
21     #include "MidiInstrumentMapper.h"
22    
23     #include "../../common/Mutex.h"
24     #include "../../engines/EngineFactory.h"
25     #include "../../engines/Engine.h"
26    
27     namespace LinuxSampler {
28    
29     // same as entry_t but without 'LoadMode'
30     struct private_entry_t {
31     String EngineName;
32     String InstrumentFile;
33     uint InstrumentIndex;
34 schoenebeck 958 float Volume;
35 schoenebeck 947 String Name;
36     };
37    
38 schoenebeck 973 // internal map type (MIDI bank&prog) -> (Engine,File,Index)
39     class MidiInstrumentMap : public std::map<midi_prog_index_t,private_entry_t> {
40     public:
41     String name;
42     };
43 schoenebeck 947
44 schoenebeck 973 // here we store all maps
45     std::map<int,MidiInstrumentMap> midiMaps;
46 schoenebeck 947
47 schoenebeck 973 // for synchronization of midiMaps
48     Mutex midiMapsMutex;
49 schoenebeck 947
50 schoenebeck 973
51     void MidiInstrumentMapper::AddOrReplaceEntry(int Map, midi_prog_index_t Index, entry_t Entry, bool bInBackground) throw (Exception) {
52 schoenebeck 947 if (bInBackground) {
53 schoenebeck 973 dmsg(3,("MidiInstrumentMapper: updating mapping %d (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d in background\n",
54     Map,
55 schoenebeck 947 Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
56     Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
57     Entry.Volume,Entry.LoadMode)
58     );
59     } else {
60 schoenebeck 973 dmsg(3,("MidiInstrumentMapper: updating mapping %d (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d\n",
61     Map,
62 schoenebeck 947 Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
63     Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
64     Entry.Volume,Entry.LoadMode)
65     );
66     }
67 schoenebeck 973 midiMapsMutex.Lock();
68     if (midiMaps.empty()) {
69     midiMapsMutex.Unlock();
70     throw Exception("There is no MIDI instrument map, you have to add one first.");
71     }
72     midiMapsMutex.Unlock();
73 schoenebeck 970 if (!Entry.InstrumentFile.size())
74     throw Exception("No instrument file name given");
75 schoenebeck 947 if (Entry.Volume < 0.0)
76     throw Exception("Volume may not be a negative value");
77     Engine* pEngine = EngineFactory::Create(Entry.EngineName);
78     if (!pEngine)
79     throw Exception("No such engine type '"+Entry.EngineName+"'");
80     Entry.EngineName = pEngine->EngineName(); // make sure to use the official engine name
81     if (pEngine->GetInstrumentManager()) {
82     InstrumentManager::instrument_id_t id;
83     id.FileName = Entry.InstrumentFile;
84     id.Index = Entry.InstrumentIndex;
85     if (Entry.LoadMode != VOID) {
86     if (bInBackground)
87     pEngine->GetInstrumentManager()->SetModeInBackground(id, static_cast<InstrumentManager::mode_t>(Entry.LoadMode));
88     else
89     pEngine->GetInstrumentManager()->SetMode(id, static_cast<InstrumentManager::mode_t>(Entry.LoadMode));
90     }
91     } else {
92     dmsg(1,("WARNING: no InstrumentManager for engine '%s'\n",Entry.EngineName.c_str()));
93     }
94     private_entry_t privateEntry;
95     privateEntry.EngineName = Entry.EngineName;
96     privateEntry.InstrumentFile = Entry.InstrumentFile;
97     privateEntry.InstrumentIndex = Entry.InstrumentIndex;
98 schoenebeck 958 privateEntry.Volume = Entry.Volume;
99 schoenebeck 947 privateEntry.Name = Entry.Name;
100 schoenebeck 973 midiMapsMutex.Lock();
101     std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
102     if (iterMap != midiMaps.end()) { // map found
103     iterMap->second[Index] = privateEntry;
104     } else { // no such map
105     midiMapsMutex.Unlock();
106     EngineFactory::Destroy(pEngine);
107     throw Exception("There is no MIDI instrument map " + ToString(Map));
108     }
109     midiMapsMutex.Unlock();
110 schoenebeck 947 EngineFactory::Destroy(pEngine);
111     }
112    
113 schoenebeck 973 void MidiInstrumentMapper::RemoveEntry(int Map, midi_prog_index_t Index) {
114     midiMapsMutex.Lock();
115     std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
116     if (iterMap != midiMaps.end()) { // map found
117     iterMap->second.erase(Index); // remove entry
118     }
119     midiMapsMutex.Unlock();
120 schoenebeck 947 }
121    
122 schoenebeck 973 void MidiInstrumentMapper::RemoveAllEntries(int Map) {
123     midiMapsMutex.Lock();
124     std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
125     if (iterMap != midiMaps.end()) { // map found
126     iterMap->second.clear(); // clear that map
127     }
128     midiMapsMutex.Unlock();
129 schoenebeck 947 }
130    
131 schoenebeck 973 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> MidiInstrumentMapper::Entries(int Map) throw (Exception) {
132 schoenebeck 947 std::map<midi_prog_index_t,entry_t> result;
133 schoenebeck 973
134 schoenebeck 947 // copy the internal map first
135 schoenebeck 973 midiMapsMutex.Lock();
136     std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
137     if (iterMap == midiMaps.end()) { // no such map
138     midiMapsMutex.Unlock();
139     throw Exception("There is no MIDI instrument map " + ToString(Map));
140     }
141     for (std::map<midi_prog_index_t,private_entry_t>::iterator iterEntry = iterMap->second.begin();
142     iterEntry != iterMap->second.end(); iterEntry++)
143 schoenebeck 947 {
144     entry_t entry;
145 schoenebeck 973 entry.EngineName = iterEntry->second.EngineName;
146     entry.InstrumentFile = iterEntry->second.InstrumentFile;
147     entry.InstrumentIndex = iterEntry->second.InstrumentIndex;
148     entry.Volume = iterEntry->second.Volume;
149     entry.Name = iterEntry->second.Name;
150     result[iterEntry->first] = entry;
151 schoenebeck 947 }
152 schoenebeck 973 midiMapsMutex.Unlock();
153    
154 schoenebeck 958 // complete it with current LoadMode of each entry
155 schoenebeck 947 for (std::map<midi_prog_index_t,entry_t>::iterator iter = result.begin();
156     iter != result.end(); iter++)
157     {
158     entry_t& entry = iter->second;
159     Engine* pEngine = EngineFactory::Create(entry.EngineName);
160     if (!pEngine) { // invalid mapping
161 schoenebeck 973 RemoveEntry(Map, iter->first);
162 schoenebeck 947 result.erase(iter);
163     continue;
164     }
165     InstrumentManager* pManager = pEngine->GetInstrumentManager();
166     if (pManager) { // engine provides an InstrumentManager
167     InstrumentManager::instrument_id_t id;
168     id.FileName = entry.InstrumentFile;
169     id.Index = entry.InstrumentIndex;
170     entry.LoadMode = static_cast<mode_t>(pManager->GetMode(id));
171     } else { // engine does not provide an InstrumentManager
172 schoenebeck 958 // use default value
173 schoenebeck 947 entry.LoadMode = ON_DEMAND;
174     }
175     EngineFactory::Destroy(pEngine);
176     }
177     return result;
178     }
179    
180 schoenebeck 973 std::vector<int> MidiInstrumentMapper::Maps() {
181     std::vector<int> result;
182     midiMapsMutex.Lock();
183     for (std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.begin();
184     iterMap != midiMaps.end(); iterMap++)
185     {
186     result.push_back(iterMap->first);
187     }
188     midiMapsMutex.Unlock();
189     return result;
190     }
191    
192     int MidiInstrumentMapper::AddMap(String MapName) throw (Exception) {
193     int ID;
194     midiMapsMutex.Lock();
195     if (midiMaps.empty()) ID = 0;
196     else {
197     // get the highest existing map ID
198     uint lastIndex = (--(midiMaps.end()))->first;
199     // check if we reached the index limit
200     if (lastIndex + 1 < lastIndex) {
201     // search for an unoccupied map ID starting from 0
202     for (uint i = 0; i < lastIndex; i++) {
203     if (midiMaps.find(i) != midiMaps.end()) continue;
204     // we found an unused ID, so insert the new map there
205     ID = i;
206     goto __create_map;
207     }
208     throw Exception("Internal error: could not find unoccupied MIDI instrument map ID.");
209     }
210 iliev 976 ID = lastIndex + 1;
211 schoenebeck 973 }
212     __create_map:
213     midiMaps[ID].name = MapName;
214     midiMapsMutex.Unlock();
215     return ID;
216     }
217    
218     String MidiInstrumentMapper::MapName(int Map) throw (Exception) {
219     String result;
220     midiMapsMutex.Lock();
221     std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
222     if (iterMap == midiMaps.end()) {
223     midiMapsMutex.Unlock();
224     throw Exception("There is no MIDI instrument map " + ToString(Map));
225     }
226     result = iterMap->second.name;
227     midiMapsMutex.Unlock();
228     return result;
229     }
230    
231     void MidiInstrumentMapper::RenameMap(int Map, String NewName) throw (Exception) {
232     midiMapsMutex.Lock();
233     std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
234     if (iterMap == midiMaps.end()) {
235     midiMapsMutex.Unlock();
236     throw Exception("There is no MIDI instrument map " + ToString(Map));
237     }
238     iterMap->second.name = NewName;
239     midiMapsMutex.Unlock();
240     }
241    
242     void MidiInstrumentMapper::RemoveMap(int Map) {
243     midiMapsMutex.Lock();
244     midiMaps.erase(Map);
245     midiMapsMutex.Unlock();
246     }
247    
248     void MidiInstrumentMapper::RemoveAllMaps() {
249     midiMapsMutex.Lock();
250     midiMaps.clear();
251     midiMapsMutex.Unlock();
252     }
253    
254     optional<MidiInstrumentMapper::entry_t> MidiInstrumentMapper::GetEntry(int Map, midi_prog_index_t Index) {
255 schoenebeck 947 optional<entry_t> result;
256 schoenebeck 973 midiMapsMutex.Lock();
257     std::map<int,MidiInstrumentMap>::iterator iterMap = midiMaps.find(Map);
258     if (iterMap != midiMaps.end()) { // map found
259     std::map<midi_prog_index_t,private_entry_t>::iterator iterEntry = iterMap->second.find(Index);
260     if (iterEntry != iterMap->second.end()) {
261     entry_t entry;
262     entry.EngineName = iterEntry->second.EngineName;
263     entry.InstrumentFile = iterEntry->second.InstrumentFile;
264     entry.InstrumentIndex = iterEntry->second.InstrumentIndex;
265     entry.Volume = iterEntry->second.Volume;
266     //TODO: for now we skip the LoadMode and Name entry here, since we don't need it in the MidiInputPort
267     result = entry;
268     }
269 schoenebeck 947 }
270 schoenebeck 973 midiMapsMutex.Unlock();
271 schoenebeck 947 return result;
272     }
273    
274     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC