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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /***************************************************************************
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 float Volume;
35 String Name;
36 };
37
38 // 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
44 // here we store all maps
45 std::map<int,MidiInstrumentMap> midiMaps;
46
47 // for synchronization of midiMaps
48 Mutex midiMapsMutex;
49
50
51 void MidiInstrumentMapper::AddOrReplaceEntry(int Map, midi_prog_index_t Index, entry_t Entry, bool bInBackground) throw (Exception) {
52 if (bInBackground) {
53 dmsg(3,("MidiInstrumentMapper: updating mapping %d (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d in background\n",
54 Map,
55 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 dmsg(3,("MidiInstrumentMapper: updating mapping %d (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d\n",
61 Map,
62 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 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 if (!Entry.InstrumentFile.size())
74 throw Exception("No instrument file name given");
75 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 privateEntry.Volume = Entry.Volume;
99 privateEntry.Name = Entry.Name;
100 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 EngineFactory::Destroy(pEngine);
111 }
112
113 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 }
121
122 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 }
130
131 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> MidiInstrumentMapper::Entries(int Map) throw (Exception) {
132 std::map<midi_prog_index_t,entry_t> result;
133
134 // copy the internal map first
135 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 {
144 entry_t entry;
145 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 }
152 midiMapsMutex.Unlock();
153
154 // complete it with current LoadMode of each entry
155 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 RemoveEntry(Map, iter->first);
162 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 // use default value
173 entry.LoadMode = ON_DEMAND;
174 }
175 EngineFactory::Destroy(pEngine);
176 }
177 return result;
178 }
179
180 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 ID = lastIndex + 1;
211 }
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 optional<entry_t> result;
256 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 }
270 midiMapsMutex.Unlock();
271 return result;
272 }
273
274 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC