1 //========================================================= 2 // MusE 3 // Linux Music Editor 4 // $Id: plugin.h,v 1.9.2.13 2009/12/06 01:25:21 terminator356 Exp $ 5 // 6 // (C) Copyright 2000 Werner Schweer (ws@seh.de) 7 // (C) Copyright 2011-2016 Tim E. Real (terminator356 on sourceforge) 8 // 9 // This program is free software; you can redistribute it and/or 10 // modify it under the terms of the GNU General Public License 11 // as published by the Free Software Foundation; version 2 of 12 // the License, or (at your option) any later version. 13 // 14 // This program is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with this program; if not, write to the Free Software 21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 // 23 //========================================================= 24 25 #ifndef __PLUGIN_H__ 26 #define __PLUGIN_H__ 27 28 #include <list> 29 #include <vector> 30 #include <QSet> 31 #include <QMap> 32 #include <QPair> 33 #include <QFileInfo> 34 #include <QMainWindow> 35 #include <QMouseEvent> 36 #include <QUiLoader> 37 #include <QRect> 38 #include <QList> 39 40 #include <ladspa.h> 41 42 #include "globaldefs.h" 43 #include "ctrl.h" 44 #include "controlfifo.h" 45 #include "config.h" 46 47 #ifdef OSC_SUPPORT 48 #include "osc.h" 49 #endif 50 51 #ifdef DSSI_SUPPORT 52 #include <dssi.h> 53 #endif 54 55 // BUG I have filed a Qt bug report 64773. If we do NOT 56 // set a position on a new QWidget, Qt seems to take control 57 // of the position management such that it will NOT accept 58 // any new position after that! It seems to decide to 59 // remain in 'auto-placement' mode forever. 60 // If the bug is ever fixed by Qt, this define should then 61 // become version-sensitive. 2017/11/28 Tim. 62 #define QT_SHOW_POS_BUG_WORKAROUND 1; 63 64 65 // Forward declarations: 66 class QScrollArea; 67 class QShowEvent; 68 class QHideEvent; 69 class QAction; 70 class QSpinBox; 71 class QToolButton; 72 73 namespace MusEGui { 74 class PluginGui; 75 class DoubleLabel; 76 } 77 78 namespace MusEPlugin { 79 class PluginScanInfoStruct; 80 } 81 82 namespace MusECore { 83 class AudioTrack; 84 class Xml; 85 86 class PluginI; 87 88 //--------------------------------------------------------- 89 // Plugin 90 //--------------------------------------------------------- 91 92 class Plugin { 93 94 protected: 95 friend class PluginI; 96 97 void* _handle; 98 int _references; 99 int _instNo; 100 QFileInfo fi; 101 // Universal resource identifier, for plugins that use it (LV2). 102 // If this exists, it should be used INSTEAD of file info, for comparison etc. 103 // Never rely on the file info if a uri exists. 104 QString _uri; 105 LADSPA_Descriptor_Function ladspa; 106 const LADSPA_Descriptor *plugin; 107 unsigned long _uniqueID; 108 QString _label; 109 QString _name; 110 QString _maker; 111 QString _copyright; 112 113 bool _isDssiSynth; 114 bool _isDssi; 115 bool _isLV2Synth; 116 bool _isLV2Plugin; 117 // Hack: Special flag required. 118 bool _isDssiVst; 119 bool _isVstNativeSynth; 120 bool _isVstNativePlugin; 121 122 #ifdef DSSI_SUPPORT 123 const DSSI_Descriptor* dssi_descr; 124 #endif 125 126 unsigned long _portCount; 127 unsigned long _inports; 128 unsigned long _outports; 129 unsigned long _controlInPorts; 130 unsigned long _controlOutPorts; 131 std::vector<unsigned long> rpIdx; // Port number to control input index. Item is -1 if it's not a control input. 132 133 bool _usesTimePosition; 134 135 PluginFeatures_t _requiredFeatures; 136 137 public: Plugin()138 Plugin() {} //empty constructor for LV2PluginWrapper 139 Plugin(QFileInfo* f, const LADSPA_Descriptor* d, const QString& uri, 140 bool isDssi = false, bool isDssiSynth = false, bool isDssiVst = false, 141 PluginFeatures_t reqFeatures = PluginNoFeatures); 142 Plugin(const MusEPlugin::PluginScanInfoStruct&); 143 virtual ~Plugin(); requiredFeatures()144 virtual PluginFeatures_t requiredFeatures() const { return _requiredFeatures; } uri()145 QString uri() const { return _uri; } label()146 virtual QString label() const { return _label; } name()147 QString name() const { return _name; } id()148 unsigned long id() const { return _uniqueID; } maker()149 QString maker() const { return _maker; } copyright()150 QString copyright() const { return _copyright; } 151 QString lib(bool complete = true) const { return complete ? fi.completeBaseName() : fi.baseName(); } // ddskrjo const 152 QString dirPath(bool complete = true) const { return complete ? fi.absolutePath() : fi.path(); } filePath()153 QString filePath() const { return fi.filePath(); } fileName()154 QString fileName() const { return fi.fileName(); } 155 references()156 int references() const { return _references; } 157 virtual int incReferences(int); instNo()158 int instNo() { return _instNo++; } 159 isDssiPlugin()160 bool isDssiPlugin() const { return _isDssi; } isDssiSynth()161 bool isDssiSynth() const { return _isDssiSynth; } isLV2Plugin()162 inline bool isLV2Plugin() const { return _isLV2Plugin; } //inline it to use in RT audio thread isLV2Synth()163 bool isLV2Synth() const { return _isLV2Synth; } isVstNativePlugin()164 inline bool isVstNativePlugin() const { return _isVstNativePlugin; } //inline it to use in RT audio thread isVstNativeSynth()165 bool isVstNativeSynth() const { return _isVstNativeSynth; } 166 167 virtual LADSPA_Handle instantiate(PluginI *); activate(LADSPA_Handle handle)168 virtual void activate(LADSPA_Handle handle) { 169 if (plugin && plugin->activate) 170 plugin->activate(handle); 171 } deactivate(LADSPA_Handle handle)172 virtual void deactivate(LADSPA_Handle handle) { 173 if (plugin && plugin->deactivate) 174 plugin->deactivate(handle); 175 } cleanup(LADSPA_Handle handle)176 virtual void cleanup(LADSPA_Handle handle) { 177 if (plugin && plugin->cleanup) 178 plugin->cleanup(handle); 179 } connectPort(LADSPA_Handle handle,unsigned long port,float * value)180 virtual void connectPort(LADSPA_Handle handle, unsigned long port, float* value) { 181 if(plugin) 182 plugin->connect_port(handle, port, value); 183 } 184 virtual void apply(LADSPA_Handle handle, unsigned long n, float /*latency_corr*/ = 0.0f) { 185 if(plugin) 186 plugin->run(handle, n); 187 } 188 189 #ifdef OSC_SUPPORT 190 int oscConfigure(LADSPA_Handle handle, const char* key, const char* value); 191 #endif 192 ports()193 unsigned long ports() { return _portCount; } 194 portd(unsigned long k)195 virtual LADSPA_PortDescriptor portd(unsigned long k) const { 196 return plugin ? plugin->PortDescriptors[k] : 0; 197 } 198 range(unsigned long i)199 virtual LADSPA_PortRangeHint range(unsigned long i) { 200 // FIXME: 201 //return plugin ? plugin->PortRangeHints[i] : 0; DELETETHIS 202 return plugin->PortRangeHints[i]; 203 } 204 205 virtual double defaultValue(unsigned long port) const; 206 virtual void range(unsigned long i, float*, float*) const; 207 virtual CtrlValueType ctrlValueType(unsigned long i) const; 208 virtual CtrlList::Mode ctrlMode(unsigned long i) const; 209 virtual CtrlEnumValues* ctrlEnumValues ( unsigned long ) const; 210 portName(unsigned long i)211 virtual const char* portName(unsigned long i) { 212 return plugin ? plugin->PortNames[i] : 0; 213 } 214 usesTimePosition()215 bool usesTimePosition() const { return _usesTimePosition; } inports()216 unsigned long inports() const { return _inports; } outports()217 unsigned long outports() const { return _outports; } controlInPorts()218 unsigned long controlInPorts() const { return _controlInPorts; } controlOutPorts()219 unsigned long controlOutPorts() const { return _controlOutPorts; } 220 getRpIdx()221 const std::vector<unsigned long>* getRpIdx() { return &rpIdx; } 222 }; 223 224 typedef std::list<Plugin *>::iterator iPlugin; 225 typedef std::list<Plugin *>::const_iterator ciPlugin; 226 227 228 class PluginGroups : public QMap< QPair<QString, QString>, QSet<int> > 229 { 230 public: get(QString a,QString b)231 QSet<int>& get(QString a, QString b) { return (*this)[(QPair<QString,QString>(a,b))]; } get(const Plugin * p)232 QSet<int>& get(const Plugin *p) 233 { return (*this)[(QPair<QString,QString>(p->uri().isEmpty() ? p->lib() : p->uri(), p->label()))]; } 234 235 void shift_left(int first, int last); 236 void shift_right(int first, int last); 237 void erase(int index); 238 239 private: 240 void replace_group(int old, int now); 241 }; 242 243 244 //--------------------------------------------------------- 245 // PluginList 246 //--------------------------------------------------------- 247 248 class PluginList : public std::list<Plugin *> { 249 public: 250 void add(QFileInfo* fi, const LADSPA_Descriptor* d, const QString& uri, 251 bool isDssi = false, bool isDssiSynth = false, bool isDssiVst = false, 252 PluginFeatures_t reqFeatures = PluginNoFeatures) 253 { 254 push_back(new Plugin(fi, d, uri, isDssi, isDssiSynth, isDssiVst, reqFeatures)); 255 } 256 add(const MusEPlugin::PluginScanInfoStruct & scan_info)257 void add(const MusEPlugin::PluginScanInfoStruct& scan_info) 258 { push_back(new Plugin(scan_info)); } 259 260 // Each argument optional, can be empty. 261 // If uri is not empty, the search is based solely on it, the other arguments are ignored. 262 Plugin* find(const QString& file, const QString& uri, const QString& label) const; PluginList()263 PluginList() {} 264 }; 265 266 //--------------------------------------------------------- 267 // Port 268 //--------------------------------------------------------- 269 270 struct Port { 271 unsigned long idx; 272 273 // NOTE: These values represent the lowest level of control value storage. 274 // The choice of float or double depends on the underlying system using this struct. 275 // For example plugins and synthesizers usually use floats to represent control values 276 // and they are directly pointed to this float, while our own track controls 277 // (volume, pan etc.) take advantage of the double precision. 278 // Double precision is preferred if possible because above this lowest level all other 279 // controller usage is in double precision. Thus our very own track controllers are 280 // perfectly matched double precision throughout the system. 281 union { 282 float val; 283 double dval; 284 }; 285 union { 286 float tmpVal; // TODO Try once again and for all to remove this, was it really required? 287 //double dtmpVal; // Not used, should not be required. 288 }; 289 290 bool enCtrl; // Enable controller stream. 291 CtrlInterpolate interp; 292 }; 293 294 //--------------------------------------------------------- 295 // PluginQuirks 296 // An ugly but necessary class due to differences in plugin behaviour. 297 //--------------------------------------------------------- 298 299 class PluginQuirks 300 { 301 public: 302 enum NatUISCaling {GLOBAL, ON, OFF}; 303 // Whether the LV2 'speed' timePosition property switches to 0.0 in stop mode, or remains 304 // fixed at 1.0 regardless of play or stop mode. Fixes plugins like TAL NoiseMak3r 305 // stuck repeating small modulator segment at speed = 0.0. 306 bool _fixedSpeed; 307 // If the plugin uses our transport (ex. as an LV2 timePosition), sets whether the timePosition 308 // affects actual audio latency (not just say, beat or sequencer or arpeggiator latency). 309 // Example: LV2 Example Metronome. 310 bool _transportAffectsAudioLatency; 311 // Override the plugin's reported latency. Some plugins get it wrong or not quite right. 312 bool _overrideReportedLatency; 313 // Value to override the reported latency. 314 int _latencyOverrideValue; 315 PluginQuirks()316 PluginQuirks() : 317 _fixedSpeed(false), 318 _transportAffectsAudioLatency(false), 319 _overrideReportedLatency(false), 320 _latencyOverrideValue(0), 321 _fixNativeUIScaling(NatUISCaling::GLOBAL) 322 { } 323 324 void write(int level, Xml& xml) const; 325 // Return true on error. 326 bool read(Xml& xml); 327 bool fixNativeUIScaling() const; setFixNativeUIScaling(NatUISCaling fixScaling)328 void setFixNativeUIScaling(NatUISCaling fixScaling) { _fixNativeUIScaling = fixScaling; }; getFixNativeUIScaling()329 NatUISCaling getFixNativeUIScaling() const { return _fixNativeUIScaling; }; 330 331 private: 332 // Reverse scaling of native UI windows on HiDPI 333 NatUISCaling _fixNativeUIScaling; 334 }; 335 336 typedef enum { 337 PROP_NONE = -1, PROP_INT = 0, PROP_LONG, PROP_FLOAT, PROP_DOUBLE, PROP_BOOL, PROP_STRING, PROP_PATH 338 } PropType; 339 340 //--------------------------------------------------------- 341 // PluginIBase 342 //--------------------------------------------------------- 343 344 class PluginIBase 345 { 346 protected: 347 ControlFifo _controlFifo; 348 MusEGui::PluginGui* _gui; 349 QRect _guiGeometry; 350 QRect _nativeGuiGeometry; 351 PluginQuirks _quirks; 352 353 void makeGui(); 354 355 public: 356 PluginIBase(); 357 virtual ~PluginIBase(); 358 virtual PluginFeatures_t requiredFeatures() const = 0; 359 virtual bool hasBypass() const = 0; 360 virtual bool on() const = 0; 361 virtual void setOn(bool val) = 0; 362 virtual unsigned long pluginID() = 0; 363 virtual int id() = 0; 364 virtual QString pluginLabel() const = 0; 365 virtual QString name() const = 0; 366 virtual QString uri() const = 0; 367 virtual QString lib() const = 0; 368 virtual QString dirPath() const = 0; 369 virtual QString fileName() const = 0; 370 virtual QString titlePrefix() const = 0; 371 372 virtual AudioTrack* track() = 0; 373 374 virtual void enableController(unsigned long i, bool v = true) = 0; 375 virtual bool controllerEnabled(unsigned long i) const = 0; 376 virtual void enableAllControllers(bool v = true) = 0; 377 virtual void updateControllers() = 0; 378 379 virtual void activate() = 0; 380 virtual void deactivate() = 0; 381 382 virtual void writeConfiguration(int level, Xml& xml) = 0; 383 virtual bool readConfiguration(Xml& xml, bool readPreset=false) = 0; 384 385 virtual bool addScheduledControlEvent(unsigned long i, double val, unsigned frame); // returns true if event cannot be delivered 386 virtual unsigned long parameters() const = 0; 387 virtual unsigned long parametersOut() const = 0; 388 virtual void setParam(unsigned long i, double val) = 0; 389 virtual double param(unsigned long i) const = 0; 390 virtual double paramOut(unsigned long i) const = 0; 391 virtual const char* paramName(unsigned long i) = 0; 392 virtual const char* paramOutName(unsigned long i) = 0; 393 // FIXME TODO: Either find a way to agnosticize these two ranges, or change them from ladspa ranges to a new MusE range class. 394 virtual LADSPA_PortRangeHint range(unsigned long i) = 0; 395 virtual LADSPA_PortRangeHint rangeOut(unsigned long i) = 0; 396 397 virtual bool usesTransportSource() const = 0; 398 virtual bool hasLatencyOutPort() const = 0; 399 virtual unsigned long latencyOutPortIndex() const = 0; 400 virtual float latency() const = 0; cquirks()401 const PluginQuirks& cquirks() const { return _quirks; } quirks()402 PluginQuirks& quirks() { return _quirks; } 403 setCustomData(const std::vector<QString> &)404 virtual void setCustomData(const std::vector<QString> &) {/* Do nothing by default */} 405 virtual CtrlValueType ctrlValueType(unsigned long i) const = 0; 406 virtual CtrlList::Mode ctrlMode(unsigned long i) const = 0; 407 virtual CtrlEnumValues *ctrlEnumValues(unsigned long i) const; 408 virtual QString portGroup(long unsigned int i) const; 409 virtual bool ctrlIsTrigger(long unsigned int i) const; 410 virtual bool ctrlNotOnGui(long unsigned int i) const; 411 412 QString dssi_ui_filename() const; 413 gui()414 MusEGui::PluginGui* gui() const { return _gui; } 415 void deleteGui(); 416 417 virtual void showGui(); 418 virtual void showGui(bool); 419 virtual bool guiVisible() const; 420 // Sets the gui's geometry. Also updates the saved geometry. 421 virtual void setGeometry(int x, int y, int w, int h); 422 // Returns the current geometry of the gui, or if the gui does not exist, 423 // the saved gui geometry. 424 virtual void getGeometry(int *x, int *y, int *w, int *h) const; 425 // Saves the current gui geometry. 426 virtual void saveGeometry(int x, int y, int w, int h); 427 // Returns the saved gui geometry. 428 virtual void savedGeometry(int *x, int *y, int *w, int *h) const; 429 showNativeGui()430 virtual void showNativeGui() { } showNativeGui(bool)431 virtual void showNativeGui(bool) { } nativeGuiVisible()432 virtual bool nativeGuiVisible() const { return false; } 433 // Sets the gui's geometry. Also updates the saved geometry. 434 virtual void setNativeGeometry(int x, int y, int w, int h); 435 // Returns the current geometry of the gui, or if the gui does not exist, 436 // the saved gui geometry. 437 virtual void getNativeGeometry(int *x, int *y, int *w, int *h) const; 438 // Saves the current gui geometry. 439 virtual void saveNativeGeometry(int x, int y, int w, int h); 440 // Returns the saved gui geometry. 441 virtual void savedNativeGeometry(int *x, int *y, int *w, int *h) const; 442 }; 443 444 //--------------------------------------------------------- 445 // PluginI 446 // plugin instance 447 //--------------------------------------------------------- 448 449 #define IS_AUDIO_IN (LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT) 450 #define IS_AUDIO_OUT (LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT) 451 452 class PluginI : public PluginIBase { 453 #ifdef LV2_SUPPORT 454 friend class LV2PluginWrapper; 455 friend class LV2Synth; 456 #endif 457 #ifdef VST_NATIVE_SUPPORT 458 friend class VstNativeSynth; 459 friend class VstNativePluginWrapper; 460 #endif 461 Plugin* _plugin; 462 int channel; 463 int instances; 464 AudioTrack* _track; 465 int _id; 466 467 LADSPA_Handle* handle; // per instance 468 Port* controls; 469 Port* controlsOut; 470 Port* controlsOutDummy; 471 472 unsigned long controlPorts; 473 unsigned long controlOutPorts; 474 475 bool _hasLatencyOutPort; 476 unsigned long _latencyOutPort; 477 478 float *_audioInSilenceBuf; // Just all zeros all the time, so we don't have to clear for silence. 479 float *_audioOutDummyBuf; // A place to connect unused outputs. 480 481 bool _on; 482 bool initControlValues; 483 QString _name; 484 QString _label; 485 486 #ifdef OSC_SUPPORT 487 OscEffectIF _oscif; 488 #endif 489 bool _showNativeGuiPending; 490 491 void init(); 492 493 public: 494 PluginI(); 495 virtual ~PluginI(); 496 plugin()497 Plugin* plugin() const { return _plugin; } 498 requiredFeatures()499 virtual PluginFeatures_t requiredFeatures() const { return _plugin->requiredFeatures(); } 500 hasBypass()501 bool hasBypass() const { return true; }; on()502 bool on() const { return _on; } setOn(bool val)503 void setOn(bool val) { _on = val; } 504 setTrack(AudioTrack * t)505 void setTrack(AudioTrack* t) { _track = t; } track()506 AudioTrack* track() { return _track; } pluginID()507 unsigned long pluginID() { return _plugin->id(); } 508 void setID(int i); id()509 int id() { return _id; } 510 void updateControllers(); 511 512 bool initPluginInstance(Plugin*, int channels); 513 void setChannels(int); 514 void connect(unsigned long ports, unsigned long offset, float** src, float** dst); 515 void apply(unsigned pos, unsigned long n, 516 unsigned long ports, float** bufIn, float** bufOut, float latency_corr_offset = 0.0f); 517 518 void enableController(unsigned long i, bool v = true) { controls[i].enCtrl = v; } controllerEnabled(unsigned long i)519 bool controllerEnabled(unsigned long i) const { return controls[i].enCtrl; } 520 void enableAllControllers(bool v = true); 521 522 void activate(); 523 void deactivate(); pluginLabel()524 QString pluginLabel() const { return _plugin->label(); } label()525 QString label() const { return _label; } name()526 QString name() const { return _name; } lib()527 QString lib() const { return _plugin->lib(); } uri()528 QString uri() const { return _plugin->uri(); } dirPath()529 QString dirPath() const { return _plugin->dirPath(); } fileName()530 QString fileName() const { return _plugin->fileName(); } 531 QString titlePrefix() const; 532 533 #ifdef OSC_SUPPORT oscIF()534 OscEffectIF& oscIF() { return _oscif; } 535 536 int oscControl(unsigned long dssiPort, float val); 537 int oscConfigure(const char *key, const char *val); 538 int oscUpdate(); 539 #endif 540 541 void writeConfiguration(int level, Xml& xml); 542 bool readConfiguration(Xml& xml, bool readPreset=false); 543 bool loadControl(Xml& xml); 544 bool setControl(const QString& s, double val); 545 void showGui(); 546 void showGui(bool); isDssiPlugin()547 bool isDssiPlugin() const { return _plugin->isDssiPlugin(); } isLV2Plugin()548 bool isLV2Plugin() const { return _plugin->isLV2Plugin(); } isVstNativePlugin()549 bool isVstNativePlugin() const { return _plugin->isVstNativePlugin(); } 550 void showNativeGui(); 551 void showNativeGui(bool); isShowNativeGuiPending()552 bool isShowNativeGuiPending() { return _showNativeGuiPending; } 553 bool nativeGuiVisible() const; 554 parameters()555 unsigned long parameters() const { return controlPorts; } parametersOut()556 unsigned long parametersOut() const { return controlOutPorts; } 557 void setParam(unsigned long i, double val); putParam(unsigned long i,double val)558 void putParam(unsigned long i, double val) { controls[i].val = controls[i].tmpVal = val; } param(unsigned long i)559 double param(unsigned long i) const { return controls[i].val; } paramOut(unsigned long i)560 double paramOut(unsigned long i) const { return controlsOut[i].val; } 561 double defaultValue(unsigned long param) const; paramName(unsigned long i)562 const char* paramName(unsigned long i) { return _plugin->portName(controls[i].idx); } paramOutName(unsigned long i)563 const char* paramOutName(unsigned long i) { return _plugin->portName(controlsOut[i].idx); } portd(unsigned long i)564 LADSPA_PortDescriptor portd(unsigned long i) const { return _plugin->portd(controls[i].idx); } range(unsigned long i,float * min,float * max)565 void range(unsigned long i, float* min, float* max) const { _plugin->range(controls[i].idx, min, max); } isAudioIn(unsigned long k)566 bool isAudioIn(unsigned long k) { return (_plugin->portd(k) & IS_AUDIO_IN) == IS_AUDIO_IN; } isAudioOut(unsigned long k)567 bool isAudioOut(unsigned long k) { return (_plugin->portd(k) & IS_AUDIO_OUT) == IS_AUDIO_OUT; } range(unsigned long i)568 LADSPA_PortRangeHint range(unsigned long i) { return _plugin->range(controls[i].idx); } rangeOut(unsigned long i)569 LADSPA_PortRangeHint rangeOut(unsigned long i) { return _plugin->range(controlsOut[i].idx); } usesTransportSource()570 bool usesTransportSource() const { return _plugin->usesTimePosition(); }; hasLatencyOutPort()571 bool hasLatencyOutPort() const { return _hasLatencyOutPort; } latencyOutPortIndex()572 unsigned long latencyOutPortIndex() const { return _latencyOutPort; } 573 float latency() const; ctrlValueType(unsigned long i)574 CtrlValueType ctrlValueType(unsigned long i) const { return _plugin->ctrlValueType(controls[i].idx); } ctrlEnumValues(unsigned long i)575 CtrlEnumValues* ctrlEnumValues( unsigned long i) const { return _plugin->ctrlEnumValues(controls[i].idx); } ctrlMode(unsigned long i)576 CtrlList::Mode ctrlMode(unsigned long i) const { return _plugin->ctrlMode(controls[i].idx); } 577 virtual void setCustomData(const std::vector<QString> &customParams); 578 }; 579 580 //--------------------------------------------------------- 581 // Pipeline 582 // chain of connected efx inserts 583 //--------------------------------------------------------- 584 585 class Pipeline : public std::vector<PluginI*> { 586 private: 587 float* buffer[MusECore::MAX_CHANNELS]; 588 void initBuffers(); 589 public: 590 Pipeline(); 591 Pipeline(const Pipeline&, AudioTrack*); 592 ~Pipeline(); 593 void insert(PluginI* p, int index); 594 void remove(int index); 595 void removeAll(); 596 bool isOn(int idx) const; 597 void setOn(int, bool); 598 QString label(int idx) const; 599 QString name(int idx) const; 600 QString uri(int idx) const; 601 void showGui(int, bool); 602 bool isDssiPlugin(int) const; 603 bool isLV2Plugin(int idx) const; 604 bool isVstNativePlugin(int idx) const; 605 bool has_dssi_ui(int idx) const; 606 void showNativeGui(int, bool); 607 void deleteGui(int idx); 608 void deleteAllGuis(); 609 bool guiVisible(int); 610 bool nativeGuiVisible(int); 611 void apply(unsigned pos, unsigned long ports, unsigned long nframes, float** buffer); 612 void move(int idx, bool up); 613 bool empty(int idx) const; 614 void setChannels(int); 615 bool addScheduledControlEvent(int track_ctrl_id, double val, unsigned frame); // returns true if event cannot be delivered 616 void enableController(int track_ctrl_id, bool en); 617 bool controllerEnabled(int track_ctrl_id); 618 float latency() const; 619 }; 620 621 typedef Pipeline::iterator iPluginI; 622 typedef Pipeline::const_iterator ciPluginI; 623 624 extern void initPlugins(); 625 626 extern bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, unsigned long port, float* val); 627 extern void ladspaControlRange(const LADSPA_Descriptor* plugin, unsigned long port, float* min, float* max); 628 extern bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, unsigned long port, int ctlnum, int* min, int* max, int* def); 629 extern float midi2LadspaValue(const LADSPA_Descriptor* plugin, unsigned long port, int ctlnum, int val); 630 extern CtrlValueType ladspaCtrlValueType(const LADSPA_Descriptor* plugin, int port); 631 extern CtrlList::Mode ladspaCtrlMode(const LADSPA_Descriptor* plugin, int port); 632 633 } // namespace MusECore 634 635 636 namespace MusEGui { 637 class DoubleLabel; 638 639 // PluginLoader 640 //--------------------------------------------------------- 641 642 class PluginLoader : public QUiLoader 643 { 644 public: 645 virtual QWidget* createWidget(const QString & className, QWidget * parent = 0, const QString & name = QString()); QUiLoader(parent)646 PluginLoader(QObject * parent = 0) : QUiLoader(parent) {} 647 }; 648 649 //--------------------------------------------------------- 650 // GuiParam 651 //--------------------------------------------------------- 652 653 struct GuiParam { 654 enum { 655 GUI_SLIDER, GUI_SWITCH, GUI_METER, GUI_ENUM 656 }; 657 int type; 658 int hint; 659 bool pressed; 660 661 MusEGui::DoubleLabel* label; 662 QWidget* actuator; // Slider or Toggle Button (SWITCH) 663 }; 664 665 //--------------------------------------------------------- 666 // GuiWidgets 667 //--------------------------------------------------------- 668 669 struct GuiWidgets { 670 enum { 671 SLIDER, DOUBLE_LABEL, QCHECKBOX, QCOMBOBOX 672 }; 673 QWidget* widget; 674 int type; 675 unsigned long param; 676 bool pressed; 677 }; 678 679 //--------------------------------------------------------- 680 // PluginGui 681 //--------------------------------------------------------- 682 683 class PluginGui : public QMainWindow { 684 Q_OBJECT 685 686 MusECore::PluginIBase* plugin; // plugin instance 687 688 GuiParam* params; 689 GuiParam* paramsOut; 690 unsigned long nobj; // number of widgets in gw 691 GuiWidgets* gw; 692 693 QAction* onOff; 694 // QAction* transpGovLatencyAct; 695 // QAction* fixedSpeedAct; 696 // QAction* overrideLatencyAct; 697 // QSpinBox* latencyOverrideEntry; 698 QWidget* mw; // main widget 699 QScrollArea* view; 700 // QToolButton* fixNativeUIScalingTB; 701 // QString fixScalingTooltip[3]; 702 703 void updateControls(); 704 void getPluginConvertedValues(LADSPA_PortRangeHint range, 705 double &lower, double &upper, double &dlower, double &dupper, double &dval); 706 void constructGUIFromFile(QFile& uifile); 707 void constructGUIFromPluginMetadata(); 708 709 protected: 710 virtual void showEvent(QShowEvent *e); 711 virtual void hideEvent(QHideEvent *e); 712 713 private slots: 714 void load(); 715 void save(); 716 void bypassToggled(bool); 717 void showSettings(); 718 // void transportGovernsLatencyToggled(bool); 719 // void fixNativeUIScalingTBClicked(); 720 // void fixedSpeedToggled(bool); 721 // void overrideReportedLatencyToggled(bool); 722 // void latencyOverrideValueChanged(int); 723 void sliderChanged(double value, int id, int scrollMode); 724 void labelChanged(double, int); 725 void comboChanged(unsigned long); 726 void guiParamChanged(unsigned long int); 727 void sliderPressed(double, int); 728 void sliderReleased(double, int); 729 void switchPressed(int); 730 void switchReleased(int); 731 void guiParamPressed(unsigned long int); 732 void guiParamReleased(unsigned long int); 733 void guiSliderPressed(double, unsigned long int); 734 void guiSliderReleased(double, unsigned long int); 735 void ctrlRightClicked(const QPoint &, int); 736 void guiSliderRightClicked(const QPoint &, unsigned long int); 737 void guiContextMenuReq(unsigned long int idx); 738 739 protected slots: 740 virtual void heartBeat(); 741 742 public: 743 PluginGui(MusECore::PluginIBase*); 744 745 ~PluginGui(); 746 void setOn(bool); 747 void updateValues(); 748 void updateWindowTitle(); 749 }; 750 751 752 } // namespace MusEGui 753 754 namespace MusEGlobal { 755 extern MusECore::PluginList plugins; 756 extern MusECore::PluginGroups plugin_groups; 757 extern QList<QString> plugin_group_names; 758 759 void writePluginGroupConfiguration(int level, MusECore::Xml& xml); 760 void readPluginGroupConfiguration(MusECore::Xml& xml); 761 } 762 #endif 763 764