/[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 2174 - (show annotations) (download)
Tue Apr 12 15:19:56 2011 UTC (13 years ago) by capela
File size: 15859 byte(s)
* plugin changes:
    - LV2 Persist + Files support (patch by David Robillard)

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 These methods can be overloaded by different plugin types to map
177 file names to/from file names to be used in the state text, making
178 it possible for state to be self-contained and/or movable.
179 */
180
181 String Plugin::PathToState(const String& string) {
182 return string;
183 }
184
185 String Plugin::PathFromState(const String& string) {
186 return string;
187 }
188
189 /*
190 The sampler state is stored in a text base format, designed to
191 be easy to parse with the istream >> operator. Values are
192 separated by spaces or newlines. All string values that may
193 contain spaces end with a newline.
194
195 The first line contains the global volume.
196
197 The rest of the lines have an integer first representing the
198 type of information on the line, except for the two lines that
199 describe each sampler channel. The first of these two starts
200 with an integer from 0 to 16 (the midi channel for the sampler
201 channel).
202
203 Note that we should try to keep the parsing of this format both
204 backwards and forwards compatible between versions. The parser
205 ignores lines with unknown type integers and accepts that new
206 types are missing.
207 */
208
209 enum {
210 FXSEND = 17,
211 MIDIMAP,
212 MIDIMAPPING,
213 DEFAULTMIDIMAP
214 };
215
216 String Plugin::GetState() {
217 std::stringstream s;
218
219 s << GLOBAL_VOLUME << '\n';
220
221 std::vector<int> maps = MidiInstrumentMapper::Maps();
222 for (int i = 0 ; i < maps.size() ; i++) {
223 s << MIDIMAP << ' ' <<
224 maps[i] << ' ' <<
225 MidiInstrumentMapper::MapName(maps[i]) << '\n';
226
227 std::map<midi_prog_index_t, MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
228 for (std::map<midi_prog_index_t, MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin() ;
229 iter != mappings.end(); iter++) {
230 s << MIDIMAPPING << ' ' <<
231 ((int(iter->first.midi_bank_msb) << 7) |
232 int(iter->first.midi_bank_lsb)) << ' ' <<
233 int(iter->first.midi_prog) << ' ' <<
234 iter->second.EngineName << ' ' <<
235 PathToState(iter->second.InstrumentFile) << '\n' <<
236 MIDIMAPPING << ' ' <<
237 iter->second.InstrumentIndex << ' ' <<
238 iter->second.Volume << ' ' <<
239 iter->second.LoadMode << ' ' <<
240 iter->second.Name << '\n';
241 }
242 }
243 if (maps.size()) {
244 s << DEFAULTMIDIMAP << ' ' <<
245 MidiInstrumentMapper::GetDefaultMap() << '\n';
246 }
247
248 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
249 for (std::map<uint, SamplerChannel*>::iterator iter = channels.begin() ;
250 iter != channels.end() ; iter++) {
251 SamplerChannel* channel = iter->second;
252 if (channel->GetAudioOutputDevice() == pAudioDevice) {
253 EngineChannel* engine_channel = channel->GetEngineChannel();
254 String filename = engine_channel->InstrumentFileName();
255 s << channel->GetMidiInputChannel() << ' ' <<
256 engine_channel->Volume() << ' ' <<
257 PathToState(filename) << '\n' <<
258 engine_channel->InstrumentIndex() << ' ' <<
259 engine_channel->GetSolo() << ' ' <<
260 (engine_channel->GetMute() == 1) << ' ' <<
261 engine_channel->OutputChannel(0) << ' ' <<
262 engine_channel->OutputChannel(1) << ' ' <<
263 (engine_channel->UsesNoMidiInstrumentMap() ? -2 :
264 (engine_channel->UsesDefaultMidiInstrumentMap() ? -1 :
265 engine_channel->GetMidiInstrumentMap())) << ' ' <<
266 engine_channel->EngineName() << '\n';
267
268 for (int i = 0 ; i < engine_channel->GetFxSendCount() ; i++) {
269 FxSend* fxsend = engine_channel->GetFxSend(i);
270 s << FXSEND << ' ' <<
271 fxsend->Level() << ' ' <<
272 int(fxsend->MidiController()) << ' ' <<
273 fxsend->DestinationChannel(0) << ' ' <<
274 fxsend->DestinationChannel(1) << ' ' <<
275 fxsend->Name() << '\n';
276 }
277 }
278 }
279 return s.str();
280 }
281
282 void Plugin::RemoveChannels() {
283 if(global == NULL) return;
284
285 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
286
287 for (std::map<uint, SamplerChannel*>::iterator iter = channels.begin() ;
288 iter != channels.end() ; iter++) {
289 if (iter->second->GetAudioOutputDevice() == pAudioDevice) {
290 global->pSampler->RemoveSamplerChannel(iter->second);
291 }
292 }
293 }
294
295 bool Plugin::SetState(String State) {
296 RemoveChannels();
297 MidiInstrumentMapper::RemoveAllMaps();
298
299 std::stringstream s(State);
300 s >> GLOBAL_VOLUME;
301
302 EngineChannel* engine_channel;
303 int midiMapId;
304 std::map<int, int> oldToNewId;
305 int type;
306 while (s >> type) {
307
308 if (type <= 16) { // sampler channel
309 int midiChannel = type;
310 float volume;
311 s >> volume;
312 s.ignore();
313 String filename;
314 std::getline(s, filename);
315 int index;
316 bool solo;
317 bool mute;
318 s >> index >> solo >> mute;
319
320 int left = -1;
321 int right;
322 int oldMapId;
323 String engineType = "gig";
324 if (s.get() == ' ') {
325 s >> left >> right >> oldMapId;
326 if (s.get() == ' ') {
327 s >> engineType;
328 // skip rest of line
329 s.ignore(std::numeric_limits<int>::max(), '\n');
330 }
331 }
332 SamplerChannel* channel = global->pSampler->AddSamplerChannel();
333 channel->SetEngineType(engineType);
334 channel->SetAudioOutputDevice(pAudioDevice);
335 channel->SetMidiInputDevice(pMidiDevice);
336 channel->SetMidiInputChannel(midi_chan_t(midiChannel));
337
338 engine_channel = channel->GetEngineChannel();
339 engine_channel->Volume(volume);
340
341 if (left != -1) {
342 engine_channel->SetOutputChannel(0, left);
343 engine_channel->SetOutputChannel(1, right);
344
345 if (oldMapId == -1) {
346 engine_channel->SetMidiInstrumentMapToDefault();
347 } else if (oldMapId >= 0) {
348 engine_channel->SetMidiInstrumentMap(oldToNewId[oldMapId]);
349 }
350 }
351 if (!filename.empty() && index != -1) {
352 InstrumentManager::instrument_id_t id;
353 id.FileName = PathFromState(filename);
354 id.Index = index;
355 InstrumentManager::LoadInstrumentInBackground(id, engine_channel);
356 }
357 if (solo) engine_channel->SetSolo(solo);
358 if (mute) engine_channel->SetMute(1);
359
360 } else if (type == FXSEND) {
361 float level;
362 int controller;
363 int fxleft;
364 int fxright;
365 String name;
366
367 s >> level >> controller >> fxleft >> fxright;
368 s.ignore();
369 std::getline(s, name);
370 FxSend* send = engine_channel->AddFxSend(controller, name);
371 send->SetLevel(level);
372 send->SetDestinationChannel(0, fxleft);
373 send->SetDestinationChannel(1, fxright);
374
375 } else if (type == MIDIMAP) {
376 int oldId;
377 s >> oldId;
378 String name;
379 s.ignore();
380 std::getline(s, name);
381 midiMapId = MidiInstrumentMapper::AddMap(name);
382 oldToNewId[oldId] = midiMapId;
383
384 } else if (type == MIDIMAPPING) {
385 int bank;
386 int prog;
387 String engine;
388 String file;
389 int index;
390 float volume;
391 int loadmode;
392 String name;
393
394 s >> bank >> prog >> engine;
395 s.ignore();
396 std::getline(s, file);
397 s >> type >> index >> volume >> loadmode;
398 s.ignore();
399 std::getline(s, name);
400
401 global->pLSCPServer->AddOrReplaceMIDIInstrumentMapping(
402 midiMapId, bank, prog, engine, file, index, volume,
403 MidiInstrumentMapper::mode_t(loadmode), name, false);
404
405 } else if (type == DEFAULTMIDIMAP) {
406 int oldId;
407 s >> oldId;
408 MidiInstrumentMapper::SetDefaultMap(oldToNewId[oldId]);
409
410 } else { // unknown type
411 // try to be forward-compatible and just skip the line
412 s.ignore(std::numeric_limits<int>::max(), '\n');
413 }
414 }
415
416 return true;
417 }
418
419 void Plugin::DestroyDevice(AudioOutputDevicePlugin* pDevice) {
420 AudioOutputDeviceFactory::DestroyPrivate(pDevice);
421 }
422
423 void Plugin::DestroyDevice(MidiInputDevicePlugin* pDevice) {
424 MidiInputDeviceFactory::DestroyPrivate(pDevice);
425 }
426 }

  ViewVC Help
Powered by ViewVC