1 //
2 // C++ Interface: plugin
3 //
4 // Description:
5 //
6 //
7 // (C) Copyright 2000 Werner Schweer (ws@seh.de)
8 // Additions/modifications: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
9 // (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net)
10 //
11 // This program is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU General Public License
13 // as published by the Free Software Foundation; version 2 of
14 // the License, or (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 //
25 //
26
27 #ifndef __SIMPLER_PLUGIN_H__
28 #define __SIMPLER_PLUGIN_H__
29
30 #include <vector>
31 #include <QFileInfo>
32 #include <QString>
33
34 #include <ladspa.h>
35 #include "muse_math.h"
36
37 #include "globaldefs.h"
38 #include "plugin_scan.h"
39
40 #define SS_PLUGIN_PARAM_MIN 0
41 #define SS_PLUGIN_PARAM_MAX 127
42
43 namespace MusESimplePlugin {
44
45 //---------------------------------------------------------
46 // Port
47 //---------------------------------------------------------
48
49 struct Port {
50 float _val;
51 };
52
53 //---------------------------------------------------------
54 // Plugin base class
55 //---------------------------------------------------------
56
57 class PluginI;
58
59 class Plugin
60 {
61 protected:
62 QFileInfo _fi;
63 void* _libHandle;
64 int _references;
65 int _instNo;
66 unsigned long _uniqueID;
67 QString _label;
68 QString _name;
69 QString _maker;
70 QString _copyright;
71
72 // Total number of ports.
73 unsigned long _portCount;
74 unsigned long _inports;
75 unsigned long _outports;
76 unsigned long _controlInPorts;
77 unsigned long _controlOutPorts;
78
79 MusECore::PluginFeatures_t _requiredFeatures;
80
81 std::vector<unsigned long> _pIdx; //control port numbers
82 std::vector<unsigned long> _poIdx; //control out port numbers
83 std::vector<unsigned long> _iIdx; //input port numbers
84 std::vector<unsigned long> _oIdx; //output port numbers
85
86 public:
Plugin(const QFileInfo * f)87 Plugin(const QFileInfo* f)
88 : _fi(*f), _libHandle(0), _references(0), _instNo(0), _uniqueID(0),
89 _portCount(0),_inports(0), _outports(0),
90 _controlInPorts(0),_controlOutPorts(0),
91 _requiredFeatures(MusECore::PluginNoFeatures) { }
92 Plugin(const MusEPlugin::PluginScanInfoStruct& info);
~Plugin()93 virtual ~Plugin() {}
94
95 //----------------------------------------------------
96 // The following methods can be called regardless of
97 // whether the libray is open or not, ie. zero or more
98 // instances exist. The information is cached.
99 //----------------------------------------------------
100
101 // Returns features required by the plugin.
requiredFeatures()102 MusECore::PluginFeatures_t requiredFeatures() const { return _requiredFeatures; }
103
104 // Create and initialize a plugin instance. Returns null if failure.
105 // Equivalent to calling (new ***PlugI())->initPluginInstance(this, ...).
106 // The returned type depends on the derived class (LadspaPluginI*, Lv2PluginI*, etc).
107 // Caller is responsible for deleting the returned object.
108 virtual PluginI* createPluginI(int chans, float sampleRate, unsigned int segmentSize,
109 bool useDenormalBias, float denormalBias) = 0;
110
references()111 int references() const { return _references; }
incReferences(int)112 virtual int incReferences(int) { return _references; }
instNo()113 int instNo() { return _instNo++; }
instantiate(float,void *)114 virtual void* instantiate(float /*sampleRate*/, void* /*data*/) { return 0; }
115
label()116 QString label() const { return _label; }
name()117 QString name() const { return _name; }
id()118 unsigned long id() const { return _uniqueID; }
maker()119 QString maker() const { return _maker; }
copyright()120 QString copyright() const { return _copyright; }
121 QString lib(bool complete = true) const { return complete ? _fi.completeBaseName() : _fi.baseName(); }
122 QString dirPath(bool complete = true) const { return complete ? _fi.absolutePath() : _fi.path(); }
filePath()123 QString filePath() const { return _fi.filePath(); }
fileName()124 QString fileName() const { return _fi.fileName(); }
125
126 // Total number of ports.
portCount()127 unsigned long portCount() const { return _portCount; }
parameter()128 unsigned long parameter() const { return _controlInPorts; }
parameterOut()129 unsigned long parameterOut() const { return _controlOutPorts; }
inports()130 unsigned long inports() const { return _inports; }
outports()131 unsigned long outports() const { return _outports; }
inPlaceCapable()132 bool inPlaceCapable() const { return !(_requiredFeatures & MusECore::PluginNoInPlaceProcessing); }
133
134
135 //----------------------------------------------------
136 // The following methods require the library be open,
137 // ie. at least one instance exists.
138 //----------------------------------------------------
139
isAudioIn(unsigned long)140 virtual bool isAudioIn(unsigned long) const { return false; }
isAudioOut(unsigned long)141 virtual bool isAudioOut(unsigned long) const { return false; }
isParameterIn(unsigned long)142 virtual bool isParameterIn(unsigned long) const { return false; }
isParameterOut(unsigned long)143 virtual bool isParameterOut(unsigned long) const { return false; }
144
isLog(unsigned long)145 virtual bool isLog(unsigned long) const { return false; }
isBool(unsigned long)146 virtual bool isBool(unsigned long) const { return false; }
isInt(unsigned long)147 virtual bool isInt(unsigned long) const { return false; }
isLinear(unsigned long)148 virtual bool isLinear(unsigned long) const { return false; }
defaultValue(unsigned long)149 virtual float defaultValue(unsigned long) const { return 0.0f; }
150 virtual bool range(unsigned long, float /*sampleRate*/, float* min, float* max) const = 0;
151 virtual bool rangeOut(unsigned long, float /*sampleRate*/, float* min, float* max) const = 0;
getParameterName(unsigned long)152 virtual const char* getParameterName(unsigned long /*param*/) const { return ""; }
getParameterOutName(unsigned long)153 virtual const char* getParameterOutName(unsigned long /*param*/) const { return ""; }
154
activate(void *)155 virtual void activate(void* /*handle*/) { }
deactivate(void *)156 virtual void deactivate(void* /*handle*/) { }
cleanup(void *)157 virtual void cleanup(void* /*handle*/) { }
connectInport(void *,unsigned long,void *)158 virtual void connectInport(void* /*handle*/, unsigned long, void* /*datalocation*/) { }
connectOutport(void *,unsigned long,void *)159 virtual void connectOutport(void* /*handle*/, unsigned long, void* /*datalocation*/) { }
connectCtrlInport(void *,unsigned long,void *)160 virtual void connectCtrlInport(void* /*handle*/, unsigned long, void* /*datalocation*/) { }
connectCtrlOutport(void *,unsigned long,void *)161 virtual void connectCtrlOutport(void* /*handle*/, unsigned long, void* /*datalocation*/) { }
connectPort(void *,unsigned long,float *)162 virtual void connectPort(void* /*handle*/, unsigned long /*port*/, float* /*value*/) { }
apply(void *,unsigned long)163 virtual void apply(void* /*handle*/, unsigned long /*n*/) { }
164 };
165
166 //---------------------------------------------------------
167 // LadspaPlugin
168 //---------------------------------------------------------
169
170 #define IS_AUDIO_IN (LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT)
171 #define IS_AUDIO_OUT (LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT)
172 #define IS_PARAMETER_IN (LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT)
173 #define IS_PARAMETER_OUT (LADSPA_PORT_CONTROL | LADSPA_PORT_OUTPUT)
174
175 class LadspaPlugin : public Plugin
176 {
177 private:
178 const LADSPA_Descriptor* _plugin;
179
180 // Accepts a master port index.
181 bool port_range(unsigned long k, float sampleRate, float* min, float* max) const;
182
183 public:
184 LadspaPlugin(const QFileInfo* f, const LADSPA_Descriptor_Function, const LADSPA_Descriptor* d);
185 LadspaPlugin(const MusEPlugin::PluginScanInfoStruct& info);
~LadspaPlugin()186 virtual ~LadspaPlugin() { }
187
188 // Create and initialize a LADSPA plugin instance. Returns null if failure.
189 // Equivalent to calling (new LadspaPlugI())->initPluginInstance(this, ...).
190 // The returned type depends on the this class (LadspaPluginI*, Lv2PluginI*, etc).
191 // Caller is responsible for deleting the returned object.
192 PluginI* createPluginI(int chans, float sampleRate, unsigned int segmentSize,
193 bool useDenormalBias, float denormalBias);
194
195 int incReferences(int);
196
isAudioIn(unsigned long k)197 bool isAudioIn(unsigned long k) const {
198 if(!_plugin)
199 return false;
200 return (_plugin->PortDescriptors[k] & IS_AUDIO_IN) == IS_AUDIO_IN;
201 }
isAudioOut(unsigned long k)202 bool isAudioOut(unsigned long k) const {
203 if(!_plugin)
204 return false;
205 return (_plugin->PortDescriptors[k] & IS_AUDIO_OUT) == IS_AUDIO_OUT;
206 }
isParameterIn(unsigned long k)207 bool isParameterIn(unsigned long k) const {
208 if(!_plugin)
209 return false;
210 return (_plugin->PortDescriptors[k] & IS_PARAMETER_IN) == IS_PARAMETER_IN;
211 }
isParameterOut(unsigned long k)212 bool isParameterOut(unsigned long k) const {
213 if(!_plugin)
214 return false;
215 return (_plugin->PortDescriptors[k] & IS_PARAMETER_OUT) == IS_PARAMETER_OUT;
216 }
217
isLog(unsigned long k)218 bool isLog(unsigned long k) const {
219 if(!_plugin)
220 return false;
221 LADSPA_PortRangeHint r = _plugin->PortRangeHints[_pIdx[k]];
222 return LADSPA_IS_HINT_LOGARITHMIC(r.HintDescriptor);
223 }
isBool(unsigned long k)224 bool isBool(unsigned long k) const {
225 if(!_plugin)
226 return false;
227 return LADSPA_IS_HINT_TOGGLED(_plugin->PortRangeHints[_pIdx[k]].HintDescriptor);
228 }
isInt(unsigned long k)229 bool isInt(unsigned long k) const {
230 if(!_plugin)
231 return false;
232 LADSPA_PortRangeHint r = _plugin->PortRangeHints[_pIdx[k]];
233 return LADSPA_IS_HINT_INTEGER(r.HintDescriptor);
234 }
isLinear(unsigned long k)235 bool isLinear(unsigned long k) const {
236 if(!_plugin)
237 return false;
238 LADSPA_PortRangeHint r = _plugin->PortRangeHints[_pIdx[k]];
239 return !LADSPA_IS_HINT_INTEGER(r.HintDescriptor) &&
240 !LADSPA_IS_HINT_LOGARITHMIC(r.HintDescriptor) &&
241 !LADSPA_IS_HINT_TOGGLED(r.HintDescriptor);
242 }
243 bool range(unsigned long k, float sampleRate, float*, float*) const;
244 bool rangeOut(unsigned long k, float sampleRate, float*, float*) const;
getParameterName(unsigned long k)245 const char* getParameterName(unsigned long k) const {
246 if(!_plugin)
247 return 0;
248 return _plugin->PortNames[_pIdx[k]];
249 }
getParameterOutName(unsigned long k)250 const char* getParameterOutName(unsigned long k) const {
251 if(!_plugin)
252 return 0;
253 return _plugin->PortNames[_poIdx[k]];
254 }
255 float defaultValue(unsigned long k) const;
256
257 float convertGuiControlValue(unsigned long k, float sampleRate, int val) const;
258
259 void* instantiate(float sampleRate, void* /*data*/);
260 void connectInport(void* handle, unsigned long k, void* datalocation);
261 void connectOutport(void* handle, unsigned long k, void* datalocation);
262 void connectCtrlInport(void* handle, unsigned long k, void* datalocation);
263 void connectCtrlOutport(void* handle, unsigned long k, void* datalocation);
264
activate(void * handle)265 void activate(void* handle) {
266 if (_plugin && _plugin->activate)
267 _plugin->activate((LADSPA_Handle)handle);
268 }
deactivate(void * handle)269 void deactivate(void* handle) {
270 if (_plugin && _plugin->deactivate)
271 _plugin->deactivate((LADSPA_Handle)handle);
272 }
cleanup(void * handle)273 void cleanup(void* handle) {
274 if (_plugin && _plugin->cleanup)
275 _plugin->cleanup((LADSPA_Handle)handle);
276 }
connectPort(void * handle,unsigned long port,float * datalocation)277 void connectPort(void* handle, unsigned long port, float* datalocation) {
278 if(_plugin)
279 _plugin->connect_port((LADSPA_Handle)handle, port, datalocation);
280 }
apply(void * handle,unsigned long n)281 void apply(void* handle, unsigned long n) {
282 if(_plugin && _plugin->run)
283 _plugin->run((LADSPA_Handle)handle, n);
284 }
285 };
286
287 //--------------------------------
288 // PluginI
289 // Plugin Instance base class
290 //--------------------------------
291
292 class PluginI {
293 private:
294 void init();
295
296 protected:
297 Plugin* _plugin;
298 // Some APIs may need to point to a float or double samplerate, or both (LV2).
299 float _sampleRate;
300 double _dSampleRate;
301 unsigned int _segmentSize;
302 int _channel;
303 int _instances;
304 int _id;
305
306 Port* _controls;
307 Port* _controlsOut;
308 Port* _controlsOutDummy;
309
310 unsigned long _audioInPorts;
311 unsigned long _audioOutPorts;
312 unsigned long _controlPorts;
313 unsigned long _controlOutPorts;
314
315 bool _hasLatencyOutPort;
316 unsigned long _latencyOutPort;
317
318 float *_audioInSilenceBuf; // Just all zeros all the time, so we don't have to clear for silence.
319 float *_audioOutDummyBuf; // A place to connect unused outputs.
320
321 bool _on;
322 QString _name;
323 QString _label;
324
325 public:
326 PluginI();
327 virtual ~PluginI();
328
plugin()329 Plugin* plugin() const { return _plugin; }
330
requiredFeatures()331 MusECore::PluginFeatures_t requiredFeatures() const {
332 if(!_plugin) return MusECore::PluginNoFeatures;
333 return _plugin->requiredFeatures(); }
334
on()335 bool on() const { return _on; }
setOn(bool val)336 void setOn(bool val) { _on = val; }
337
pluginID()338 unsigned long pluginID() { return _plugin->id(); }
339 void setID(int i);
id()340 int id() { return _id; }
341
inPlaceCapable()342 bool inPlaceCapable() const {
343 if(!_plugin) return false;
344 return _plugin->inPlaceCapable();
345 }
346
347 // Returns true on error.
348 virtual bool initPluginInstance(Plugin* plug, int channels,
349 float sampleRate, unsigned int segmentSize,
350 bool useDenormalBias, float denormalBias) = 0;
sampleRate()351 float sampleRate() const { return _sampleRate; }
setSampleRate(float rate)352 void setSampleRate(float rate) { _sampleRate = rate; _dSampleRate = rate; }
segmentSize()353 unsigned int segmentSize() const { return _segmentSize; }
channels()354 int channels() const { return _channel; }
355 virtual void setChannels(int chans) = 0;
356 // Runs the plugin for frames. Any ports involved must already be connected.
357 virtual void process(unsigned long frames) = 0;
358 // Runs the plugin for frames. This automatically connects the given
359 // data locations to the ports each time it is called.
360 void apply(unsigned pos, unsigned long frames, unsigned long ports, float** bufIn, float** bufOut);
361
362 // Connects ports with data locations. Multiple sources and destinations, with offset.
363 virtual void connect(unsigned long ports, unsigned long offset, float** src, float** dst) = 0;
364 // // Connects a single audio input port to a data location.
365 // void connectInport(unsigned long k, void* datalocation);
366 // // Connects a single audio output port to a data location.
367 // void connectOutport(unsigned long k, void* datalocation);
368 // // Connects a single control parameter input port to a data location.
369 // void connectCtrlInport(unsigned long k, void* datalocation);
370 // // Connects a single control parameter output port to a data location.
371 // void connectCtrlOutport(unsigned long k, void* datalocation);
372
373 // Returns true on success.
374 bool start();
375 // Returns true on success.
376 bool stop();
377
isAudioIn(unsigned long k)378 bool isAudioIn(unsigned long k) {
379 if(!_plugin) return false;
380 return _plugin->isAudioIn(k);
381 }
382
isAudioOut(unsigned long k)383 bool isAudioOut(unsigned long k) {
384 if(!_plugin) return false;
385 return _plugin->isAudioOut(k);
386 }
387
isLog(unsigned long k)388 bool isLog(unsigned long k) const {
389 if(!_plugin) return false;
390 return _plugin->isLog(k);
391 }
isBool(unsigned long k)392 bool isBool(unsigned long k) const {
393 if(!_plugin) return false;
394 return _plugin->isBool(k);
395 }
isInt(unsigned long k)396 bool isInt(unsigned long k) const {
397 if(!_plugin) return false;
398 return _plugin->isInt(k);
399 }
isLinear(unsigned long k)400 bool isLinear(unsigned long k) const {
401 if(!_plugin) return false;
402 return _plugin->isLinear(k);
403 }
404
range(unsigned long i,float * min,float * max)405 void range(unsigned long i, float* min, float* max) const {
406 if(!_plugin) return;
407 _plugin->range(i, _sampleRate, min, max);
408 }
rangeOut(unsigned long i,float * min,float * max)409 void rangeOut(unsigned long i, float* min, float* max) const {
410 if(!_plugin) return;
411 _plugin->rangeOut(i, _sampleRate, min, max);
412 }
getParameterName(unsigned long i)413 const char* getParameterName(unsigned long i) const {
414 if(!_plugin) return 0;
415 return _plugin->getParameterName(i);
416 }
getParameterOutName(unsigned long i)417 const char* getParameterOutName(unsigned long i) const {
418 if(!_plugin) return 0;
419 return _plugin->getParameterOutName(i);
420 }
defaultValue(unsigned long i)421 float defaultValue(unsigned long i) const {
422 if(!_plugin) return 0.0;
423 return _plugin->defaultValue(i);
424 }
425
426 // Return true on success.
427 virtual bool activate() = 0;
428 // Return true on success.
429 virtual bool deactivate() = 0;
pluginLabel()430 QString pluginLabel() const { return _plugin->label(); }
label()431 QString label() const { return _label; }
name()432 QString name() const { return _name; }
lib()433 QString lib() const { return _plugin->lib(); }
dirPath()434 QString dirPath() const { return _plugin->dirPath(); }
fileName()435 QString fileName() const { return _plugin->fileName(); }
436
437 bool setControl(const QString& s, float val);
438
inports()439 unsigned long inports() const { return _audioInPorts; }
outports()440 unsigned long outports() const { return _audioOutPorts; }
parameters()441 unsigned long parameters() const { return _controlPorts; }
parametersOut()442 unsigned long parametersOut() const { return _controlOutPorts; }
443
444 void setParam(unsigned long i, float val);
param(unsigned long i)445 float param(unsigned long i) const { if(i >= _controlPorts) return 0.0; return _controls[i]._val; }
paramOut(unsigned long i)446 float paramOut(unsigned long i) const { if(i >= _controlOutPorts) return 0.0; return _controlsOut[i]._val; }
447
448 // Alias for getParameterName.
paramName(unsigned long i)449 const char* paramName(unsigned long i) const { return getParameterName(i); }
paramOutName(unsigned long i)450 const char* paramOutName(unsigned long i) const { return getParameterOutName(i); }
451
452 float latency() const;
453 //CtrlValueType ctrlValueType(unsigned long i) const { return _plugin->ctrlValueType(controls[i].idx); }
454 //CtrlList::Mode ctrlMode(unsigned long i) const { return _plugin->ctrlMode(controls[i].idx); }
455
456 int getGuiControlValue(unsigned long parameter) const;
457 float convertGuiControlValue(unsigned long parameter, int val) const;
458 };
459
460
461 //--------------------------------
462 // LadspaPluginI
463 // Ladspa Plugin Instance class
464 //--------------------------------
465
466 class LadspaPluginI : public PluginI {
467 private:
468 LADSPA_Handle* _handle; // per instance
469 void init();
470
471 public:
472 LadspaPluginI();
473 virtual ~LadspaPluginI();
474
475 // Returns true on error.
476 bool initPluginInstance(Plugin* plug, int channels,
477 float sampleRate, unsigned int segmentSize,
478 bool useDenormalBias, float denormalBias);
479 void setChannels(int chans);
480 // Runs the plugin for frames. Any ports involved must already be connected.
481 void process(unsigned long frames);
482
483 // Connects ports with data locations. Multiple sources and destinations, with offset.
484 void connect(unsigned long ports, unsigned long offset, float** src, float** dst);
485 // // Connects a single audio input port to a data location.
486 // void connectInport(unsigned long k, void* datalocation);
487 // // Connects a single audio output port to a data location.
488 // void connectOutport(unsigned long k, void* datalocation);
489 // // Connects a single control parameter input port to a data location.
490 // void connectCtrlInport(unsigned long k, void* datalocation);
491 // // Connects a single control parameter output port to a data location.
492 // void connectCtrlOutport(unsigned long k, void* datalocation);
493
494 // Return true on success.
495 bool activate();
496 // Return true on success.
497 bool deactivate();
498 };
499
fast_log2(float val)500 static inline float fast_log2 (float val)
501 {
502 /* don't use reinterpret_cast<> because that prevents this
503 from being used by pure C code (for example, GnomeCanvasItems)
504 */
505 int* const exp_ptr = (int *)(&val);
506 int x = *exp_ptr;
507 const int log_2 = ((x >> 23) & 255) - 128;
508 x &= ~(255 << 23);
509 x += 127 << 23;
510 *exp_ptr = x;
511 val = ((-1.0f/3) * val + 2) * val - 2.0f/3; // (1)
512 return (val + log_2);
513 }
514
fast_log10(const float val)515 static inline float fast_log10 (const float val)
516 {
517 return fast_log2(val) / 3.312500f;
518 }
519
520 //---------------------------------------------------------
521 // PluginList
522 //---------------------------------------------------------
523
524 typedef std::list<Plugin*>::iterator iPlugin;
525
526 class PluginList : public std::list<Plugin*> {
527 public:
528 Plugin* find(const QString& file, const QString& name);
PluginList()529 PluginList() {}
530 ~PluginList();
531 };
532
533 extern void SS_initPlugins(const QString& hostCachePath);
534 extern PluginList plugins;
535
536 } // namespace MusESimplePlugin
537
538 #endif
539