--- linuxsampler/trunk/src/drivers/midi/MidiInstrumentMapper.cpp 2006/12/10 17:07:02 972 +++ linuxsampler/trunk/src/drivers/midi/MidiInstrumentMapper.cpp 2006/12/15 21:40:27 973 @@ -35,27 +35,41 @@ String Name; }; - // here we store all mappings (MIDI bank&prog) -> (Engine,File,Index) - std::map midiMap; + // internal map type (MIDI bank&prog) -> (Engine,File,Index) + class MidiInstrumentMap : public std::map { + public: + String name; + }; + + // here we store all maps + std::map midiMaps; - // for synchronization of midiMap - Mutex midiMapMutex; + // for synchronization of midiMaps + Mutex midiMapsMutex; - 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) { if (bInBackground) { - 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", + Map, Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog, Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex, Entry.Volume,Entry.LoadMode) ); } else { - 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", + Map, Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog, Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex, Entry.Volume,Entry.LoadMode) ); } + midiMapsMutex.Lock(); + if (midiMaps.empty()) { + midiMapsMutex.Unlock(); + throw Exception("There is no MIDI instrument map, you have to add one first."); + } + midiMapsMutex.Unlock(); if (!Entry.InstrumentFile.size()) throw Exception("No instrument file name given"); if (Entry.Volume < 0.0) @@ -83,40 +97,60 @@ privateEntry.InstrumentIndex = Entry.InstrumentIndex; privateEntry.Volume = Entry.Volume; privateEntry.Name = Entry.Name; - midiMapMutex.Lock(); - midiMap[Index] = privateEntry; - midiMapMutex.Unlock(); + midiMapsMutex.Lock(); + std::map::iterator iterMap = midiMaps.find(Map); + if (iterMap != midiMaps.end()) { // map found + iterMap->second[Index] = privateEntry; + } else { // no such map + midiMapsMutex.Unlock(); + EngineFactory::Destroy(pEngine); + throw Exception("There is no MIDI instrument map " + ToString(Map)); + } + midiMapsMutex.Unlock(); EngineFactory::Destroy(pEngine); } - void MidiInstrumentMapper::RemoveMapping(midi_prog_index_t Index) { - midiMapMutex.Lock(); - midiMap.erase(Index); - midiMapMutex.Unlock(); + void MidiInstrumentMapper::RemoveEntry(int Map, midi_prog_index_t Index) { + midiMapsMutex.Lock(); + std::map::iterator iterMap = midiMaps.find(Map); + if (iterMap != midiMaps.end()) { // map found + iterMap->second.erase(Index); // remove entry + } + midiMapsMutex.Unlock(); } - void MidiInstrumentMapper::RemoveAllMappings() { - midiMapMutex.Lock(); - midiMap.clear(); - midiMapMutex.Unlock(); + void MidiInstrumentMapper::RemoveAllEntries(int Map) { + midiMapsMutex.Lock(); + std::map::iterator iterMap = midiMaps.find(Map); + if (iterMap != midiMaps.end()) { // map found + iterMap->second.clear(); // clear that map + } + midiMapsMutex.Unlock(); } - std::map MidiInstrumentMapper::Mappings() { + std::map MidiInstrumentMapper::Entries(int Map) throw (Exception) { std::map result; + // copy the internal map first - midiMapMutex.Lock(); - for (std::map::iterator iter = midiMap.begin(); - iter != midiMap.end(); iter++) + midiMapsMutex.Lock(); + std::map::iterator iterMap = midiMaps.find(Map); + if (iterMap == midiMaps.end()) { // no such map + midiMapsMutex.Unlock(); + throw Exception("There is no MIDI instrument map " + ToString(Map)); + } + for (std::map::iterator iterEntry = iterMap->second.begin(); + iterEntry != iterMap->second.end(); iterEntry++) { entry_t entry; - entry.EngineName = iter->second.EngineName; - entry.InstrumentFile = iter->second.InstrumentFile; - entry.InstrumentIndex = iter->second.InstrumentIndex; - entry.Volume = iter->second.Volume; - entry.Name = iter->second.Name; - result[iter->first] = entry; + entry.EngineName = iterEntry->second.EngineName; + entry.InstrumentFile = iterEntry->second.InstrumentFile; + entry.InstrumentIndex = iterEntry->second.InstrumentIndex; + entry.Volume = iterEntry->second.Volume; + entry.Name = iterEntry->second.Name; + result[iterEntry->first] = entry; } - midiMapMutex.Unlock(); + midiMapsMutex.Unlock(); + // complete it with current LoadMode of each entry for (std::map::iterator iter = result.begin(); iter != result.end(); iter++) @@ -124,7 +158,7 @@ entry_t& entry = iter->second; Engine* pEngine = EngineFactory::Create(entry.EngineName); if (!pEngine) { // invalid mapping - RemoveMapping(iter->first); + RemoveEntry(Map, iter->first); result.erase(iter); continue; } @@ -143,20 +177,97 @@ return result; } - optional MidiInstrumentMapper::GetEntry(midi_prog_index_t Index) { + std::vector MidiInstrumentMapper::Maps() { + std::vector result; + midiMapsMutex.Lock(); + for (std::map::iterator iterMap = midiMaps.begin(); + iterMap != midiMaps.end(); iterMap++) + { + result.push_back(iterMap->first); + } + midiMapsMutex.Unlock(); + return result; + } + + int MidiInstrumentMapper::AddMap(String MapName) throw (Exception) { + int ID; + midiMapsMutex.Lock(); + if (midiMaps.empty()) ID = 0; + else { + // get the highest existing map ID + uint lastIndex = (--(midiMaps.end()))->first; + // check if we reached the index limit + if (lastIndex + 1 < lastIndex) { + // search for an unoccupied map ID starting from 0 + for (uint i = 0; i < lastIndex; i++) { + if (midiMaps.find(i) != midiMaps.end()) continue; + // we found an unused ID, so insert the new map there + ID = i; + goto __create_map; + } + throw Exception("Internal error: could not find unoccupied MIDI instrument map ID."); + } + ID = lastIndex; + } + __create_map: + midiMaps[ID].name = MapName; + midiMapsMutex.Unlock(); + return ID; + } + + String MidiInstrumentMapper::MapName(int Map) throw (Exception) { + String result; + midiMapsMutex.Lock(); + std::map::iterator iterMap = midiMaps.find(Map); + if (iterMap == midiMaps.end()) { + midiMapsMutex.Unlock(); + throw Exception("There is no MIDI instrument map " + ToString(Map)); + } + result = iterMap->second.name; + midiMapsMutex.Unlock(); + return result; + } + + void MidiInstrumentMapper::RenameMap(int Map, String NewName) throw (Exception) { + midiMapsMutex.Lock(); + std::map::iterator iterMap = midiMaps.find(Map); + if (iterMap == midiMaps.end()) { + midiMapsMutex.Unlock(); + throw Exception("There is no MIDI instrument map " + ToString(Map)); + } + iterMap->second.name = NewName; + midiMapsMutex.Unlock(); + } + + void MidiInstrumentMapper::RemoveMap(int Map) { + midiMapsMutex.Lock(); + midiMaps.erase(Map); + midiMapsMutex.Unlock(); + } + + void MidiInstrumentMapper::RemoveAllMaps() { + midiMapsMutex.Lock(); + midiMaps.clear(); + midiMapsMutex.Unlock(); + } + + optional MidiInstrumentMapper::GetEntry(int Map, midi_prog_index_t Index) { optional result; - midiMapMutex.Lock(); - std::map::iterator iter = midiMap.find(Index); - if (iter != midiMap.end()) { - entry_t entry; - entry.EngineName = iter->second.EngineName; - entry.InstrumentFile = iter->second.InstrumentFile; - entry.InstrumentIndex = iter->second.InstrumentIndex; - entry.Volume = iter->second.Volume; - //TODO: for now we skip the LoadMode and Name entry here, since we don't need it in the MidiInputPort - result = entry; + midiMapsMutex.Lock(); + std::map::iterator iterMap = midiMaps.find(Map); + if (iterMap != midiMaps.end()) { // map found + std::map::iterator iterEntry = iterMap->second.find(Index); + if (iterEntry != iterMap->second.end()) { + entry_t entry; + entry.EngineName = iterEntry->second.EngineName; + entry.InstrumentFile = iterEntry->second.InstrumentFile; + entry.InstrumentIndex = iterEntry->second.InstrumentIndex; + entry.Volume = iterEntry->second.Volume; + //TODO: for now we skip the LoadMode and Name entry here, since we don't need it in the MidiInputPort + result = entry; + } } - midiMapMutex.Unlock(); + midiMapsMutex.Unlock(); return result; }