1 /* 2 ** Surge Synthesizer is Free and Open Source Software 3 ** 4 ** Surge is made available under the Gnu General Public License, v3.0 5 ** https://www.gnu.org/licenses/gpl-3.0.en.html 6 ** 7 ** Copyright 2004-2020 by various individuals as described by the Git transaction log 8 ** 9 ** All source at: https://github.com/surge-synthesizer/surge.git 10 ** 11 ** Surge was a commercial product from 2004-2018, with Copyright and ownership 12 ** in that period held by Claes Johanson at Vember Audio. Claes made Surge 13 ** open source in September 2018. 14 */ 15 16 #pragma once 17 18 #include "globals.h" 19 20 #if TARGET_AUDIOUNIT 21 //#include "vstkeycode.h" 22 #include "vstgui/plugin-bindings/plugguieditor.h" 23 typedef VSTGUI::PluginGUIEditor EditorType; 24 #elif TARGET_VST3 25 #include "public.sdk/source/vst/vstguieditor.h" 26 #include "pluginterfaces/gui/iplugviewcontentscalesupport.h" 27 typedef Steinberg::Vst::VSTGUIEditor EditorType; 28 #define PARENT_PLUGIN_TYPE SurgeVst3Processor 29 #elif TARGET_VST2 30 #if LINUX 31 #include "../linux/linux-aeffguieditor.h" 32 typedef VSTGUI::LinuxAEffGUIEditor EditorType; 33 #else 34 #include "vstgui/plugin-bindings/aeffguieditor.h" 35 typedef VSTGUI::AEffGUIEditor EditorType; 36 #endif 37 #elif TARGET_JUCE_UI 38 #include <JuceHeader.h> 39 #include "efvg/escape_from_vstgui.h" 40 #include "SurgeSynthEditor.h" 41 typedef EscapeFromVSTGUI::JuceVSTGUIEditorAdapter EditorType; 42 #define PARENT_PLUGIN_TYPE SurgeSynthEditor 43 #else 44 #include "vstgui/plugin-bindings/plugguieditor.h" 45 typedef VSTGUI::PluginGUIEditor EditorType; 46 #endif 47 48 #ifndef PARENT_PLUGIN_TYPE 49 #define PARENT_PLUGIN_TYPE void 50 #endif 51 52 #include "SurgeStorage.h" 53 #include "SurgeBitmaps.h" 54 55 #include "vstcontrols.h" 56 #include "SurgeSynthesizer.h" 57 58 #include "SkinSupport.h" 59 #include "SkinColors.h" 60 61 #include <vector> 62 #include "MSEGEditor.h" 63 64 class CSurgeSlider; 65 class CModulationSourceButton; 66 class CAboutBox; 67 class CMidiLearnOverlay; 68 69 #if TARGET_VST3 70 namespace Steinberg 71 { 72 namespace Vst 73 { 74 class IContextMenu; 75 } 76 } // namespace Steinberg 77 #endif 78 79 struct SGEDropAdapter; 80 81 class SurgeGUIEditor : public EditorType, 82 public VSTGUI::IControlListener, 83 public VSTGUI::IKeyboardHook 84 #if TARGET_VST3 85 , 86 public Steinberg::IPlugViewContentScaleSupport 87 #endif 88 { 89 private: 90 using super = EditorType; 91 92 public: 93 SurgeGUIEditor(PARENT_PLUGIN_TYPE *effect, SurgeSynthesizer *synth, void *userdata = nullptr); 94 virtual ~SurgeGUIEditor(); 95 96 static int start_paramtag_value; 97 98 #if TARGET_AUDIOUNIT | TARGET_VST2 | TARGET_LV2 99 void idle() override; 100 #else 101 void idle(); 102 #endif 103 bool queue_refresh; 104 virtual void toggle_mod_editing(); 105 106 virtual void beginEdit(long index); 107 virtual void endEdit(long index); 108 109 static long applyParameterOffset(long index); 110 static long unapplyParameterOffset(long index); 111 112 #if !TARGET_VST3 113 bool open(void *parent) override; 114 void close() override; 115 #else 116 virtual bool PLUGIN_API 117 open(void *parent, const VSTGUI::PlatformType &platformType = VSTGUI::kDefaultNative) override; 118 virtual void PLUGIN_API close() override; 119 onWheel(float distance)120 virtual Steinberg::tresult PLUGIN_API onWheel(float distance) override 121 { 122 /* 123 ** in VST3 the VstGuiEditorBase we have - even if the OS has handled it 124 ** a call to the VSTGUIEditor::onWheel (trust me; I put in stack traces 125 ** and prints). That's probably wrong. But when you use VSTGUI Zoom 126 ** and frame->getCurrentPosition gets screwed up because VSTGUI has transform 127 ** bugs it is definitely wrong. So the mouse wheel event gets mistakenly 128 ** delivered twice (OK) but to the wrong spot (not OK!). 129 ** 130 ** So stop the superclass from doing that by just making this do nothing. 131 */ 132 return Steinberg::kResultFalse; 133 } 134 canResize()135 virtual Steinberg::tresult PLUGIN_API canResize() override { return Steinberg::kResultTrue; } 136 137 void resizeFromIdleSentinel(); 138 139 bool initialZoom(); 140 virtual Steinberg::tresult PLUGIN_API onSize(Steinberg::ViewRect *newSize) override; 141 virtual Steinberg::tresult PLUGIN_API 142 checkSizeConstraint(Steinberg::ViewRect *newSize) override; setContentScaleFactor(ScaleFactor factor)143 virtual Steinberg::tresult PLUGIN_API setContentScaleFactor(ScaleFactor factor) override 144 { 145 // Unused for now. Consider removing this callback since not all hosts use it 146 return Steinberg::kResultTrue; 147 } 148 149 #endif 150 151 bool pause_idle_updates = false; 152 int enqueuePatchId = -1; flushEnqueuedPatchId()153 void flushEnqueuedPatchId() 154 { 155 auto t = enqueuePatchId; 156 enqueuePatchId = -1; 157 if (t >= 0) 158 { 159 synth->patchid_queue = t; 160 // Looks scary but remember this only runs if audio thread is off 161 synth->processThreadunsafeOperations(); 162 patchCountdown = 200; 163 } 164 } 165 166 protected: 167 int32_t onKeyDown(const VstKeyCode &code, 168 VSTGUI::CFrame *frame) override; ///< should return 1 if no further key down 169 ///< processing should apply, otherwise -1 170 int32_t onKeyUp(const VstKeyCode &code, 171 VSTGUI::CFrame *frame) override; ///< should return 1 if no further key up 172 ///< processing should apply, otherwise -1 173 174 virtual void setParameter(long index, float value); 175 176 // listener class 177 void valueChanged(VSTGUI::CControl *control) override; 178 int32_t controlModifierClicked(VSTGUI::CControl *pControl, 179 VSTGUI::CButtonState button) override; 180 void controlBeginEdit(VSTGUI::CControl *pControl) override; 181 void controlEndEdit(VSTGUI::CControl *pControl) override; 182 183 public: 184 void refresh_mod(); 185 void forceautomationchangefor(Parameter *p); 186 187 void effectSettingsBackgroundClick(int whichScene); 188 189 #if TARGET_VST3 190 public: 191 /** 192 * getIPlugFrame 193 * 194 * Amazingly, IPlugView has a setFrame( IPlugFrame ) method but 195 * no getter. It does, however, store the value as a protected 196 * variable. To collaborate for zoom, we need this reference 197 * in the VST Processor, so expose this function 198 */ getIPlugFrame()199 Steinberg::IPlugFrame *getIPlugFrame() { return plugFrame; } 200 #endif 201 void setDisabledForParameter(Parameter *p, CSurgeSlider *s); 202 void showSettingsMenu(VSTGUI::CRect &menuRect); 203 204 static bool fromSynthGUITag(SurgeSynthesizer *synth, int tag, SurgeSynthesizer::ID &q); 205 // If n_scenes > 2, then this initialization and the modsource_editor one below will need to 206 // adjust 207 int current_scene = 0, current_osc[n_scenes] = {0, 0}, current_fx = 0; 208 209 private: 210 void openOrRecreateEditor(); 211 void makeStorePatchDialog(); 212 void close_editor(); 213 bool isControlVisible(ControlGroup controlGroup, int controlGroupEntry); 214 void repushAutomationFor(Parameter *p); 215 SurgeSynthesizer *synth = nullptr; 216 bool editor_open = false; 217 bool mod_editor = false; 218 modsources modsource = ms_lfo1, modsource_editor[n_scenes] = {ms_lfo1, ms_lfo1}; 219 int fxbypass_tag = 0, f1subtypetag = 0, f2subtypetag = 0, filterblock_tag = 0, fmconfig_tag = 0; 220 double lastTempo = 0; 221 int lastTSNum = 0, lastTSDen = 0; 222 void draw_infowindow(int ptag, VSTGUI::CControl *control, bool modulate, bool forceMB = false); 223 void adjustSize(float &width, float &height) const; 224 225 struct patchdata 226 { 227 std::string name; 228 std::string category; 229 std::string comments; 230 std::string author; 231 }; 232 233 void setBitmapZoomFactor(float zf); 234 void showTooLargeZoomError(double width, double height, float zf) const; 235 void showMinimumZoomError() const; 236 237 /* 238 ** Zoom Implementation 239 ** 240 ** Zoom works by the system maintaining a zoom factor (created by user actions) 241 ** 242 ** All zoom factors are set in units of percentages as ints. So no zoom is "100", 243 ** and double size is "200" 244 */ 245 246 float zoomFactor = 100; 247 float initialZoomFactor = 100; 248 249 int patchCountdown = -1; 250 251 public: populateDawExtraState(SurgeSynthesizer * synth)252 void populateDawExtraState(SurgeSynthesizer *synth) 253 { 254 auto des = &(synth->storage.getPatch().dawExtraState); 255 256 des->isPopulated = true; 257 des->editor.instanceZoomFactor = zoomFactor; 258 des->editor.current_scene = current_scene; 259 des->editor.current_fx = current_fx; 260 des->editor.modsource = modsource; 261 for (int i = 0; i < n_scenes; ++i) 262 { 263 des->editor.current_osc[i] = current_osc[i]; 264 des->editor.modsource_editor[i] = modsource_editor[i]; 265 266 des->editor.msegStateIsPopulated = true; 267 for (int lf = 0; lf < n_lfos; ++lf) 268 { 269 des->editor.msegEditState[i][lf].timeEditMode = msegEditState[i][lf].timeEditMode; 270 } 271 } 272 des->editor.isMSEGOpen = (editorOverlayTagAtClose == "msegEditor"); 273 } 274 loadFromDAWExtraState(SurgeSynthesizer * synth)275 void loadFromDAWExtraState(SurgeSynthesizer *synth) 276 { 277 auto des = &(synth->storage.getPatch().dawExtraState); 278 if (des->isPopulated) 279 { 280 auto sz = des->editor.instanceZoomFactor; 281 if (sz > 0) 282 setZoomFactor(sz); 283 current_scene = des->editor.current_scene; 284 current_fx = des->editor.current_fx; 285 modsource = des->editor.modsource; 286 287 for (int i = 0; i < n_scenes; ++i) 288 { 289 current_osc[i] = des->editor.current_osc[i]; 290 modsource_editor[i] = des->editor.modsource_editor[i]; 291 if (des->editor.msegStateIsPopulated) 292 { 293 for (int lf = 0; lf < n_lfos; ++lf) 294 { 295 msegEditState[i][lf].timeEditMode = 296 des->editor.msegEditState[i][lf].timeEditMode; 297 } 298 } 299 } 300 if (des->editor.isMSEGOpen) 301 { 302 showMSEGEditorOnNextIdleOrOpen = true; 303 } 304 } 305 } 306 setZoomCallback(std::function<void (SurgeGUIEditor *,bool resizeWindow)> f)307 void setZoomCallback(std::function<void(SurgeGUIEditor *, bool resizeWindow)> f) 308 { 309 zoom_callback = f; 310 setZoomFactor(getZoomFactor()); // notify the new callback 311 } getZoomFactor()312 float getZoomFactor() const { return zoomFactor; } 313 void setZoomFactor(float zf); 314 void setZoomFactor(float zf, bool resizeWindow); 315 void resizeWindow(float zf); 316 bool doesZoomFitToScreen(float zf, 317 float &correctedZf); // returns true if it fits; false if not; sets 318 // correctedZF to right size in either case 319 320 void swapFX(int source, int target, SurgeSynthesizer::FXReorderMode m); 321 322 /* 323 ** Callbacks from the Status Panel. If this gets to be too many perhaps make these an interface? 324 */ 325 void showMPEMenu(VSTGUI::CPoint &where); 326 void showTuningMenu(VSTGUI::CPoint &where); 327 void showZoomMenu(VSTGUI::CPoint &where); 328 void showLfoMenu(VSTGUI::CPoint &menuRect); 329 330 void toggleMPE(); 331 void toggleTuning(); 332 void scaleFileDropped(std::string fn); 333 void mappingFileDropped(std::string fn); 334 std::string tuningToHtml(); 335 336 void swapControllers(int t1, int t2); 337 void openModTypeinOnDrop(int ms, VSTGUI::CControl *sl, int tgt); 338 queueRebuildUI()339 void queueRebuildUI() 340 { 341 queue_refresh = true; 342 synth->refresh_editor = true; 343 } 344 345 std::string midiMappingToHtml(); 346 347 // These are unused right now 348 enum SkinInspectorFlags 349 { 350 COLORS = 1 << 0, 351 COMPONENTS = 1 << 1, 352 353 ALL = COLORS | COMPONENTS 354 }; 355 std::string skinInspectorHtml(SkinInspectorFlags f = ALL); 356 357 /* 358 ** Modulation Hover Support 359 */ 360 void sliderHoverStart(int tag); 361 void sliderHoverEnd(int tag); 362 getWindowSizeX()363 int getWindowSizeX() const { return wsx; } getWindowSizeY()364 int getWindowSizeY() const { return wsy; } 365 366 /* 367 * We have an enumerated set of overlay tags which we can push 368 * to the UI. You *have* to give a new overlay type a tag in 369 * order for it to work. 370 */ 371 enum OverlayTags 372 { 373 NO_EDITOR, 374 MSEG_EDITOR, 375 STORE_PATCH 376 }; 377 378 void addEditorOverlay( 379 VSTGUI::CView *c, 380 std::string editorTitle, // A window display title - whatever you want 381 OverlayTags editorTag, // A tag by editor class. Please unique, no spaces. 382 const VSTGUI::CPoint &topleft = VSTGUI::CPoint(0, 0), bool modalOverlay = true, 383 bool hasCloseButton = true, std::function<void()> onClose = []() {}); 384 void dismissEditorOfType(OverlayTags ofType); topmostEditorTag()385 OverlayTags topmostEditorTag() 386 { 387 if (!editorOverlay.size()) 388 return NO_EDITOR; 389 return editorOverlay.back().first; 390 } isAnyOverlayPresent(OverlayTags tag)391 bool isAnyOverlayPresent(OverlayTags tag) 392 { 393 for (auto el : editorOverlay) 394 { 395 if (el.first == tag) 396 return true; 397 } 398 return false; 399 } 400 401 std::string getDisplayForTag(long tag); 402 queuePatchFileLoad(std::string file)403 void queuePatchFileLoad(std::string file) 404 { 405 strncpy(synth->patchid_file, file.c_str(), FILENAME_MAX); 406 synth->has_patchid_file = true; 407 } 408 409 void closeStorePatchDialog(); 410 void showStorePatchDialog(); 411 412 void lfoShapeChanged(int prior, int curr); 413 void showMSEGEditor(); 414 void closeMSEGEditor(); 415 void toggleMSEGEditor(); 416 void broadcastMSEGState(); 417 int msegIsOpenFor = -1, msegIsOpenInScene = -1; 418 bool showMSEGEditorOnNextIdleOrOpen = false; 419 420 MSEGEditor::State msegEditState[n_scenes][n_lfos]; 421 MSEGEditor::State mostRecentCopiedMSEGState; 422 423 int oscilatorMenuIndex[n_scenes][n_oscs] = {0}; 424 425 bool hasIdleRun = false; 426 VSTGUI::CPoint resizeToOnIdle = VSTGUI::CPoint(-1, -1); 427 /* 428 * A countdown which will clearr the bitmap store offscreen caches 429 * after N idles if set to a positive N. This is needed as some 430 * DAWS (cough cough LIVE) handle draw and resize events in a 431 * different order so the offscren cache when going classic->royal 432 * at 100% (for instance) is the wrong size. 433 */ 434 int clearOffscreenCachesAtZero = -1; 435 436 private: 437 SGEDropAdapter *dropAdapter = nullptr; 438 friend class SGEDropAdapter; 439 440 public: 441 bool canDropTarget(const std::string &fname); // these come as const char* from vstgui 442 bool onDrop(const std::string &fname); 443 444 private: 445 VSTGUI::CRect positionForModulationGrid(modsources entry); 446 447 int wsx = BASE_WINDOW_SIZE_X; 448 int wsy = BASE_WINDOW_SIZE_Y; 449 450 /** 451 * findLargestFittingZoomBetween 452 * 453 * Finds the largest zoom which will fit your current screen between a lower and upper bound. 454 * Will never return something smaller than lower or larger than upper. Default is as large as 455 * possible, quantized in units of zoomQuanta, with the maximum screen usage percentages 456 * protecting for screen real estate. The function also needs to know the 100% size of the UI 457 * the baseW and baseH) 458 * 459 * for instance findLargestFittingZoomBetween( 100, 200, 5, 90, bw, bh ) 460 * 461 * would find the largest possible zoom which uses at most 90% of your screen real estate but 462 * would also guarantee that the result % 5 == 0. 463 */ 464 int findLargestFittingZoomBetween(int zoomLow, int zoomHigh, int zoomQuanta, 465 int percentageOfScreenAvailable, float baseW, float baseH); 466 467 public: 468 void showAboutBox(int devModeGrid = -1); 469 void hideAboutBox(); 470 471 void showMidiLearnOverlay(const VSTGUI::CRect &r); 472 void hideMidiLearnOverlay(); 473 474 private: 475 #if TARGET_VST3 476 Steinberg::Vst::IContextMenu * 477 addVst3MenuForParams(VSTGUI::COptionMenu *c, const SurgeSynthesizer::ID &, 478 int &eid); // just a noop if you aren't a vst3 of course 479 #endif 480 481 std::function<void(SurgeGUIEditor *, bool resizeWindow)> zoom_callback; 482 bool zoomInvalid = false; 483 int minimumZoom = 100; 484 485 int selectedFX[8]; 486 std::string fxPresetName[8]; 487 488 public: 489 std::shared_ptr<SurgeBitmaps> bitmapStore = nullptr; 490 491 private: 492 bool modsource_is_alternate[n_modsources]; 493 494 public: 495 void toggleAlternateFor(VSTGUI::CControl *c); 496 497 private: 498 VSTGUI::CControl *vu[16]; 499 VSTGUI::CControl *infowindow, *patchname, *ccfxconf = nullptr; 500 VSTGUI::CControl *statusMPE = nullptr, *statusTune = nullptr, *statusZoom = nullptr; 501 CAboutBox *aboutbox = nullptr; 502 CMidiLearnOverlay *midiLearnOverlay = nullptr; 503 VSTGUI::CTextEdit *patchName = nullptr; 504 VSTGUI::CTextEdit *patchCategory = nullptr; 505 VSTGUI::CTextEdit *patchCreator = nullptr; 506 VSTGUI::CTextEdit *patchComment = nullptr; 507 VSTGUI::CCheckBox *patchTuning = nullptr; 508 VSTGUI::CTextLabel *patchTuningLabel = nullptr; 509 #if BUILD_IS_DEBUG 510 VSTGUI::CTextLabel *debugLabel = nullptr; 511 #endif 512 513 VSTGUI::CViewContainer *typeinDialog = nullptr; 514 VSTGUI::CTextEdit *typeinValue = nullptr; 515 VSTGUI::CTextLabel *typeinLabel = nullptr; 516 VSTGUI::CTextLabel *typeinPriorValueLabel = nullptr; 517 VSTGUI::CControl *typeinEditControl = nullptr; 518 VSTGUI::CControl *msegEditSwitch = nullptr; 519 enum TypeInMode 520 { 521 Inactive, 522 Param, 523 Control 524 } typeinMode = Inactive; 525 std::vector<VSTGUI::CView *> removeFromFrame; 526 int typeinResetCounter = -1; 527 std::string typeinResetLabel = ""; 528 529 // Data structures for a list of overlays and associated data witht hem 530 std::vector<std::pair<OverlayTags, VSTGUI::CViewContainer *>> editorOverlay; 531 std::unordered_map<VSTGUI::CViewContainer *, VSTGUI::CView *> 532 editorOverlayContentsWeakReference; 533 std::unordered_map<VSTGUI::CViewContainer *, std::function<void()>> editorOverlayOnClose; 534 535 VSTGUI::CViewContainer *minieditOverlay = nullptr; 536 VSTGUI::CTextEdit *minieditTypein = nullptr; 537 std::function<void(const char *)> minieditOverlayDone = [](const char *) {}; 538 539 public: 540 std::string editorOverlayTagAtClose; // FIXME what is this? 541 void promptForMiniEdit(const std::string &value, const std::string &prompt, 542 const std::string &title, const VSTGUI::CPoint &where, 543 std::function<void(const std::string &)> onOK); 544 545 private: 546 VSTGUI::CTextLabel *lfoNameLabel = nullptr; 547 VSTGUI::CTextLabel *fxPresetLabel = nullptr; 548 549 std::string modulatorName(int ms, bool forButton); 550 551 Parameter *typeinEditTarget = nullptr; 552 int typeinModSource = -1; 553 554 VSTGUI::CControl *polydisp = nullptr; 555 VSTGUI::CControl *oscdisplay = nullptr; 556 VSTGUI::CControl *splitpointControl = nullptr; 557 558 static const int n_paramslots = 1024; 559 VSTGUI::CControl *param[n_paramslots] = {}; 560 VSTGUI::CControl *nonmod_param[n_paramslots] = {}; 561 CModulationSourceButton *gui_modsrc[n_modsources] = {}; 562 VSTGUI::CControl *metaparam[n_customcontrollers] = {}; 563 VSTGUI::CControl *lfodisplay = nullptr; 564 VSTGUI::CControl *filtersubtype[2] = {}; 565 VSTGUI::CControl *fxmenu = nullptr; 566 int clear_infoview_countdown = 0; 567 568 public: 569 int clear_infoview_peridle = -1; 570 bool useDevMenu = false; 571 572 private: 573 float blinktimer = 0; 574 bool blinkstate = false; 575 PARENT_PLUGIN_TYPE *_effect = nullptr; 576 void *_userdata = nullptr; 577 #if TARGET_JUCE_UI 578 std::shared_ptr<int> _idleTimer; // FIXME 579 #else 580 VSTGUI::SharedPointer<VSTGUI::CVSTGUITimer> _idleTimer; 581 #endif 582 int firstIdleCountdown = 0; 583 584 /* 585 ** Utility Function 586 */ 587 VSTGUI::CCommandMenuItem *addCallbackMenu(VSTGUI::COptionMenu *toThis, std::string label, 588 std::function<void()> op); 589 590 VSTGUI::COptionMenu * 591 makeSmoothMenu(VSTGUI::CRect &menuRect, const std::string &key, int defaultValue, 592 std::function<void(ControllerModulationSource::SmoothingMode)> setSmooth); 593 594 VSTGUI::COptionMenu *makeMpeMenu(VSTGUI::CRect &rect, bool showhelp); 595 VSTGUI::COptionMenu *makeTuningMenu(VSTGUI::CRect &rect, bool showhelp); 596 VSTGUI::COptionMenu *makeZoomMenu(VSTGUI::CRect &rect, bool showhelp); 597 VSTGUI::COptionMenu *makeSkinMenu(VSTGUI::CRect &rect); 598 VSTGUI::COptionMenu *makeUserSettingsMenu(VSTGUI::CRect &rect); 599 VSTGUI::COptionMenu *makeDataMenu(VSTGUI::CRect &rect); 600 VSTGUI::COptionMenu *makeMidiMenu(VSTGUI::CRect &rect); 601 VSTGUI::COptionMenu *makeDevMenu(VSTGUI::CRect &rect); 602 VSTGUI::COptionMenu *makeLfoMenu(VSTGUI::CRect &rect); 603 VSTGUI::COptionMenu *makeMonoModeOptionsMenu(VSTGUI::CRect &rect, bool updateDefaults); 604 bool scannedForMidiPresets = false; 605 606 void resetSmoothing(ControllerModulationSource::SmoothingMode t); 607 void resetPitchSmoothing(ControllerModulationSource::SmoothingMode t); 608 609 public: 610 std::string helpURLFor(Parameter *p); // this requires internal state so doesn't have statics 611 std::string helpURLForSpecial(std::string special); // these can be either this way or static 612 613 static std::string helpURLForSpecial(SurgeStorage *, std::string special); 614 static std::string fullyResolvedHelpURL(std::string helpurl); 615 616 private: 617 #if TARGET_VST3 618 OBJ_METHODS(SurgeGUIEditor, EditorType) 619 DEFINE_INTERFACES 620 DEF_INTERFACE(Steinberg::IPlugViewContentScaleSupport) 621 END_DEFINE_INTERFACES(EditorType) 622 REFCOUNT_METHODS(EditorType) 623 #endif 624 625 void promptForUserValueEntry(Parameter *p, VSTGUI::CControl *c, int modulationSource = -1); 626 627 /* 628 ** Skin support 629 */ 630 Surge::UI::Skin::ptr_t currentSkin; 631 void setupSkinFromEntry(const Surge::UI::SkinDB::Entry &entry); 632 void reloadFromSkin(); 633 VSTGUI::CControl *layoutComponentForSkin(std::shared_ptr<Surge::UI::Skin::Control> skinCtrl, 634 long tag, int paramIndex = -1, Parameter *p = nullptr, 635 int style = 0); 636 637 /* 638 ** General MIDI CC names 639 */ 640 const char midicc_names[128][42] = {"Bank Select MSB", 641 "Modulation Wheel MSB", 642 "Breath Controller MSB", 643 "Control 3 MSB", 644 "Foot Controller MSB", 645 "Portamento Time MSB", 646 "Data Entry MSB", 647 "Volume MSB", 648 "Balance MSB", 649 "Control 9 MSB", 650 "Pan MSB", 651 "Expression MSB", 652 "Effect #1 MSB", 653 "Effect #2 MSB", 654 "Control 14 MSB", 655 "Control 15 MSB", 656 "General Purpose Controller #1 MSB", 657 "General Purpose Controller #2 MSB", 658 "General Purpose Controller #3 MSB", 659 "General Purpose Controller #4 MSB", 660 "Control 20 MSB", 661 "Control 21 MSB", 662 "Control 22 MSB", 663 "Control 23 MSB", 664 "Control 24 MSB", 665 "Control 25 MSB", 666 "Control 26 MSB", 667 "Control 27 MSB", 668 "Control 28 MSB", 669 "Control 29 MSB", 670 "Control 30 MSB", 671 "Control 31 MSB", 672 "Bank Select LSB", 673 "Modulation Wheel LSB", 674 "Breath Controller LSB", 675 "Control 3 LSB", 676 "Foot Controller LSB", 677 "Portamento Time LSB", 678 "Data Entry LSB", 679 "Volume LSB", 680 "Balance LSB", 681 "Control 9 LSB", 682 "Pan LSB", 683 "Expression LSB", 684 "Effect #1 LSB", 685 "Effect #2 LSB", 686 "Control 14 LSB", 687 "Control 15 LSB", 688 "General Purpose Controller #1 LSB", 689 "General Purpose Controller #2 LSB", 690 "General Purpose Controller #3 LSB", 691 "General Purpose Controller #4 LSB", 692 "Control 20 LSB", 693 "Control 21 LSB", 694 "Control 22 LSB", 695 "Control 23 LSB", 696 "Control 24 LSB", 697 "Control 25 LSB", 698 "Control 26 LSB", 699 "Control 27 LSB", 700 "Control 28 LSB", 701 "Control 29 LSB", 702 "Control 30 LSB", 703 "Control 31 LSB", 704 "Sustain Pedal", 705 "Portamento Pedal", 706 "Sostenuto Pedal", 707 "Soft Pedal", 708 "Legato Pedal", 709 "Hold Pedal", 710 "Sound Control #1 Sound Variation", 711 "Sound Control #2 Timbre", 712 "Sound Control #3 Release Time", 713 "Sound Control #4 Attack Time", 714 "Sound Control #5 Brightness / MPE Timbre", 715 "Sound Control #6 Decay Time", 716 "Sound Control #7 Vibrato Rate", 717 "Sound Control #8 Vibrato Depth", 718 "Sound Control #9 Vibrato Delay", 719 "Sound Control #10 Control 79", 720 "General Purpose Controller #5", 721 "General Purpose Controller #6", 722 "General Purpose Controller #7", 723 "General Purpose Controller #8", 724 "Portamento Control", 725 "Control 85", 726 "Control 86", 727 "Control 87", 728 "High Resolution Velocity Prefix", 729 "Control 89", 730 "Control 90", 731 "Reverb Send Level", 732 "Tremolo Depth", 733 "Chorus Send Level", 734 "Celeste Depth", 735 "Phaser Depth", 736 "Data Increment", 737 "Data Decrement", 738 "NRPN LSB", 739 "NRPN MSB", 740 "RPN LSB", 741 "RPN MLSB", 742 "Control 102", 743 "Control 103", 744 "Control 104", 745 "Control 105", 746 "Control 106", 747 "Control 107", 748 "Control 108", 749 "Control 109", 750 "Control 110", 751 "Control 111", 752 "Control 112", 753 "Control 113", 754 "Control 114", 755 "Control 115", 756 "Control 116", 757 "Control 117", 758 "Control 118", 759 "Control 119", 760 "Control 120 All Sound Off", 761 "Control 121 Reset All Controllers", 762 "Control 122 Local Control On/Of", 763 "Control 123 All Notes Off", 764 "Control 124 Omni Mode Off", 765 "Control 125 Omni Mode On", 766 "Control 126 Mono Mode Off", 767 "Control 127 Mono Mode On"}; 768 }; 769