/[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 1994 - (hide annotations) (download)
Sun Aug 30 13:30:01 2009 UTC (14 years, 8 months ago) by iliev
File size: 15156 byte(s)
* bugfix: AU plugin hangs on some hosts if bound to loopback

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 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     engine_channel->GetMidiInstrumentMap())) << '\n';
252    
253     for (int i = 0 ; i < engine_channel->GetFxSendCount() ; i++) {
254     FxSend* fxsend = engine_channel->GetFxSend(i);
255     s << FXSEND << ' ' <<
256     fxsend->Level() << ' ' <<
257     int(fxsend->MidiController()) << ' ' <<
258     fxsend->DestinationChannel(0) << ' ' <<
259     fxsend->DestinationChannel(1) << ' ' <<
260     fxsend->Name() << '\n';
261     }
262 persson 1777 }
263     }
264     return s.str();
265     }
266    
267     void Plugin::RemoveChannels() {
268 iliev 1835 if(global == NULL) return;
269    
270 persson 1777 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
271 iliev 1835
272 persson 1777 for (std::map<uint, SamplerChannel*>::iterator iter = channels.begin() ;
273     iter != channels.end() ; iter++) {
274     if (iter->second->GetAudioOutputDevice() == pAudioDevice) {
275     global->pSampler->RemoveSamplerChannel(iter->second);
276     }
277     }
278     }
279    
280     bool Plugin::SetState(String State) {
281     RemoveChannels();
282 persson 1922 MidiInstrumentMapper::RemoveAllMaps();
283 persson 1777
284     std::stringstream s(State);
285     s >> GLOBAL_VOLUME;
286    
287 persson 1922 EngineChannel* engine_channel;
288     int midiMapId;
289     std::map<int, int> oldToNewId;
290     int type;
291     while (s >> type) {
292 persson 1777
293 persson 1922 if (type <= 16) { // sampler channel
294     int midiChannel = type;
295     float volume;
296     s >> volume;
297     s.ignore();
298     String filename;
299     std::getline(s, filename);
300     int index;
301     bool solo;
302     bool mute;
303     s >> index >> solo >> mute;
304 persson 1777
305 persson 1922 SamplerChannel* channel = global->pSampler->AddSamplerChannel();
306     channel->SetEngineType("gig");
307     channel->SetAudioOutputDevice(pAudioDevice);
308     channel->SetMidiInputDevice(pMidiDevice);
309     channel->SetMidiInputChannel(midi_chan_t(midiChannel));
310    
311     engine_channel = channel->GetEngineChannel();
312     engine_channel->Volume(volume);
313     if (s.get() == ' ') {
314     int left;
315     int right;
316     int oldMapId;
317     s >> left >> right >> oldMapId;
318     engine_channel->SetOutputChannel(0, left);
319     engine_channel->SetOutputChannel(1, right);
320    
321     if (oldMapId == -1) {
322     engine_channel->SetMidiInstrumentMapToDefault();
323     } else if (oldMapId >= 0) {
324     engine_channel->SetMidiInstrumentMap(oldToNewId[oldMapId]);
325     }
326     // skip rest of line
327     s.ignore(std::numeric_limits<int>::max(), '\n');
328     }
329     if (!filename.empty() && index != -1) {
330     InstrumentManager::instrument_id_t id;
331     id.FileName = filename;
332     id.Index = index;
333     InstrumentManager::LoadInstrumentInBackground(id, engine_channel);
334     }
335     if (solo) engine_channel->SetSolo(solo);
336     if (mute) engine_channel->SetMute(1);
337    
338     } else if (type == FXSEND) {
339     float level;
340     int controller;
341     int fxleft;
342     int fxright;
343     String name;
344    
345     s >> level >> controller >> fxleft >> fxright;
346     s.ignore();
347     std::getline(s, name);
348     FxSend* send = engine_channel->AddFxSend(controller, name);
349     send->SetLevel(level);
350     send->SetDestinationChannel(0, fxleft);
351     send->SetDestinationChannel(1, fxright);
352    
353     } else if (type == MIDIMAP) {
354     int oldId;
355     s >> oldId;
356     String name;
357     s.ignore();
358     std::getline(s, name);
359     midiMapId = MidiInstrumentMapper::AddMap(name);
360     oldToNewId[oldId] = midiMapId;
361    
362     } else if (type == MIDIMAPPING) {
363     int bank;
364     int prog;
365     String engine;
366     String file;
367     int index;
368     float volume;
369     int loadmode;
370     String name;
371    
372     s >> bank >> prog >> engine;
373     s.ignore();
374     std::getline(s, file);
375     s >> type >> index >> volume >> loadmode;
376     s.ignore();
377     std::getline(s, name);
378    
379     global->pLSCPServer->AddOrReplaceMIDIInstrumentMapping(
380     midiMapId, bank, prog, engine, file, index, volume,
381     MidiInstrumentMapper::mode_t(loadmode), name, false);
382    
383     } else if (type == DEFAULTMIDIMAP) {
384     int oldId;
385     s >> oldId;
386     MidiInstrumentMapper::SetDefaultMap(oldToNewId[oldId]);
387    
388     } else { // unknown type
389     // try to be forward-compatible and just skip the line
390     s.ignore(std::numeric_limits<int>::max(), '\n');
391 persson 1777 }
392     }
393    
394     return true;
395     }
396 iliev 1992
397     void Plugin::DestroyDevice(AudioOutputDevicePlugin* pDevice) {
398     AudioOutputDeviceFactory::DestroyPrivate(pDevice);
399     }
400    
401     void Plugin::DestroyDevice(MidiInputDevicePlugin* pDevice) {
402     MidiInputDeviceFactory::DestroyPrivate(pDevice);
403     }
404 persson 1777 }

  ViewVC Help
Powered by ViewVC