/[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 2165 - (show annotations) (download)
Sun Feb 20 14:20:22 2011 UTC (13 years, 2 months ago) by persson
File size: 15422 byte(s)
* bugfix: calling SET VOICES (which Fantasia does on start and
  refresh) could cause instruments to be unloaded
* plugins: save engine type (gig, sfz or sf2) in plugin state
* VST: when opening Fantasia, look for both 32 and 64 bit Java on
  64 bit Windows

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

  ViewVC Help
Powered by ViewVC