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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1934 - (hide annotations) (download)
Sun Jul 12 10:35:55 2009 UTC (14 years, 9 months ago) by schoenebeck
File size: 14727 byte(s)
* bugfix: don't allow to create or destroy audio devices and MIDI devices
  of host plugin implementations (e.g VST, AU, DSSI, LV2) on their own,
  as they only exist in the context of the plugin instance and would
  otherwise crash the application

1 persson 1777 /***************************************************************************
2     * *
3 persson 1889 * Copyright (C) 2008 - 2009 Andreas Persson *
4 persson 1777 * *
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 persson 1922 #include <limits>
22 persson 1777 #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 persson 1889 AudioOutputDeviceFactory::Unregister("ASIO");
38 persson 1777
39     REGISTER_AUDIO_OUTPUT_DRIVER(AudioOutputDevicePlugin);
40     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDevicePlugin, ParameterActive);
41     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDevicePlugin, ParameterSampleRate);
42 iliev 1907 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDevicePlugin, ParameterChannelsPlugin);
43 persson 1777 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDevicePlugin, ParameterFragmentSize);
44    
45     REGISTER_MIDI_INPUT_DRIVER(MidiInputDevicePlugin);
46     REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDevicePlugin, ParameterActive);
47 iliev 1907 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDevicePlugin, ParameterPortsPlugin);
48 persson 1777
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 iliev 1835 pLSCPServer->RemoveListeners();
67 persson 1777
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 persson 1895 return 0;
89 persson 1777 }
90    
91    
92     // *************** Plugin ***************
93     // *
94    
95     PluginGlobal* Plugin::global = 0;
96    
97 iliev 1835 Plugin::Plugin(bool bDoPreInit) :
98 persson 1777 pAudioDevice(0),
99     pMidiDevice(0) {
100 iliev 1835 bPreInitDone = false;
101     if (bDoPreInit) PreInit();
102     }
103    
104     void Plugin::PreInit() {
105     if (bPreInitDone) return;
106    
107     bPreInitDone = true;
108 persson 1777 if (!global) {
109     global = new PluginGlobal;
110     }
111     global->RefCount++;
112     }
113    
114 iliev 1835 void Plugin::Init(int SampleRate, int FragmentSize, int Channels) {
115 persson 1895 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 schoenebeck 1934 AudioOutputDeviceFactory::DestroyPrivate(pAudioDevice);
125 persson 1895 }
126 persson 1777 std::map<String, String> params;
127     params["SAMPLERATE"] = ToString(SampleRate);
128     params["FRAGMENTSIZE"] = ToString(FragmentSize);
129 iliev 1835 if (Channels > 0) params["CHANNELS"] = ToString(Channels);
130 persson 1777 pAudioDevice = dynamic_cast<AudioOutputDevicePlugin*>(
131 schoenebeck 1934 AudioOutputDeviceFactory::CreatePrivate(
132     AudioOutputDevicePlugin::Name(), params
133     )
134     );
135 persson 1777
136 persson 1895 if (!pMidiDevice) {
137     pMidiDevice = dynamic_cast<MidiInputDevicePlugin*>(
138 schoenebeck 1934 MidiInputDeviceFactory::CreatePrivate(
139     MidiInputDevicePlugin::Name(), std::map<String,String>(),
140     global->pSampler
141     )
142     );
143 persson 1895 }
144    
145     if (!oldState.empty()) {
146     SetState(oldState);
147     }
148 persson 1777 }
149    
150     Plugin::~Plugin() {
151     RemoveChannels();
152 schoenebeck 1934 if (pAudioDevice) AudioOutputDeviceFactory::DestroyPrivate(pAudioDevice);
153     if (pMidiDevice) MidiInputDeviceFactory::DestroyPrivate(pMidiDevice);
154 iliev 1835 if (bPreInitDone) {
155     if (--global->RefCount == 0) {
156     delete global;
157     global = 0;
158     }
159 persson 1777 }
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 persson 1922 /*
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 persson 1777
176 persson 1922 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 persson 1777 String Plugin::GetState() {
198     std::stringstream s;
199    
200     s << GLOBAL_VOLUME << '\n';
201 persson 1922
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 persson 1777 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 persson 1922 (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 persson 1777 }
258     }
259     return s.str();
260     }
261    
262     void Plugin::RemoveChannels() {
263 iliev 1835 if(global == NULL) return;
264    
265 persson 1777 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
266 iliev 1835
267 persson 1777 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 persson 1922 MidiInstrumentMapper::RemoveAllMaps();
278 persson 1777
279     std::stringstream s(State);
280     s >> GLOBAL_VOLUME;
281    
282 persson 1922 EngineChannel* engine_channel;
283     int midiMapId;
284     std::map<int, int> oldToNewId;
285     int type;
286     while (s >> type) {
287 persson 1777
288 persson 1922 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 persson 1777
300 persson 1922 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 persson 1777 }
387     }
388    
389     return true;
390     }
391     }

  ViewVC Help
Powered by ViewVC