/[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 1922 - (hide annotations) (download)
Fri Jun 26 18:55:02 2009 UTC (14 years, 10 months ago) by persson
File size: 14665 byte(s)
* added channel routing, fxsends and midi maps to the settings stored
  in the plugin state

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     global->pSampler->DestroyAudioOutputDevice(pAudioDevice);
125     }
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     global->pSampler->CreateAudioOutputDevice(AudioOutputDevicePlugin::Name(), params));
132    
133 persson 1895 if (!pMidiDevice) {
134     pMidiDevice = dynamic_cast<MidiInputDevicePlugin*>(
135     global->pSampler->CreateMidiInputDevice(MidiInputDevicePlugin::Name(),
136     std::map<String,String>()));
137     }
138    
139     if (!oldState.empty()) {
140     SetState(oldState);
141     }
142 persson 1777 }
143    
144     Plugin::~Plugin() {
145     RemoveChannels();
146     if (pAudioDevice) global->pSampler->DestroyAudioOutputDevice(pAudioDevice);
147     if (pMidiDevice) global->pSampler->DestroyMidiInputDevice(pMidiDevice);
148 iliev 1835 if (bPreInitDone) {
149     if (--global->RefCount == 0) {
150     delete global;
151     global = 0;
152     }
153 persson 1777 }
154     }
155    
156     void Plugin::InitState() {
157     SamplerChannel* channel = global->pSampler->AddSamplerChannel();
158     channel->SetEngineType("gig");
159     channel->SetAudioOutputDevice(pAudioDevice);
160     channel->SetMidiInputDevice(pMidiDevice);
161     channel->SetMidiInputChannel(midi_chan_1);
162     }
163    
164 persson 1922 /*
165     The sampler state is stored in a text base format, designed to
166     be easy to parse with the istream >> operator. Values are
167     separated by spaces or newlines. All string values that may
168     contain spaces end with a newline.
169 persson 1777
170 persson 1922 The first line contains the global volume.
171    
172     The rest of the lines have an integer first representing the
173     type of information on the line, except for the two lines that
174     describe each sampler channel. The first of these two starts
175     with an integer from 0 to 16 (the midi channel for the sampler
176     channel).
177    
178     Note that we should try to keep the parsing of this format both
179     backwards and forwards compatible between versions. The parser
180     ignores lines with unknown type integers and accepts that new
181     types are missing.
182     */
183    
184     enum {
185     FXSEND = 17,
186     MIDIMAP,
187     MIDIMAPPING,
188     DEFAULTMIDIMAP
189     };
190    
191 persson 1777 String Plugin::GetState() {
192     std::stringstream s;
193    
194     s << GLOBAL_VOLUME << '\n';
195 persson 1922
196     std::vector<int> maps = MidiInstrumentMapper::Maps();
197     for (int i = 0 ; i < maps.size() ; i++) {
198     s << MIDIMAP << ' ' <<
199     maps[i] << ' ' <<
200     MidiInstrumentMapper::MapName(maps[i]) << '\n';
201    
202     std::map<midi_prog_index_t, MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
203     for (std::map<midi_prog_index_t, MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin() ;
204     iter != mappings.end(); iter++) {
205     s << MIDIMAPPING << ' ' <<
206     ((int(iter->first.midi_bank_msb) << 7) |
207     int(iter->first.midi_bank_lsb)) << ' ' <<
208     int(iter->first.midi_prog) << ' ' <<
209     iter->second.EngineName << ' ' <<
210     iter->second.InstrumentFile << '\n' <<
211     MIDIMAPPING << ' ' <<
212     iter->second.InstrumentIndex << ' ' <<
213     iter->second.Volume << ' ' <<
214     iter->second.LoadMode << ' ' <<
215     iter->second.Name << '\n';
216     }
217     }
218     if (maps.size()) {
219     s << DEFAULTMIDIMAP << ' ' <<
220     MidiInstrumentMapper::GetDefaultMap() << '\n';
221     }
222    
223 persson 1777 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
224     for (std::map<uint, SamplerChannel*>::iterator iter = channels.begin() ;
225     iter != channels.end() ; iter++) {
226     SamplerChannel* channel = iter->second;
227     if (channel->GetAudioOutputDevice() == pAudioDevice) {
228     EngineChannel* engine_channel = channel->GetEngineChannel();
229     String filename = engine_channel->InstrumentFileName();
230     s << channel->GetMidiInputChannel() << ' ' <<
231     engine_channel->Volume() << ' ' <<
232     filename << '\n' <<
233     engine_channel->InstrumentIndex() << ' ' <<
234     engine_channel->GetSolo() << ' ' <<
235 persson 1922 (engine_channel->GetMute() == 1) << ' ' <<
236     engine_channel->OutputChannel(0) << ' ' <<
237     engine_channel->OutputChannel(1) << ' ' <<
238     (engine_channel->UsesNoMidiInstrumentMap() ? -2 :
239     (engine_channel->UsesDefaultMidiInstrumentMap() ? -1 :
240     engine_channel->GetMidiInstrumentMap())) << '\n';
241    
242     for (int i = 0 ; i < engine_channel->GetFxSendCount() ; i++) {
243     FxSend* fxsend = engine_channel->GetFxSend(i);
244     s << FXSEND << ' ' <<
245     fxsend->Level() << ' ' <<
246     int(fxsend->MidiController()) << ' ' <<
247     fxsend->DestinationChannel(0) << ' ' <<
248     fxsend->DestinationChannel(1) << ' ' <<
249     fxsend->Name() << '\n';
250     }
251 persson 1777 }
252     }
253     return s.str();
254     }
255    
256     void Plugin::RemoveChannels() {
257 iliev 1835 if(global == NULL) return;
258    
259 persson 1777 std::map<uint, SamplerChannel*> channels = global->pSampler->GetSamplerChannels();
260 iliev 1835
261 persson 1777 for (std::map<uint, SamplerChannel*>::iterator iter = channels.begin() ;
262     iter != channels.end() ; iter++) {
263     if (iter->second->GetAudioOutputDevice() == pAudioDevice) {
264     global->pSampler->RemoveSamplerChannel(iter->second);
265     }
266     }
267     }
268    
269     bool Plugin::SetState(String State) {
270     RemoveChannels();
271 persson 1922 MidiInstrumentMapper::RemoveAllMaps();
272 persson 1777
273     std::stringstream s(State);
274     s >> GLOBAL_VOLUME;
275    
276 persson 1922 EngineChannel* engine_channel;
277     int midiMapId;
278     std::map<int, int> oldToNewId;
279     int type;
280     while (s >> type) {
281 persson 1777
282 persson 1922 if (type <= 16) { // sampler channel
283     int midiChannel = type;
284     float volume;
285     s >> volume;
286     s.ignore();
287     String filename;
288     std::getline(s, filename);
289     int index;
290     bool solo;
291     bool mute;
292     s >> index >> solo >> mute;
293 persson 1777
294 persson 1922 SamplerChannel* channel = global->pSampler->AddSamplerChannel();
295     channel->SetEngineType("gig");
296     channel->SetAudioOutputDevice(pAudioDevice);
297     channel->SetMidiInputDevice(pMidiDevice);
298     channel->SetMidiInputChannel(midi_chan_t(midiChannel));
299    
300     engine_channel = channel->GetEngineChannel();
301     engine_channel->Volume(volume);
302     if (s.get() == ' ') {
303     int left;
304     int right;
305     int oldMapId;
306     s >> left >> right >> oldMapId;
307     engine_channel->SetOutputChannel(0, left);
308     engine_channel->SetOutputChannel(1, right);
309    
310     if (oldMapId == -1) {
311     engine_channel->SetMidiInstrumentMapToDefault();
312     } else if (oldMapId >= 0) {
313     engine_channel->SetMidiInstrumentMap(oldToNewId[oldMapId]);
314     }
315     // skip rest of line
316     s.ignore(std::numeric_limits<int>::max(), '\n');
317     }
318     if (!filename.empty() && index != -1) {
319     InstrumentManager::instrument_id_t id;
320     id.FileName = filename;
321     id.Index = index;
322     InstrumentManager::LoadInstrumentInBackground(id, engine_channel);
323     }
324     if (solo) engine_channel->SetSolo(solo);
325     if (mute) engine_channel->SetMute(1);
326    
327     } else if (type == FXSEND) {
328     float level;
329     int controller;
330     int fxleft;
331     int fxright;
332     String name;
333    
334     s >> level >> controller >> fxleft >> fxright;
335     s.ignore();
336     std::getline(s, name);
337     FxSend* send = engine_channel->AddFxSend(controller, name);
338     send->SetLevel(level);
339     send->SetDestinationChannel(0, fxleft);
340     send->SetDestinationChannel(1, fxright);
341    
342     } else if (type == MIDIMAP) {
343     int oldId;
344     s >> oldId;
345     String name;
346     s.ignore();
347     std::getline(s, name);
348     midiMapId = MidiInstrumentMapper::AddMap(name);
349     oldToNewId[oldId] = midiMapId;
350    
351     } else if (type == MIDIMAPPING) {
352     int bank;
353     int prog;
354     String engine;
355     String file;
356     int index;
357     float volume;
358     int loadmode;
359     String name;
360    
361     s >> bank >> prog >> engine;
362     s.ignore();
363     std::getline(s, file);
364     s >> type >> index >> volume >> loadmode;
365     s.ignore();
366     std::getline(s, name);
367    
368     global->pLSCPServer->AddOrReplaceMIDIInstrumentMapping(
369     midiMapId, bank, prog, engine, file, index, volume,
370     MidiInstrumentMapper::mode_t(loadmode), name, false);
371    
372     } else if (type == DEFAULTMIDIMAP) {
373     int oldId;
374     s >> oldId;
375     MidiInstrumentMapper::SetDefaultMap(oldToNewId[oldId]);
376    
377     } else { // unknown type
378     // try to be forward-compatible and just skip the line
379     s.ignore(std::numeric_limits<int>::max(), '\n');
380 persson 1777 }
381     }
382    
383     return true;
384     }
385     }

  ViewVC Help
Powered by ViewVC