/[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 1994 - (show annotations) (download)
Sun Aug 30 13:30:01 2009 UTC (14 years, 7 months ago) by iliev
File size: 15156 byte(s)
* bugfix: AU plugin hangs on some hosts if bound to loopback

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 #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())) << '\n';
252
253 for (int i = 0 ; i < engine_channel->GetFxSendCount() ; i++) {
254 FxSend* fxsend = engine_channel->GetFxSend(i);
255 s << FXSEND << ' ' <<
256 fxsend->Level() << ' ' <<
257 int(fxsend->MidiController()) << ' ' <<
258 fxsend->DestinationChannel(0) << ' ' <<
259 fxsend->DestinationChannel(1) << ' ' <<
260 fxsend->Name() << '\n';
261 }
262 }
263 }
264 return s.str();
265 }
266
267 void Plugin::RemoveChannels() {
268 if(global == NULL) return;
269
270 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
271
272 for (std::map<uint, SamplerChannel*>::iterator iter = channels.begin() ;
273 iter != channels.end() ; iter++) {
274 if (iter->second->GetAudioOutputDevice() == pAudioDevice) {
275 global->pSampler->RemoveSamplerChannel(iter->second);
276 }
277 }
278 }
279
280 bool Plugin::SetState(String State) {
281 RemoveChannels();
282 MidiInstrumentMapper::RemoveAllMaps();
283
284 std::stringstream s(State);
285 s >> GLOBAL_VOLUME;
286
287 EngineChannel* engine_channel;
288 int midiMapId;
289 std::map<int, int> oldToNewId;
290 int type;
291 while (s >> type) {
292
293 if (type <= 16) { // sampler channel
294 int midiChannel = type;
295 float volume;
296 s >> volume;
297 s.ignore();
298 String filename;
299 std::getline(s, filename);
300 int index;
301 bool solo;
302 bool mute;
303 s >> index >> solo >> mute;
304
305 SamplerChannel* channel = global->pSampler->AddSamplerChannel();
306 channel->SetEngineType("gig");
307 channel->SetAudioOutputDevice(pAudioDevice);
308 channel->SetMidiInputDevice(pMidiDevice);
309 channel->SetMidiInputChannel(midi_chan_t(midiChannel));
310
311 engine_channel = channel->GetEngineChannel();
312 engine_channel->Volume(volume);
313 if (s.get() == ' ') {
314 int left;
315 int right;
316 int oldMapId;
317 s >> left >> right >> oldMapId;
318 engine_channel->SetOutputChannel(0, left);
319 engine_channel->SetOutputChannel(1, right);
320
321 if (oldMapId == -1) {
322 engine_channel->SetMidiInstrumentMapToDefault();
323 } else if (oldMapId >= 0) {
324 engine_channel->SetMidiInstrumentMap(oldToNewId[oldMapId]);
325 }
326 // skip rest of line
327 s.ignore(std::numeric_limits<int>::max(), '\n');
328 }
329 if (!filename.empty() && index != -1) {
330 InstrumentManager::instrument_id_t id;
331 id.FileName = filename;
332 id.Index = index;
333 InstrumentManager::LoadInstrumentInBackground(id, engine_channel);
334 }
335 if (solo) engine_channel->SetSolo(solo);
336 if (mute) engine_channel->SetMute(1);
337
338 } else if (type == FXSEND) {
339 float level;
340 int controller;
341 int fxleft;
342 int fxright;
343 String name;
344
345 s >> level >> controller >> fxleft >> fxright;
346 s.ignore();
347 std::getline(s, name);
348 FxSend* send = engine_channel->AddFxSend(controller, name);
349 send->SetLevel(level);
350 send->SetDestinationChannel(0, fxleft);
351 send->SetDestinationChannel(1, fxright);
352
353 } else if (type == MIDIMAP) {
354 int oldId;
355 s >> oldId;
356 String name;
357 s.ignore();
358 std::getline(s, name);
359 midiMapId = MidiInstrumentMapper::AddMap(name);
360 oldToNewId[oldId] = midiMapId;
361
362 } else if (type == MIDIMAPPING) {
363 int bank;
364 int prog;
365 String engine;
366 String file;
367 int index;
368 float volume;
369 int loadmode;
370 String name;
371
372 s >> bank >> prog >> engine;
373 s.ignore();
374 std::getline(s, file);
375 s >> type >> index >> volume >> loadmode;
376 s.ignore();
377 std::getline(s, name);
378
379 global->pLSCPServer->AddOrReplaceMIDIInstrumentMapping(
380 midiMapId, bank, prog, engine, file, index, volume,
381 MidiInstrumentMapper::mode_t(loadmode), name, false);
382
383 } else if (type == DEFAULTMIDIMAP) {
384 int oldId;
385 s >> oldId;
386 MidiInstrumentMapper::SetDefaultMap(oldToNewId[oldId]);
387
388 } else { // unknown type
389 // try to be forward-compatible and just skip the line
390 s.ignore(std::numeric_limits<int>::max(), '\n');
391 }
392 }
393
394 return true;
395 }
396
397 void Plugin::DestroyDevice(AudioOutputDevicePlugin* pDevice) {
398 AudioOutputDeviceFactory::DestroyPrivate(pDevice);
399 }
400
401 void Plugin::DestroyDevice(MidiInputDevicePlugin* pDevice) {
402 MidiInputDeviceFactory::DestroyPrivate(pDevice);
403 }
404 }

  ViewVC Help
Powered by ViewVC