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

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     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