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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2390 - (show annotations) (download)
Sat Jan 5 12:31:05 2013 UTC (11 years, 3 months ago) by persson
File size: 12910 byte(s)
* fixed compilation with Clang 3.2

1 /***************************************************************************
2 * *
3 * Copyright (C) 2008 - 2013 Andreas Persson *
4 * *
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 #include "../../engines/AbstractEngineChannel.h"
30 #include "../../engines/EngineChannelFactory.h"
31
32 namespace {
33
34 // *************** PluginDssi ***************
35 // *
36
37 PluginDssi::PluginDssi(unsigned long SampleRate) :
38 RefCount(0) {
39 // 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 }
44
45 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 pChannel->SetEngineType("gig");
58 pChannel->SetAudioOutputDevice(plugin->pAudioDevice);
59
60 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 LinuxSampler::AbstractEngineChannel* engineChannel =
69 static_cast<LinuxSampler::AbstractEngineChannel*>(pChannel->GetEngineChannel());
70 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 }
77
78 PluginInstance::~PluginInstance() {
79 if (--plugin->RefCount == 0) {
80 delete plugin;
81 plugin = 0;
82 } else {
83 LinuxSampler::AbstractEngineChannel* engineChannel =
84 static_cast<LinuxSampler::AbstractEngineChannel*>(pChannel->GetEngineChannel());
85 int oldChannelNumber = engineChannel->OutputChannel(0);
86
87 plugin->global->pSampler->RemoveSamplerChannel(pChannel);
88 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 }
105 }
106
107 void PluginInstance::ConnectPort(unsigned long Port, LADSPA_Data* DataLocation) {
108 if (Port < 2) Out[Port] = DataLocation;
109 }
110
111 char* PluginInstance::Configure(const char* Key, const char* Value) {
112 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 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 int samplePos = 0;
153 while (SampleCount) {
154 int samples = std::min(SampleCount, 128UL);
155
156 for (unsigned long i = 0 ; i < InstanceCount ; i++) {
157 PluginInstance* instance = static_cast<PluginInstance*>(Instances[i]);
158 LinuxSampler::MidiInputPort* port = instance->pPort;
159
160 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 ev->data.control.channel, time);
182 break;
183
184 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
190 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
196 case SND_SEQ_EVENT_SYSEX:
197 port->DispatchSysex(ev->data.ext.ptr, ev->data.ext.len);
198 break;
199 }
200 }
201
202 instance->pChannelLeft->SetBuffer(instance->Out[0] + samplePos);
203 instance->pChannelRight->SetBuffer(instance->Out[1] + samplePos);
204 }
205
206 audioDevice->Render(samples);
207
208 samplePos += samples;
209 SampleCount -= samples;
210 }
211 }
212
213 void PluginInstance::Activate() {
214 dmsg(2, ("linuxsampler: activate instance=%p\n", static_cast<void*>(this)));
215 pPort->DispatchControlChange(123, 0, 0, 0); // all sound off
216 }
217
218
219 // *************** LADSPA callback functions ***************
220 // *
221
222 LADSPA_Handle instantiate(const LADSPA_Descriptor* Descriptor,
223 unsigned long SampleRate) {
224 return new PluginInstance(SampleRate);
225 }
226
227 void cleanup(LADSPA_Handle Instance) {
228 dmsg(2, ("linuxsampler: cleanup Instance=%p\n", static_cast<void*>(Instance)));
229 delete static_cast<PluginInstance*>(Instance);
230 }
231
232 void activate(LADSPA_Handle Instance) {
233 static_cast<PluginInstance*>(Instance)->Activate();
234 }
235
236 void connect_port(LADSPA_Handle Instance, unsigned long Port,
237 LADSPA_Data* DataLocation) {
238 static_cast<PluginInstance*>(Instance)->ConnectPort(Port, DataLocation);
239 }
240
241 void run(LADSPA_Handle Instance, unsigned long SampleCount) {
242 return;
243 }
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 unsigned long* EventCounts) {
254 PluginInstance::RunMultipleSynths(InstanceCount, Instances,
255 SampleCount, Events,
256 EventCounts);
257 }
258
259 char* configure(LADSPA_Handle Instance, const char* Key, const char* Value) {
260 return static_cast<PluginInstance*>(Instance)->Configure(Key, Value);
261 }
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 "2005-2013 Christian Schoenebeck";
277 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 Dssi.run_synth = 0;
306 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