/[svn]/linuxsampler/trunk/src/hostplugins/dssi/PluginDssi.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/hostplugins/dssi/PluginDssi.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2354 - (hide annotations) (download)
Sun Jul 8 10:29:07 2012 UTC (11 years, 9 months ago) by persson
File size: 12910 byte(s)
* DSSI bugfix: it wasn't possible to change engine type. The MIDI port
  and audio channel routing for DSSI plugins are now visible.

1 persson 1777 /***************************************************************************
2     * *
3 persson 2162 * 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     #include <algorithm>
22     #include <cstring>
23     #include <exception>
24     #include <sstream>
25     #include <string>
26    
27     #include "PluginDssi.h"
28    
29 persson 2013 #include "../../engines/AbstractEngineChannel.h"
30 persson 2354 #include "../../engines/EngineChannelFactory.h"
31 persson 1777
32     namespace {
33    
34     // *************** PluginDssi ***************
35     // *
36    
37 persson 1858 PluginDssi::PluginDssi(unsigned long SampleRate) :
38     RefCount(0) {
39 persson 1777 // As there is no way in DSSI of knowing a max value of the
40     // output buffer size, we set the audio device buffer size to
41     // 128 and let RunSynth call Render in a loop if needed.
42     Init(SampleRate, 128);
43 persson 1858 }
44 persson 1777
45 persson 1858 PluginDssi* PluginInstance::plugin = 0;
46    
47     PluginInstance::PluginInstance(unsigned long SampleRate) {
48     Out[0] = 0;
49     Out[1] = 0;
50    
51     if (!plugin) {
52     plugin = new PluginDssi(SampleRate);
53     }
54     plugin->RefCount++;
55    
56     pChannel = plugin->global->pSampler->AddSamplerChannel();
57 persson 1777 pChannel->SetEngineType("gig");
58 persson 1858 pChannel->SetAudioOutputDevice(plugin->pAudioDevice);
59    
60 persson 2354 if (plugin->RefCount > 1) {
61     plugin->pMidiDevice->AddMidiPort();
62     plugin->pAudioDevice->AddChannels(2);
63     }
64    
65     int i = plugin->RefCount - 1;
66    
67     pChannel->SetMidiInput(plugin->pMidiDevice, i, LinuxSampler::midi_chan_all);
68 persson 2013 LinuxSampler::AbstractEngineChannel* engineChannel =
69     static_cast<LinuxSampler::AbstractEngineChannel*>(pChannel->GetEngineChannel());
70 persson 2354 engineChannel->SetOutputChannel(0, i * 2);
71     engineChannel->SetOutputChannel(1, i * 2 + 1);
72    
73     pPort = plugin->pMidiDevice->GetPort(i);
74     pChannelLeft = plugin->pAudioDevice->Channel(i * 2);
75     pChannelRight = plugin->pAudioDevice->Channel(i * 2 + 1);
76 persson 1777 }
77    
78 persson 1858 PluginInstance::~PluginInstance() {
79     if (--plugin->RefCount == 0) {
80     delete plugin;
81     plugin = 0;
82     } else {
83 persson 2354 LinuxSampler::AbstractEngineChannel* engineChannel =
84     static_cast<LinuxSampler::AbstractEngineChannel*>(pChannel->GetEngineChannel());
85     int oldChannelNumber = engineChannel->OutputChannel(0);
86    
87 persson 1858 plugin->global->pSampler->RemoveSamplerChannel(pChannel);
88 persson 2354 plugin->pMidiDevice->RemoveMidiPort(pPort);
89     plugin->pAudioDevice->RemoveChannel(pChannelLeft);
90     plugin->pAudioDevice->RemoveChannel(pChannelRight);
91    
92     const std::set<LinuxSampler::EngineChannel*>& engineChannels =
93     LinuxSampler::EngineChannelFactory::EngineChannelInstances();
94     for (std::set<LinuxSampler::EngineChannel*>::iterator i = engineChannels.begin();
95     i != engineChannels.end() ; ++i) {
96     if ((*i)->GetAudioOutputDevice() == plugin->pAudioDevice) {
97     int channelNumber = (*i)->OutputChannel(0);
98     if (channelNumber > oldChannelNumber) {
99     (*i)->SetOutputChannel(0, channelNumber - 2);
100     (*i)->SetOutputChannel(1, channelNumber - 1);
101     }
102     }
103     }
104 persson 1858 }
105 persson 1777 }
106    
107 persson 1858 void PluginInstance::ConnectPort(unsigned long Port, LADSPA_Data* DataLocation) {
108 persson 1777 if (Port < 2) Out[Port] = DataLocation;
109     }
110    
111 persson 1858 char* PluginInstance::Configure(const char* Key, const char* Value) {
112 persson 1777 dmsg(2, ("linuxsampler: configure Key=%s Value=%s\n", Key, Value));
113    
114     if (strcmp(Key, "instrument") == 0 && strcmp(Value, "") != 0) {
115     String filename(Value);
116     String::size_type colon = filename.rfind(':');
117     int instrument = 0;
118     if (colon != String::npos) {
119     std::stringstream(String(filename, colon + 1)) >> instrument;
120     filename.erase(colon);
121     }
122     try {
123     LinuxSampler::EngineChannel* engineChannel =
124     pChannel->GetEngineChannel();
125     dmsg(2, (" before LoadInstrument\n"));
126     engineChannel->PrepareLoadInstrument(filename.c_str(),
127     instrument);
128     engineChannel->LoadInstrument();
129     dmsg(2, (" after LoadInstrument\n"));
130     }
131     catch (std::exception& e) {
132     return strdup(e.what());
133     }
134     }
135    
136     return 0;
137     }
138    
139 persson 1858 inline void PluginInstance::RunMultipleSynths(unsigned long InstanceCount,
140     LADSPA_Handle* Instances,
141     unsigned long SampleCount,
142     snd_seq_event_t** Events,
143     unsigned long* EventCounts) {
144     if (InstanceCount == 0) return;
145    
146     LinuxSampler::AudioOutputDevicePlugin* audioDevice =
147     static_cast<PluginInstance*>(Instances[0])->plugin->pAudioDevice;
148    
149     unsigned eventPosArr[InstanceCount];
150     for (unsigned long i = 0 ; i < InstanceCount ; i++) eventPosArr[i] = 0;
151    
152 persson 1777 int samplePos = 0;
153     while (SampleCount) {
154     int samples = std::min(SampleCount, 128UL);
155    
156 persson 1858 for (unsigned long i = 0 ; i < InstanceCount ; i++) {
157     PluginInstance* instance = static_cast<PluginInstance*>(Instances[i]);
158 persson 2354 LinuxSampler::MidiInputPort* port = instance->pPort;
159 persson 1777
160 persson 1858 snd_seq_event_t* events = Events[i];
161     unsigned& eventPos = eventPosArr[i];
162    
163     for ( ; eventPos < EventCounts[i] ; eventPos++) {
164     snd_seq_event_t* ev = &events[eventPos];
165     int time = ev->time.tick - samplePos;
166     if (time >= samples) break;
167     switch (ev->type) {
168     case SND_SEQ_EVENT_CONTROLLER:
169     port->DispatchControlChange(ev->data.control.param,
170     ev->data.control.value,
171     ev->data.control.channel, time);
172     break;
173    
174     case SND_SEQ_EVENT_CHANPRESS:
175     port->DispatchControlChange(128, ev->data.control.value,
176     ev->data.control.channel, time);
177     break;
178    
179     case SND_SEQ_EVENT_PITCHBEND:
180     port->DispatchPitchbend(ev->data.control.value,
181 persson 1777 ev->data.control.channel, time);
182 persson 1858 break;
183 persson 1777
184 persson 1858 case SND_SEQ_EVENT_NOTEON:
185     port->DispatchNoteOn(ev->data.note.note,
186     ev->data.note.velocity,
187     ev->data.control.channel, time);
188     break;
189 persson 1777
190 persson 1858 case SND_SEQ_EVENT_NOTEOFF:
191     port->DispatchNoteOff(ev->data.note.note,
192     ev->data.note.velocity,
193     ev->data.control.channel, time);
194     break;
195 persson 1777
196 persson 1858 case SND_SEQ_EVENT_SYSEX:
197     port->DispatchSysex(ev->data.ext.ptr, ev->data.ext.len);
198     break;
199     }
200     }
201 persson 1777
202 persson 2354 instance->pChannelLeft->SetBuffer(instance->Out[0] + samplePos);
203     instance->pChannelRight->SetBuffer(instance->Out[1] + samplePos);
204 persson 1777 }
205    
206 persson 1858 audioDevice->Render(samples);
207 persson 1777
208     samplePos += samples;
209     SampleCount -= samples;
210     }
211     }
212    
213 persson 1858 void PluginInstance::Activate() {
214 persson 1777 dmsg(2, ("linuxsampler: activate instance=%p\n", static_cast<void*>(this)));
215 persson 2354 pPort->DispatchControlChange(123, 0, 0, 0); // all sound off
216 persson 1777 }
217    
218    
219     // *************** LADSPA callback functions ***************
220     // *
221    
222     LADSPA_Handle instantiate(const LADSPA_Descriptor* Descriptor,
223     unsigned long SampleRate) {
224 persson 1858 return new PluginInstance(SampleRate);
225 persson 1777 }
226    
227     void cleanup(LADSPA_Handle Instance) {
228     dmsg(2, ("linuxsampler: cleanup Instance=%p\n", static_cast<void*>(Instance)));
229 persson 1858 delete static_cast<PluginInstance*>(Instance);
230 persson 1777 }
231    
232     void activate(LADSPA_Handle Instance) {
233 persson 1858 static_cast<PluginInstance*>(Instance)->Activate();
234 persson 1777 }
235    
236     void connect_port(LADSPA_Handle Instance, unsigned long Port,
237     LADSPA_Data* DataLocation) {
238 persson 1858 static_cast<PluginInstance*>(Instance)->ConnectPort(Port, DataLocation);
239 persson 1777 }
240    
241     void run(LADSPA_Handle Instance, unsigned long SampleCount) {
242 persson 1858 return;
243 persson 1777 }
244    
245    
246     // *************** DSSI callback functions ***************
247     // *
248    
249     void run_multiple_synths(unsigned long InstanceCount,
250     LADSPA_Handle* Instances,
251     unsigned long SampleCount,
252     snd_seq_event_t** Events,
253 persson 1858 unsigned long* EventCounts) {
254     PluginInstance::RunMultipleSynths(InstanceCount, Instances,
255     SampleCount, Events,
256     EventCounts);
257 persson 1777 }
258    
259     char* configure(LADSPA_Handle Instance, const char* Key, const char* Value) {
260 persson 1858 return static_cast<PluginInstance*>(Instance)->Configure(Key, Value);
261 persson 1777 }
262    
263    
264     // *************** PluginInfo ***************
265     // *
266    
267     PluginInfo PluginInfo::Instance;
268    
269     PluginInfo::PluginInfo() {
270     Ladspa.UniqueID = 3781; // (received from ladspa.org)
271     Ladspa.Label = "LinuxSampler";
272     Ladspa.Properties = 0;
273     Ladspa.Name = "LinuxSampler";
274     Ladspa.Maker = "linuxsampler.org";
275     Ladspa.Copyright = "(C) 2003,2004 Benno Senoner and Christian Schoenebeck, "
276 persson 2326 "2005-2012 Christian Schoenebeck";
277 persson 1777 Ladspa.PortCount = 2;
278     Ladspa.ImplementationData = 0;
279     Ladspa.PortDescriptors = PortDescriptors;
280     Ladspa.PortRangeHints = PortRangeHints;
281     Ladspa.PortNames = PortNames;
282    
283     PortDescriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
284     PortNames[0] = "Output Left";
285     PortRangeHints[0].HintDescriptor = 0;
286     PortDescriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
287     PortNames[1] = "Output Right";
288     PortRangeHints[1].HintDescriptor = 0;
289    
290     Ladspa.activate = activate;
291     Ladspa.cleanup = cleanup;
292     Ladspa.connect_port = connect_port;
293     Ladspa.deactivate = 0;
294     Ladspa.instantiate = instantiate;
295     Ladspa.run = run;
296     Ladspa.run_adding = 0;
297     Ladspa.set_run_adding_gain = 0;
298    
299     Dssi.DSSI_API_Version = 1;
300     Dssi.LADSPA_Plugin = &Ladspa;
301     Dssi.configure = configure;
302     Dssi.get_program = 0;
303     Dssi.get_midi_controller_for_port = 0;
304     Dssi.select_program = 0;
305 persson 1858 Dssi.run_synth = 0;
306 persson 1777 Dssi.run_synth_adding = 0;
307     Dssi.run_multiple_synths = run_multiple_synths;
308     Dssi.run_multiple_synths_adding = 0;
309     }
310     }
311    
312    
313     extern "C" {
314     const LADSPA_Descriptor* ladspa_descriptor(unsigned long Index) {
315     dmsg(2, ("linuxsampler: ladspa_descriptor\n"));
316     return Index == 0 ? PluginInfo::LadspaDescriptor() : 0;
317     }
318    
319     const DSSI_Descriptor *dssi_descriptor(unsigned long Index) {
320     dmsg(2, ("linuxsampler: dssi_descriptor\n"));
321     return Index == 0 ? PluginInfo::DssiDescriptor() : 0;
322     }
323     }

  ViewVC Help
Powered by ViewVC