/[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 947 - (show annotations) (download)
Mon Nov 27 21:34:55 2006 UTC (17 years, 4 months ago) by schoenebeck
File size: 8012 byte(s)
* implemented MIDI instrument mapping according to latest LSCP draft

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 String Name;
35 };
36
37 // here we store all mappings (MIDI bank&prog) -> (Engine,File,Index)
38 std::map<midi_prog_index_t,private_entry_t> midiMap;
39
40 // for synchronization of midiMap
41 Mutex midiMapMutex;
42
43
44 void MidiInstrumentMapper::AddOrReplaceMapping(midi_prog_index_t Index, entry_t Entry, bool bInBackground) throw (Exception) {
45 if (bInBackground) {
46 dmsg(3,("MidiInstrumentMapper: updating mapping (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d in background\n",
47 Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
48 Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
49 Entry.Volume,Entry.LoadMode)
50 );
51 } else {
52 dmsg(3,("MidiInstrumentMapper: updating mapping (%d,%d,%d) -> ('%s','%s',%d) with vol=%f, mode=%d\n",
53 Index.midi_bank_msb,Index.midi_bank_lsb,Index.midi_prog,
54 Entry.EngineName.c_str(),Entry.InstrumentFile.c_str(),Entry.InstrumentIndex,
55 Entry.Volume,Entry.LoadMode)
56 );
57 }
58 if (Entry.Volume < 0.0)
59 throw Exception("Volume may not be a negative value");
60 Engine* pEngine = EngineFactory::Create(Entry.EngineName);
61 if (!pEngine)
62 throw Exception("No such engine type '"+Entry.EngineName+"'");
63 Entry.EngineName = pEngine->EngineName(); // make sure to use the official engine name
64 if (pEngine->GetInstrumentManager()) {
65 InstrumentManager::instrument_id_t id;
66 id.FileName = Entry.InstrumentFile;
67 id.Index = Entry.InstrumentIndex;
68 if (Entry.LoadMode != VOID) {
69 if (bInBackground)
70 pEngine->GetInstrumentManager()->SetModeInBackground(id, static_cast<InstrumentManager::mode_t>(Entry.LoadMode));
71 else
72 pEngine->GetInstrumentManager()->SetMode(id, static_cast<InstrumentManager::mode_t>(Entry.LoadMode));
73 }
74 pEngine->GetInstrumentManager()->SetVolume(id, Entry.Volume);
75 } else {
76 dmsg(1,("WARNING: no InstrumentManager for engine '%s'\n",Entry.EngineName.c_str()));
77 }
78 private_entry_t privateEntry;
79 privateEntry.EngineName = Entry.EngineName;
80 privateEntry.InstrumentFile = Entry.InstrumentFile;
81 privateEntry.InstrumentIndex = Entry.InstrumentIndex;
82 privateEntry.Name = Entry.Name;
83 midiMapMutex.Lock();
84 midiMap[Index] = privateEntry;
85 midiMapMutex.Unlock();
86 EngineFactory::Destroy(pEngine);
87 }
88
89 void MidiInstrumentMapper::RemoveMapping(midi_prog_index_t Index) {
90 midiMapMutex.Lock();
91 midiMap.erase(Index);
92 midiMapMutex.Unlock();
93 }
94
95 void MidiInstrumentMapper::RemoveAllMappings() {
96 midiMapMutex.Lock();
97 midiMap.clear();
98 midiMapMutex.Unlock();
99 }
100
101 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> MidiInstrumentMapper::Mappings() {
102 std::map<midi_prog_index_t,entry_t> result;
103 // copy the internal map first
104 midiMapMutex.Lock();
105 for (std::map<midi_prog_index_t,private_entry_t>::iterator iter = midiMap.begin();
106 iter != midiMap.end(); iter++)
107 {
108 entry_t entry;
109 entry.EngineName = iter->second.EngineName;
110 entry.InstrumentFile = iter->second.InstrumentFile;
111 entry.InstrumentIndex = iter->second.InstrumentIndex;
112 entry.Name = iter->second.Name;
113 result[iter->first] = entry;
114 }
115 midiMapMutex.Unlock();
116 // complete it with current LoadMode & Volume of each entry
117 for (std::map<midi_prog_index_t,entry_t>::iterator iter = result.begin();
118 iter != result.end(); iter++)
119 {
120 entry_t& entry = iter->second;
121 Engine* pEngine = EngineFactory::Create(entry.EngineName);
122 if (!pEngine) { // invalid mapping
123 RemoveMapping(iter->first);
124 result.erase(iter);
125 continue;
126 }
127 InstrumentManager* pManager = pEngine->GetInstrumentManager();
128 if (pManager) { // engine provides an InstrumentManager
129 InstrumentManager::instrument_id_t id;
130 id.FileName = entry.InstrumentFile;
131 id.Index = entry.InstrumentIndex;
132 entry.LoadMode = static_cast<mode_t>(pManager->GetMode(id));
133 entry.Volume = pManager->GetVolume(id);
134 } else { // engine does not provide an InstrumentManager
135 // use default values
136 entry.LoadMode = ON_DEMAND;
137 entry.Volume = 1.0f;
138 }
139 EngineFactory::Destroy(pEngine);
140 }
141 return result;
142 }
143
144 optional<MidiInstrumentMapper::entry_t> MidiInstrumentMapper::GetEntry(midi_prog_index_t Index) {
145 optional<entry_t> result;
146 midiMapMutex.Lock();
147 std::map<midi_prog_index_t,private_entry_t>::iterator iter = midiMap.find(Index);
148 if (iter != midiMap.end()) {
149 entry_t entry;
150 entry.EngineName = iter->second.EngineName;
151 entry.InstrumentFile = iter->second.InstrumentFile;
152 entry.InstrumentIndex = iter->second.InstrumentIndex;
153 Engine* pEngine = EngineFactory::Create(iter->second.EngineName);
154 // try to retrieve volume from InstrumentManager entry
155 if (pEngine && pEngine->GetInstrumentManager()) {
156 InstrumentManager::instrument_id_t id;
157 id.FileName = iter->second.InstrumentFile;
158 id.Index = iter->second.InstrumentIndex;
159 entry.Volume = pEngine->GetInstrumentManager()->GetVolume(id);
160 } else entry.Volume = 1.0f; // default value
161 if (pEngine) EngineFactory::Destroy(pEngine);
162 //TODO: for now we skip the LoadMode and Name entry here, since we don't need it in the MidiInputPort
163 result = entry;
164 }
165 midiMapMutex.Unlock();
166 return result;
167 }
168
169 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC