/[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 1992 - (show annotations) (download)
Fri Aug 28 07:48:47 2009 UTC (11 years, 6 months ago) by iliev
File size: 14989 byte(s)
* bugfix: AU plugin failed to destroy its audio/MIDI devices

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

  ViewVC Help
Powered by ViewVC