/[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 2185 - (hide annotations) (download)
Sun Jun 19 09:09:38 2011 UTC (12 years, 10 months ago) by persson
File size: 15885 byte(s)
* fixed compilation with gcc 4.6.1
* another "make dist" fix, for LV2 plugin
* made --enable-pthread-testcancel default on Mac OS X
* Mac OS X: fixed hanging threads

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

  ViewVC Help
Powered by ViewVC