/[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 2174 - (hide 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 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 capela 2174 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 persson 1922 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 persson 1777
195 persson 1922 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 persson 1777 String Plugin::GetState() {
217     std::stringstream s;
218    
219     s << GLOBAL_VOLUME << '\n';
220 persson 1922
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 capela 2174 PathToState(iter->second.InstrumentFile) << '\n' <<
236 persson 1922 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 persson 1777 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 capela 2174 PathToState(filename) << '\n' <<
258 persson 1777 engine_channel->InstrumentIndex() << ' ' <<
259     engine_channel->GetSolo() << ' ' <<
260 persson 1922 (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 persson 2165 engine_channel->GetMidiInstrumentMap())) << ' ' <<
266     engine_channel->EngineName() << '\n';
267 persson 1922
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 persson 1777 }
278     }
279     return s.str();
280     }
281    
282     void Plugin::RemoveChannels() {
283 iliev 1835 if(global == NULL) return;
284    
285 persson 1777 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
286 iliev 1835
287 persson 1777 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 persson 1922 MidiInstrumentMapper::RemoveAllMaps();
298 persson 1777
299     std::stringstream s(State);
300     s >> GLOBAL_VOLUME;
301    
302 persson 1922 EngineChannel* engine_channel;
303     int midiMapId;
304     std::map<int, int> oldToNewId;
305     int type;
306     while (s >> type) {
307 persson 1777
308 persson 1922 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 persson 1777
320 persson 2165 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 persson 1922 SamplerChannel* channel = global->pSampler->AddSamplerChannel();
333 persson 2165 channel->SetEngineType(engineType);
334 persson 1922 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 persson 2165
341     if (left != -1) {
342 persson 1922 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 capela 2174 id.FileName = PathFromState(filename);
354 persson 1922 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 persson 1777 }
414     }
415    
416     return true;
417     }
418 iliev 1992
419     void Plugin::DestroyDevice(AudioOutputDevicePlugin* pDevice) {
420     AudioOutputDeviceFactory::DestroyPrivate(pDevice);
421     }
422    
423     void Plugin::DestroyDevice(MidiInputDevicePlugin* pDevice) {
424     MidiInputDeviceFactory::DestroyPrivate(pDevice);
425     }
426 persson 1777 }

  ViewVC Help
Powered by ViewVC