/[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 2165 - (hide 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 persson 1777 /***************************************************************************
2     * *
3 persson 2165 * Copyright (C) 2008 - 2011 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 iliev 1994 #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 persson 1777 // using LOOPBACK instead of ANY to prevent windows firewall
56     // warnings
57 iliev 1994 pLSCPServer = new LSCPServer(pSampler, htonl(INADDR_LOOPBACK), htons(LSCP_PORT));
58     #endif
59    
60 persson 1777 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 iliev 1835 pLSCPServer->RemoveListeners();
72 persson 1777
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 persson 1895 return 0;
94 persson 1777 }
95    
96    
97     // *************** Plugin ***************
98     // *
99    
100     PluginGlobal* Plugin::global = 0;
101    
102 iliev 1835 Plugin::Plugin(bool bDoPreInit) :
103 persson 1777 pAudioDevice(0),
104     pMidiDevice(0) {
105 iliev 1835 bPreInitDone = false;
106     if (bDoPreInit) PreInit();
107     }
108    
109     void Plugin::PreInit() {
110     if (bPreInitDone) return;
111    
112     bPreInitDone = true;
113 persson 1777 if (!global) {
114     global = new PluginGlobal;
115     }
116     global->RefCount++;
117     }
118    
119 iliev 1835 void Plugin::Init(int SampleRate, int FragmentSize, int Channels) {
120 persson 1895 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 schoenebeck 1934 AudioOutputDeviceFactory::DestroyPrivate(pAudioDevice);
130 persson 1895 }
131 persson 1777 std::map<String, String> params;
132     params["SAMPLERATE"] = ToString(SampleRate);
133     params["FRAGMENTSIZE"] = ToString(FragmentSize);
134 iliev 1835 if (Channels > 0) params["CHANNELS"] = ToString(Channels);
135 persson 1777 pAudioDevice = dynamic_cast<AudioOutputDevicePlugin*>(
136 schoenebeck 1934 AudioOutputDeviceFactory::CreatePrivate(
137     AudioOutputDevicePlugin::Name(), params
138     )
139     );
140 persson 1777
141 persson 1895 if (!pMidiDevice) {
142     pMidiDevice = dynamic_cast<MidiInputDevicePlugin*>(
143 schoenebeck 1934 MidiInputDeviceFactory::CreatePrivate(
144     MidiInputDevicePlugin::Name(), std::map<String,String>(),
145     global->pSampler
146     )
147     );
148 persson 1895 }
149    
150     if (!oldState.empty()) {
151     SetState(oldState);
152     }
153 persson 1777 }
154    
155     Plugin::~Plugin() {
156     RemoveChannels();
157 schoenebeck 1934 if (pAudioDevice) AudioOutputDeviceFactory::DestroyPrivate(pAudioDevice);
158     if (pMidiDevice) MidiInputDeviceFactory::DestroyPrivate(pMidiDevice);
159 iliev 1835 if (bPreInitDone) {
160     if (--global->RefCount == 0) {
161     delete global;
162     global = 0;
163     }
164 persson 1777 }
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 persson 1922 /*
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 persson 1777
181 persson 1922 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 persson 1777 String Plugin::GetState() {
203     std::stringstream s;
204    
205     s << GLOBAL_VOLUME << '\n';
206 persson 1922
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 persson 1777 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 persson 1922 (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 persson 2165 engine_channel->GetMidiInstrumentMap())) << ' ' <<
252     engine_channel->EngineName() << '\n';
253 persson 1922
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 persson 1777 }
264     }
265     return s.str();
266     }
267    
268     void Plugin::RemoveChannels() {
269 iliev 1835 if(global == NULL) return;
270    
271 persson 1777 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
272 iliev 1835
273 persson 1777 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 persson 1922 MidiInstrumentMapper::RemoveAllMaps();
284 persson 1777
285     std::stringstream s(State);
286     s >> GLOBAL_VOLUME;
287    
288 persson 1922 EngineChannel* engine_channel;
289     int midiMapId;
290     std::map<int, int> oldToNewId;
291     int type;
292     while (s >> type) {
293 persson 1777
294 persson 1922 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 persson 1777
306 persson 2165 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 persson 1922 SamplerChannel* channel = global->pSampler->AddSamplerChannel();
319 persson 2165 channel->SetEngineType(engineType);
320 persson 1922 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 persson 2165
327     if (left != -1) {
328 persson 1922 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 persson 1777 }
400     }
401    
402     return true;
403     }
404 iliev 1992
405     void Plugin::DestroyDevice(AudioOutputDevicePlugin* pDevice) {
406     AudioOutputDeviceFactory::DestroyPrivate(pDevice);
407     }
408    
409     void Plugin::DestroyDevice(MidiInputDevicePlugin* pDevice) {
410     MidiInputDeviceFactory::DestroyPrivate(pDevice);
411     }
412 persson 1777 }

  ViewVC Help
Powered by ViewVC