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

Contents of /linuxsampler/trunk/src/drivers/Plugin.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1922 - (show annotations) (download)
Fri Jun 26 18:55:02 2009 UTC (14 years, 9 months ago) by persson
File size: 14665 byte(s)
* added channel routing, fxsends and midi maps to the settings stored
  in the plugin state

1 /***************************************************************************
2 * *
3 * Copyright (C) 2008 - 2009 Andreas Persson *
4 * *
5 * This program 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 program 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 program; if not, write to the Free Software *
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, *
18 * MA 02110-1301 USA *
19 ***************************************************************************/
20
21 #include <limits>
22 #include <sstream>
23
24 #include "Plugin.h"
25 #include "audio/AudioOutputDeviceFactory.h"
26 #include "midi/MidiInputDeviceFactory.h"
27
28 namespace LinuxSampler {
29
30 // *************** PluginGlobal ***************
31 // *
32
33 PluginGlobal::PluginGlobal() :
34 RefCount(0) {
35 // we need to remove the ASIO driver, otherwise the lscp info
36 // methods will lock up the audio device
37 AudioOutputDeviceFactory::Unregister("ASIO");
38
39 REGISTER_AUDIO_OUTPUT_DRIVER(AudioOutputDevicePlugin);
40 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDevicePlugin, ParameterActive);
41 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDevicePlugin, ParameterSampleRate);
42 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDevicePlugin, ParameterChannelsPlugin);
43 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDevicePlugin, ParameterFragmentSize);
44
45 REGISTER_MIDI_INPUT_DRIVER(MidiInputDevicePlugin);
46 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDevicePlugin, ParameterActive);
47 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDevicePlugin, ParameterPortsPlugin);
48
49 pSampler = new Sampler;
50
51 // using LOOPBACK instead of ANY to prevent windows firewall
52 // warnings
53 pLSCPServer = new LSCPServer(pSampler, htonl(INADDR_LOOPBACK),
54 htons(LSCP_PORT));
55 pLSCPServer->StartThread();
56 pLSCPServer->WaitUntilInitialized();
57
58 pEventThread = new EventThread(pSampler);
59 pEventThread->StartThread();
60 }
61
62
63 PluginGlobal::~PluginGlobal() {
64 pEventThread->StopThread();
65 pLSCPServer->StopThread();
66 pLSCPServer->RemoveListeners();
67
68 delete pEventThread;
69 delete pSampler;
70 delete pLSCPServer;
71 }
72
73
74 // *************** EventThread ***************
75 // *
76
77
78 EventThread::EventThread(Sampler* pSampler) :
79 Thread(false, false, 0, 0),
80 pSampler(pSampler) {
81 }
82
83 int EventThread::Main() {
84 for (;;) {
85 sleep(1);
86 pSampler->fireStatistics();
87 }
88 return 0;
89 }
90
91
92 // *************** Plugin ***************
93 // *
94
95 PluginGlobal* Plugin::global = 0;
96
97 Plugin::Plugin(bool bDoPreInit) :
98 pAudioDevice(0),
99 pMidiDevice(0) {
100 bPreInitDone = false;
101 if (bDoPreInit) PreInit();
102 }
103
104 void Plugin::PreInit() {
105 if (bPreInitDone) return;
106
107 bPreInitDone = true;
108 if (!global) {
109 global = new PluginGlobal;
110 }
111 global->RefCount++;
112 }
113
114 void Plugin::Init(int SampleRate, int FragmentSize, int Channels) {
115 if (pAudioDevice && SampleRate == pAudioDevice->SampleRate() &&
116 FragmentSize == pAudioDevice->MaxSamplesPerCycle()) {
117 return; // nothing has changed
118 }
119
120 String oldState;
121 if (pAudioDevice) {
122 oldState = GetState();
123 RemoveChannels();
124 global->pSampler->DestroyAudioOutputDevice(pAudioDevice);
125 }
126 std::map<String, String> params;
127 params["SAMPLERATE"] = ToString(SampleRate);
128 params["FRAGMENTSIZE"] = ToString(FragmentSize);
129 if (Channels > 0) params["CHANNELS"] = ToString(Channels);
130 pAudioDevice = dynamic_cast<AudioOutputDevicePlugin*>(
131 global->pSampler->CreateAudioOutputDevice(AudioOutputDevicePlugin::Name(), params));
132
133 if (!pMidiDevice) {
134 pMidiDevice = dynamic_cast<MidiInputDevicePlugin*>(
135 global->pSampler->CreateMidiInputDevice(MidiInputDevicePlugin::Name(),
136 std::map<String,String>()));
137 }
138
139 if (!oldState.empty()) {
140 SetState(oldState);
141 }
142 }
143
144 Plugin::~Plugin() {
145 RemoveChannels();
146 if (pAudioDevice) global->pSampler->DestroyAudioOutputDevice(pAudioDevice);
147 if (pMidiDevice) global->pSampler->DestroyMidiInputDevice(pMidiDevice);
148 if (bPreInitDone) {
149 if (--global->RefCount == 0) {
150 delete global;
151 global = 0;
152 }
153 }
154 }
155
156 void Plugin::InitState() {
157 SamplerChannel* channel = global->pSampler->AddSamplerChannel();
158 channel->SetEngineType("gig");
159 channel->SetAudioOutputDevice(pAudioDevice);
160 channel->SetMidiInputDevice(pMidiDevice);
161 channel->SetMidiInputChannel(midi_chan_1);
162 }
163
164 /*
165 The sampler state is stored in a text base format, designed to
166 be easy to parse with the istream >> operator. Values are
167 separated by spaces or newlines. All string values that may
168 contain spaces end with a newline.
169
170 The first line contains the global volume.
171
172 The rest of the lines have an integer first representing the
173 type of information on the line, except for the two lines that
174 describe each sampler channel. The first of these two starts
175 with an integer from 0 to 16 (the midi channel for the sampler
176 channel).
177
178 Note that we should try to keep the parsing of this format both
179 backwards and forwards compatible between versions. The parser
180 ignores lines with unknown type integers and accepts that new
181 types are missing.
182 */
183
184 enum {
185 FXSEND = 17,
186 MIDIMAP,
187 MIDIMAPPING,
188 DEFAULTMIDIMAP
189 };
190
191 String Plugin::GetState() {
192 std::stringstream s;
193
194 s << GLOBAL_VOLUME << '\n';
195
196 std::vector<int> maps = MidiInstrumentMapper::Maps();
197 for (int i = 0 ; i < maps.size() ; i++) {
198 s << MIDIMAP << ' ' <<
199 maps[i] << ' ' <<
200 MidiInstrumentMapper::MapName(maps[i]) << '\n';
201
202 std::map<midi_prog_index_t, MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
203 for (std::map<midi_prog_index_t, MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin() ;
204 iter != mappings.end(); iter++) {
205 s << MIDIMAPPING << ' ' <<
206 ((int(iter->first.midi_bank_msb) << 7) |
207 int(iter->first.midi_bank_lsb)) << ' ' <<
208 int(iter->first.midi_prog) << ' ' <<
209 iter->second.EngineName << ' ' <<
210 iter->second.InstrumentFile << '\n' <<
211 MIDIMAPPING << ' ' <<
212 iter->second.InstrumentIndex << ' ' <<
213 iter->second.Volume << ' ' <<
214 iter->second.LoadMode << ' ' <<
215 iter->second.Name << '\n';
216 }
217 }
218 if (maps.size()) {
219 s << DEFAULTMIDIMAP << ' ' <<
220 MidiInstrumentMapper::GetDefaultMap() << '\n';
221 }
222
223 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
224 for (std::map<uint, SamplerChannel*>::iterator iter = channels.begin() ;
225 iter != channels.end() ; iter++) {
226 SamplerChannel* channel = iter->second;
227 if (channel->GetAudioOutputDevice() == pAudioDevice) {
228 EngineChannel* engine_channel = channel->GetEngineChannel();
229 String filename = engine_channel->InstrumentFileName();
230 s << channel->GetMidiInputChannel() << ' ' <<
231 engine_channel->Volume() << ' ' <<
232 filename << '\n' <<
233 engine_channel->InstrumentIndex() << ' ' <<
234 engine_channel->GetSolo() << ' ' <<
235 (engine_channel->GetMute() == 1) << ' ' <<
236 engine_channel->OutputChannel(0) << ' ' <<
237 engine_channel->OutputChannel(1) << ' ' <<
238 (engine_channel->UsesNoMidiInstrumentMap() ? -2 :
239 (engine_channel->UsesDefaultMidiInstrumentMap() ? -1 :
240 engine_channel->GetMidiInstrumentMap())) << '\n';
241
242 for (int i = 0 ; i < engine_channel->GetFxSendCount() ; i++) {
243 FxSend* fxsend = engine_channel->GetFxSend(i);
244 s << FXSEND << ' ' <<
245 fxsend->Level() << ' ' <<
246 int(fxsend->MidiController()) << ' ' <<
247 fxsend->DestinationChannel(0) << ' ' <<
248 fxsend->DestinationChannel(1) << ' ' <<
249 fxsend->Name() << '\n';
250 }
251 }
252 }
253 return s.str();
254 }
255
256 void Plugin::RemoveChannels() {
257 if(global == NULL) return;
258
259 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
260
261 for (std::map<uint, SamplerChannel*>::iterator iter = channels.begin() ;
262 iter != channels.end() ; iter++) {
263 if (iter->second->GetAudioOutputDevice() == pAudioDevice) {
264 global->pSampler->RemoveSamplerChannel(iter->second);
265 }
266 }
267 }
268
269 bool Plugin::SetState(String State) {
270 RemoveChannels();
271 MidiInstrumentMapper::RemoveAllMaps();
272
273 std::stringstream s(State);
274 s >> GLOBAL_VOLUME;
275
276 EngineChannel* engine_channel;
277 int midiMapId;
278 std::map<int, int> oldToNewId;
279 int type;
280 while (s >> type) {
281
282 if (type <= 16) { // sampler channel
283 int midiChannel = type;
284 float volume;
285 s >> volume;
286 s.ignore();
287 String filename;
288 std::getline(s, filename);
289 int index;
290 bool solo;
291 bool mute;
292 s >> index >> solo >> mute;
293
294 SamplerChannel* channel = global->pSampler->AddSamplerChannel();
295 channel->SetEngineType("gig");
296 channel->SetAudioOutputDevice(pAudioDevice);
297 channel->SetMidiInputDevice(pMidiDevice);
298 channel->SetMidiInputChannel(midi_chan_t(midiChannel));
299
300 engine_channel = channel->GetEngineChannel();
301 engine_channel->Volume(volume);
302 if (s.get() == ' ') {
303 int left;
304 int right;
305 int oldMapId;
306 s >> left >> right >> oldMapId;
307 engine_channel->SetOutputChannel(0, left);
308 engine_channel->SetOutputChannel(1, right);
309
310 if (oldMapId == -1) {
311 engine_channel->SetMidiInstrumentMapToDefault();
312 } else if (oldMapId >= 0) {
313 engine_channel->SetMidiInstrumentMap(oldToNewId[oldMapId]);
314 }
315 // skip rest of line
316 s.ignore(std::numeric_limits<int>::max(), '\n');
317 }
318 if (!filename.empty() && index != -1) {
319 InstrumentManager::instrument_id_t id;
320 id.FileName = filename;
321 id.Index = index;
322 InstrumentManager::LoadInstrumentInBackground(id, engine_channel);
323 }
324 if (solo) engine_channel->SetSolo(solo);
325 if (mute) engine_channel->SetMute(1);
326
327 } else if (type == FXSEND) {
328 float level;
329 int controller;
330 int fxleft;
331 int fxright;
332 String name;
333
334 s >> level >> controller >> fxleft >> fxright;
335 s.ignore();
336 std::getline(s, name);
337 FxSend* send = engine_channel->AddFxSend(controller, name);
338 send->SetLevel(level);
339 send->SetDestinationChannel(0, fxleft);
340 send->SetDestinationChannel(1, fxright);
341
342 } else if (type == MIDIMAP) {
343 int oldId;
344 s >> oldId;
345 String name;
346 s.ignore();
347 std::getline(s, name);
348 midiMapId = MidiInstrumentMapper::AddMap(name);
349 oldToNewId[oldId] = midiMapId;
350
351 } else if (type == MIDIMAPPING) {
352 int bank;
353 int prog;
354 String engine;
355 String file;
356 int index;
357 float volume;
358 int loadmode;
359 String name;
360
361 s >> bank >> prog >> engine;
362 s.ignore();
363 std::getline(s, file);
364 s >> type >> index >> volume >> loadmode;
365 s.ignore();
366 std::getline(s, name);
367
368 global->pLSCPServer->AddOrReplaceMIDIInstrumentMapping(
369 midiMapId, bank, prog, engine, file, index, volume,
370 MidiInstrumentMapper::mode_t(loadmode), name, false);
371
372 } else if (type == DEFAULTMIDIMAP) {
373 int oldId;
374 s >> oldId;
375 MidiInstrumentMapper::SetDefaultMap(oldToNewId[oldId]);
376
377 } else { // unknown type
378 // try to be forward-compatible and just skip the line
379 s.ignore(std::numeric_limits<int>::max(), '\n');
380 }
381 }
382
383 return true;
384 }
385 }

  ViewVC Help
Powered by ViewVC