Audacity  3.0.3
VSTEffect.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  VSTEffect.cpp
6 
7  Dominic Mazzoni
8 
9  This class implements a VST Plug-in effect. The plug-in must be
10  loaded in a platform-specific way and passed into the constructor,
11  but from here this class handles the interfacing.
12 
13 ********************************************************************//********************************************************************/
19 
20 //#define VST_DEBUG
21 //#define DEBUG_VST
22 
23 // *******************************************************************
24 // WARNING: This is NOT 64-bit safe
25 // *******************************************************************
26 
27 
28 #include "VSTEffect.h"
29 #include "../../ModuleManager.h"
30 #include "SampleCount.h"
31 
32 #include "../../widgets/ProgressDialog.h"
33 
34 #if 0
35 #if defined(BUILDING_AUDACITY)
36 #include "../../PlatformCompatibility.h"
37 
38 // Make the main function private
39 #else
40 #define USE_VST 1
41 #endif
42 #endif
43 
44 #if USE_VST
45 
46 #include <limits.h>
47 #include <stdio.h>
48 
49 #include <wx/setup.h> // for wxUSE_* macros
50 #include <wx/dynlib.h>
51 #include <wx/app.h>
52 #include <wx/defs.h>
53 #include <wx/buffer.h>
54 #include <wx/busyinfo.h>
55 #include <wx/button.h>
56 #include <wx/combobox.h>
57 #include <wx/file.h>
58 #include <wx/filename.h>
59 #include <wx/imaglist.h>
60 #include <wx/listctrl.h>
61 #include <wx/log.h>
62 #include <wx/module.h>
63 #include <wx/process.h>
64 #include <wx/recguard.h>
65 #include <wx/sizer.h>
66 #include <wx/slider.h>
67 #include <wx/scrolwin.h>
68 #include <wx/sstream.h>
69 #include <wx/statbox.h>
70 #include <wx/stattext.h>
71 #include <wx/timer.h>
72 #include <wx/tokenzr.h>
73 #include <wx/utils.h>
74 
75 #if defined(__WXMSW__)
76 #include <shlwapi.h>
77 #pragma comment(lib, "shlwapi")
78 #else
79 #include <dlfcn.h>
80 #endif
81 
82 // TODO: Unfortunately we have some dependencies on Audacity provided
83 // dialogs, widgets and other stuff. This will need to be cleaned up.
84 
85 #include "../../FileNames.h"
86 #include "../../PlatformCompatibility.h"
87 #include "../../ShuttleGui.h"
88 #include "../../effects/Effect.h"
89 #include "../../widgets/valnum.h"
90 #include "../../widgets/AudacityMessageBox.h"
91 #include "../../widgets/NumericTextCtrl.h"
92 #include "../../xml/XMLFileReader.h"
93 
94 #if wxUSE_ACCESSIBILITY
95 #include "../../widgets/WindowAccessible.h"
96 #endif
97 
98 #include "ConfigInterface.h"
99 
100 #include <cstring>
101 
102 // Put this inclusion last. On Linux it makes some unfortunate pollution of
103 // preprocessor macro name space that interferes with other headers.
104 #if defined(__WXOSX__)
105 #include "VSTControlOSX.h"
106 #elif defined(__WXMSW__)
107 #include "VSTControlMSW.h"
108 #elif defined(__WXGTK__)
109 #include "VSTControlGTK.h"
110 #endif
111 
112 static float reinterpretAsFloat(uint32_t x)
113 {
114  static_assert(sizeof(float) == sizeof(uint32_t), "Cannot reinterpret uint32_t to float since sizes are different.");
115  float f;
116  std::memcpy(&f, &x, sizeof(float));
117  return f;
118 }
119 
120 static uint32_t reinterpretAsUint32(float f)
121 {
122  static_assert(sizeof(float) == sizeof(uint32_t), "Cannot reinterpret float to uint32_t since sizes are different.");
123 
124  uint32_t x;
125  std::memcpy(&x, &f, sizeof(uint32_t));
126  return x;
127 }
128 
129 // NOTE: To debug the subprocess, use wxLogDebug and, on Windows, Debugview
130 // from TechNet (Sysinternals).
131 
132 // ============================================================================
133 //
134 // Module registration entry point
135 //
136 // This is the symbol that Audacity looks for when the module is built as a
137 // dynamic library.
138 //
139 // When the module is builtin to Audacity, we use the same function, but it is
140 // declared static so as not to clash with other builtin modules.
141 //
142 // ============================================================================
143 DECLARE_MODULE_ENTRY(AudacityModule)
144 {
145  // Create our effects module and register
146  // Trust the module manager not to leak this
147  return safenew VSTEffectsModule();
148 }
149 
150 // ============================================================================
151 //
152 // Register this as a builtin module
153 //
154 // We also take advantage of the fact that wxModules are initialized before
155 // the wxApp::OnInit() method is called. We check to see if Audacity was
156 // executed to scan a VST effect in a different process.
157 //
158 // ============================================================================
160 
161 
167 class VSTSubEntry final : public wxModule
168 {
169 public:
170  bool OnInit()
171  {
172  // Have we been started to check a plugin?
173  if (wxTheApp && wxTheApp->argc == 3 && wxStrcmp(wxTheApp->argv[1], VSTCMDKEY) == 0)
174  {
175  // NOTE: This can really hide failures, which is what we want for those pesky
176  // VSTs that are bad or that our support isn't correct. But, it can also
177  // hide Audacity failures in the subprocess, so if you're having an unruley
178  // VST or odd Audacity failures, comment it out and you might get more info.
179  //wxHandleFatalExceptions();
180  VSTEffectsModule::Check(wxTheApp->argv[2]);
181 
182  // Returning false causes default processing to display a message box, but we don't
183  // want that so disable logging.
184  wxLog::EnableLogging(false);
185 
186  return false;
187  }
188 
189  return true;
190  };
191 
192  void OnExit() {};
193 
194  DECLARE_DYNAMIC_CLASS(VSTSubEntry)
195 };
197 
198 //----------------------------------------------------------------------------
199 // VSTSubProcess
200 //----------------------------------------------------------------------------
201 #define OUTPUTKEY wxT("<VSTLOADCHK>-")
203 {
214  kKeyEnd
215 };
216 
217 
223 class VSTSubProcess final : public wxProcess,
225 {
226 public:
228  {
229  Redirect();
230  }
231 
232  // EffectClientInterface implementation
233 
234  PluginPath GetPath() override
235  {
236  return mPath;
237  }
238 
240  {
241  return mName;
242  }
243 
245  {
246  return { mVendor };
247  }
248 
249  wxString GetVersion() override
250  {
251  return mVersion;
252  }
253 
255  {
256  return mDescription;
257  }
258 
260  {
261  return VSTPLUGINTYPE;
262  }
263 
264  EffectType GetType() override
265  {
266  return mType;
267  }
268 
269  bool IsInteractive() override
270  {
271  return mInteractive;
272  }
273 
274  bool IsDefault() override
275  {
276  return false;
277  }
278 
279  bool IsLegacy() override
280  {
281  return false;
282  }
283 
284  bool SupportsRealtime() override
285  {
286  return mType == EffectTypeProcess;
287  }
288 
289  bool SupportsAutomation() override
290  {
291  return mAutomatable;
292  }
293 
294 public:
295  wxString mPath;
296  wxString mName;
297  wxString mVendor;
298  wxString mVersion;
303 };
304 
305 // ============================================================================
306 //
307 // VSTEffectsModule
308 //
309 // ============================================================================
311 {
312 }
313 
315 {
316 }
317 
318 // ============================================================================
319 // ComponentInterface implementation
320 // ============================================================================
321 
323 {
324  return {};
325 }
326 
328 {
329  return XO("VST Effects");
330 }
331 
333 {
334  return XO("The Audacity Team");
335 }
336 
338 {
339  // This "may" be different if this were to be maintained as a separate DLL
340  return AUDACITY_VERSION_STRING;
341 }
342 
344 {
345  return XO("Adds the ability to use VST effects in Audacity.");
346 }
347 
348 // ============================================================================
349 // ModuleInterface implementation
350 // ============================================================================
351 
353 {
354  // Nothing to do here
355  return true;
356 }
357 
359 {
360  // Nothing to do here
361  return;
362 }
363 
365 {
366 #if USE_VST
367  return VSTPLUGINTYPE;
368 #else
369  return {};
370 #endif
371 }
372 
374 {
375  static FileExtensions result{{ _T("vst") }};
376  return result;
377 }
378 
380 {
381  // Not yet ready for VST drag-and-drop...
382  // return FileNames::PlugInDir();
383 
384  return {};
385 }
386 
388 {
389  // We don't auto-register
390  return true;
391 }
392 
394 {
395  FilePaths pathList;
396  FilePaths files;
397 
398  // Check for the VST_PATH environment variable
399  wxString vstpath = wxString::FromUTF8(getenv("VST_PATH"));
400  if (!vstpath.empty())
401  {
402  wxStringTokenizer tok(vstpath, wxPATH_SEP);
403  while (tok.HasMoreTokens())
404  {
405  pathList.push_back(tok.GetNextToken());
406  }
407  }
408 
409 #if defined(__WXMAC__)
410 #define VSTPATH wxT("/Library/Audio/Plug-Ins/VST")
411 
412  // Look in ~/Library/Audio/Plug-Ins/VST and /Library/Audio/Plug-Ins/VST
413  pathList.push_back(wxGetHomeDir() + wxFILE_SEP_PATH + VSTPATH);
414  pathList.push_back(VSTPATH);
415 
416  // Recursively search all paths for Info.plist files. This will identify all
417  // bundles.
418  pm.FindFilesInPathList(wxT("Info.plist"), pathList, files, true);
419 
420  // Remove the 'Contents/Info.plist' portion of the names
421  for (size_t i = 0; i < files.size(); i++)
422  {
423  files[i] = wxPathOnly(wxPathOnly(files[i]));
424  if (!files[i].EndsWith(wxT(".vst")))
425  {
426  files.erase( files.begin() + i-- );
427  }
428  }
429 
430 #elif defined(__WXMSW__)
431 
432  TCHAR dpath[MAX_PATH];
433  TCHAR tpath[MAX_PATH];
434  DWORD len;
435 
436  // Try HKEY_CURRENT_USER registry key first
437  len = WXSIZEOF(tpath);
438  if (SHRegGetUSValue(wxT("Software\\VST"),
439  wxT("VSTPluginsPath"),
440  NULL,
441  tpath,
442  &len,
443  FALSE,
444  NULL,
445  0) == ERROR_SUCCESS)
446  {
447  tpath[len] = 0;
448  dpath[0] = 0;
449  ExpandEnvironmentStrings(tpath, dpath, WXSIZEOF(dpath));
450  pathList.push_back(dpath);
451  }
452 
453  // Then try HKEY_LOCAL_MACHINE registry key
454  len = WXSIZEOF(tpath);
455  if (SHRegGetUSValue(wxT("Software\\VST"),
456  wxT("VSTPluginsPath"),
457  NULL,
458  tpath,
459  &len,
460  TRUE,
461  NULL,
462  0) == ERROR_SUCCESS)
463  {
464  tpath[len] = 0;
465  dpath[0] = 0;
466  ExpandEnvironmentStrings(tpath, dpath, WXSIZEOF(dpath));
467  pathList.push_back(dpath);
468  }
469 
470  // Add the default path last
471  dpath[0] = 0;
472  ExpandEnvironmentStrings(wxT("%ProgramFiles%\\Steinberg\\VSTPlugins"),
473  dpath,
474  WXSIZEOF(dpath));
475  pathList.push_back(dpath);
476 
477  // Recursively scan for all DLLs
478  pm.FindFilesInPathList(wxT("*.dll"), pathList, files, true);
479 
480 #else
481 
482  // Nothing specified in the VST_PATH environment variable...provide defaults
483  if (vstpath.empty())
484  {
485  // We add this "non-default" one
486  pathList.push_back(wxT(LIBDIR) wxT("/vst"));
487 
488  // These are the defaults used by other hosts
489  pathList.push_back(wxT("/usr/lib/vst"));
490  pathList.push_back(wxT("/usr/local/lib/vst"));
491  pathList.push_back(wxGetHomeDir() + wxFILE_SEP_PATH + wxT(".vst"));
492  }
493 
494  // Recursively scan for all shared objects
495  pm.FindFilesInPathList(wxT("*.so"), pathList, files, true);
496 
497 #endif
498 
499  return { files.begin(), files.end() };
500 }
501 
503  const PluginPath & path, TranslatableString &errMsg,
504  const RegistrationCallback &callback)
505 {
506  bool error = false;
507  unsigned nFound = 0;
508  errMsg = {};
509  // TODO: Fix this for external usage
510  const auto &cmdpath = PlatformCompatibility::GetExecutablePath();
511 
512  wxString effectIDs = wxT("0;");
513  wxStringTokenizer effectTzr(effectIDs, wxT(";"));
514 
515  Optional<ProgressDialog> progress{};
516  size_t idCnt = 0;
517  size_t idNdx = 0;
518 
519  bool cont = true;
520 
521  while (effectTzr.HasMoreTokens() && cont)
522  {
523  wxString effectID = effectTzr.GetNextToken();
524 
525  wxString cmd;
526  cmd.Printf(wxT("\"%s\" %s \"%s;%s\""), cmdpath, VSTCMDKEY, path, effectID);
527 
528  VSTSubProcess proc;
529  try
530  {
531  int flags = wxEXEC_SYNC | wxEXEC_NODISABLE;
532 #if defined(__WXMSW__)
533  flags += wxEXEC_NOHIDE;
534 #endif
535  wxExecute(cmd, flags, &proc);
536  }
537  catch (...)
538  {
539  wxLogMessage(wxT("VST plugin registration failed for %s\n"), path);
540  error = true;
541  }
542 
543  wxString output;
544  wxStringOutputStream ss(&output);
545  proc.GetInputStream()->Read(ss);
546 
547  int keycount = 0;
548  bool haveBegin = false;
549  wxStringTokenizer tzr(output, wxT("\n"));
550  while (tzr.HasMoreTokens())
551  {
552  wxString line = tzr.GetNextToken();
553 
554  // Our output may follow any output the plugin may have written.
555  if (!line.StartsWith(OUTPUTKEY))
556  {
557  continue;
558  }
559 
560  long key;
561  if (!line.Mid(wxStrlen(OUTPUTKEY)).BeforeFirst(wxT('=')).ToLong(&key))
562  {
563  continue;
564  }
565  wxString val = line.AfterFirst(wxT('=')).BeforeFirst(wxT('\r'));
566 
567  switch (key)
568  {
569  case kKeySubIDs:
570  effectIDs = val;
571  effectTzr.Reinit(effectIDs);
572  idCnt = effectTzr.CountTokens();
573  if (idCnt > 3)
574  {
575  progress.emplace( XO("Scanning Shell VST"),
576  XO("Registering %d of %d: %-64.64s")
577  .Format( 0, idCnt, proc.GetSymbol().Translation())
578  /*
579  , wxPD_APP_MODAL |
580  wxPD_AUTO_HIDE |
581  wxPD_CAN_ABORT |
582  wxPD_ELAPSED_TIME |
583  wxPD_ESTIMATED_TIME |
584  wxPD_REMAINING_TIME
585  */
586  );
587  progress->Show();
588  }
589  break;
590 
591  case kKeyBegin:
592  haveBegin = true;
593  keycount++;
594  break;
595 
596  case kKeyName:
597  proc.mName = val;
598  keycount++;
599  break;
600 
601  case kKeyPath:
602  proc.mPath = val;
603  keycount++;
604  break;
605 
606  case kKeyVendor:
607  proc.mVendor = val;
608  keycount++;
609  break;
610 
611  case kKeyVersion:
612  proc.mVersion = val;
613  keycount++;
614  break;
615 
616  case kKeyDescription:
617  proc.mDescription = Verbatim( val );
618  keycount++;
619  break;
620 
621  case kKeyEffectType:
622  long type;
623  val.ToLong(&type);
624  proc.mType = (EffectType) type;
625  keycount++;
626  break;
627 
628  case kKeyInteractive:
629  proc.mInteractive = val == wxT("1");
630  keycount++;
631  break;
632 
633  case kKeyAutomatable:
634  proc.mAutomatable = val == wxT("1");
635  keycount++;
636  break;
637 
638  case kKeyEnd:
639  {
640  if (!haveBegin || ++keycount != kKeyEnd)
641  {
642  keycount = 0;
643  haveBegin = false;
644  continue;
645  }
646 
647  bool skip = false;
648  if (progress)
649  {
650  idNdx++;
651  auto result = progress->Update((int)idNdx, (int)idCnt,
652  XO("Registering %d of %d: %-64.64s")
653  .Format( idNdx, idCnt, proc.GetSymbol().Translation() ));
654  cont = (result == ProgressResult::Success);
655  }
656 
657  if (!skip && cont)
658  {
659  if (callback)
660  callback( this, &proc );
661  ++nFound;
662  }
663  }
664  break;
665 
666  default:
667  keycount = 0;
668  haveBegin = false;
669  break;
670  }
671  }
672  }
673 
674  if (error)
675  errMsg = XO("Could not load the library");
676 
677  return nFound;
678 }
679 
680 bool VSTEffectsModule::IsPluginValid(const PluginPath & path, bool bFast)
681 {
682  if( bFast )
683  return true;
684  wxString realPath = path.BeforeFirst(wxT(';'));
685  return wxFileName::FileExists(realPath) || wxFileName::DirExists(realPath);
686 }
687 
688 std::unique_ptr<ComponentInterface>
690 {
691  // Acquires a resource for the application.
692  // For us, the ID is simply the path to the effect
693  return std::make_unique<VSTEffect>(path);
694 }
695 
696 // ============================================================================
697 // ModuleEffectInterface implementation
698 // ============================================================================
699 
700 // ============================================================================
701 // VSTEffectsModule implementation
702 // ============================================================================
703 
704 // static
705 //
706 // Called from reinvokation of Audacity or DLL to check in a separate process
707 void VSTEffectsModule::Check(const wxChar *path)
708 {
709  VSTEffect effect(path);
710  if (effect.SetHost(NULL))
711  {
712  auto effectIDs = effect.GetEffectIDs();
713  wxString out;
714 
715  if (effectIDs.size() > 0)
716  {
717  wxString subids;
718 
719  for (size_t i = 0, cnt = effectIDs.size(); i < cnt; i++)
720  {
721  subids += wxString::Format(wxT("%d;"), effectIDs[i]);
722  }
723 
724  out = wxString::Format(wxT("%s%d=%s\n"), OUTPUTKEY, kKeySubIDs, subids.RemoveLast());
725  }
726  else
727  {
728  out += wxString::Format(wxT("%s%d=%s\n"), OUTPUTKEY, kKeyBegin, wxEmptyString);
729  out += wxString::Format(wxT("%s%d=%s\n"), OUTPUTKEY, kKeyPath, effect.GetPath());
730  out += wxString::Format(wxT("%s%d=%s\n"), OUTPUTKEY, kKeyName, effect.GetSymbol().Internal());
731  out += wxString::Format(wxT("%s%d=%s\n"), OUTPUTKEY, kKeyVendor,
732  effect.GetVendor().Internal());
733  out += wxString::Format(wxT("%s%d=%s\n"), OUTPUTKEY, kKeyVersion, effect.GetVersion());
734  out += wxString::Format(wxT("%s%d=%s\n"), OUTPUTKEY, kKeyDescription, effect.GetDescription().Translation());
735  out += wxString::Format(wxT("%s%d=%d\n"), OUTPUTKEY, kKeyEffectType, effect.GetType());
736  out += wxString::Format(wxT("%s%d=%d\n"), OUTPUTKEY, kKeyInteractive, effect.IsInteractive());
737  out += wxString::Format(wxT("%s%d=%d\n"), OUTPUTKEY, kKeyAutomatable, effect.SupportsAutomation());
738  out += wxString::Format(wxT("%s%d=%s\n"), OUTPUTKEY, kKeyEnd, wxEmptyString);
739  }
740 
741  // We want to output info in one chunk to prevent output
742  // from the effect intermixing with the info
743  const wxCharBuffer buf = out.ToUTF8();
744  fwrite(buf, 1, strlen(buf), stdout);
745  fflush(stdout);
746  }
747 }
748 
750 //
751 // Dialog for configuring latency, buffer size and graphics mode for a
752 // VST effect.
753 //
756 {
757 public:
758  VSTEffectOptionsDialog(wxWindow * parent, EffectHostInterface *host);
759  virtual ~VSTEffectOptionsDialog();
760 
761  void PopulateOrExchange(ShuttleGui & S);
762 
763  void OnOk(wxCommandEvent & evt);
764 
765 private:
769  bool mUseGUI;
770 
771  DECLARE_EVENT_TABLE()
772 };
773 
774 BEGIN_EVENT_TABLE(VSTEffectOptionsDialog, wxDialogWrapper)
777 
779 : wxDialogWrapper(parent, wxID_ANY, XO("VST Effect Options"))
780 {
781  mHost = host;
782 
783  mHost->GetSharedConfig(wxT("Options"), wxT("BufferSize"), mBufferSize, 8192);
784  mHost->GetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency, true);
785  mHost->GetSharedConfig(wxT("Options"), wxT("UseGUI"), mUseGUI, true);
786 
787  ShuttleGui S(this, eIsCreating);
788  PopulateOrExchange(S);
789 }
790 
792 {
793 }
794 
796 {
797  S.SetBorder(5);
798  S.StartHorizontalLay(wxEXPAND, 1);
799  {
800  S.StartVerticalLay(false);
801  {
802  S.StartStatic(XO("Buffer Size"));
803  {
804  S.AddVariableText( XO(
805 "The buffer size controls the number of samples sent to the effect "
806 "on each iteration. Smaller values will cause slower processing and "
807 "some effects require 8192 samples or less to work properly. However "
808 "most effects can accept large buffers and using them will greatly "
809 "reduce processing time."),
810  false, 0, 650);
811 
812  S.StartHorizontalLay(wxALIGN_LEFT);
813  {
814  wxTextCtrl *t;
815  t = S.Validator<IntegerValidator<int>>(
816  &mBufferSize, NumValidatorStyle::DEFAULT, 8, 1048576 * 1)
817  .MinSize( { 100, -1 } )
818  .TieNumericTextBox(XXO("&Buffer Size (8 to 1048576 samples):"),
819  mBufferSize,
820  12);
821  }
822  S.EndHorizontalLay();
823  }
824  S.EndStatic();
825 
826  S.StartStatic(XO("Latency Compensation"));
827  {
828  S.AddVariableText( XO(
829 "As part of their processing, some VST effects must delay returning "
830 "audio to Audacity. When not compensating for this delay, you will "
831 "notice that small silences have been inserted into the audio. "
832 "Enabling this option will provide that compensation, but it may "
833 "not work for all VST effects."),
834  false, 0, 650);
835 
836  S.StartHorizontalLay(wxALIGN_LEFT);
837  {
838  S.TieCheckBox(XXO("Enable &compensation"),
839  mUseLatency);
840  }
841  S.EndHorizontalLay();
842  }
843  S.EndStatic();
844 
845  S.StartStatic(XO("Graphical Mode"));
846  {
847  S.AddVariableText( XO(
848 "Most VST effects have a graphical interface for setting parameter values."
849 " A basic text-only method is also available. "
850 " Reopen the effect for this to take effect."),
851  false, 0, 650);
852  S.TieCheckBox(XXO("Enable &graphical interface"),
853  mUseGUI);
854  }
855  S.EndStatic();
856  }
857  S.EndVerticalLay();
858  }
859  S.EndHorizontalLay();
860 
861  S.AddStandardButtons();
862 
863  Layout();
864  Fit();
865  Center();
866 }
867 
868 void VSTEffectOptionsDialog::OnOk(wxCommandEvent & WXUNUSED(evt))
869 {
870  if (!Validate())
871  {
872  return;
873  }
874 
877 
878  mHost->SetSharedConfig(wxT("Options"), wxT("BufferSize"), mBufferSize);
879  mHost->SetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency);
880  mHost->SetSharedConfig(wxT("Options"), wxT("UseGUI"), mUseGUI);
881 
882  EndModal(wxID_OK);
883 }
884 
892 class VSTEffectTimer final : public wxTimer
893 {
894 public:
896  : wxTimer(),
897  mEffect(effect)
898  {
899  }
900 
902  {
903  }
904 
905  void Notify()
906  {
907  mEffect->OnTimer();
908  }
909 
910 private:
912 };
913 
915 //
916 // VSTEffect
917 //
919 enum
920 {
921  ID_Duration = 20000,
922  ID_Sliders = 21000,
923 };
924 
925 DEFINE_LOCAL_EVENT_TYPE(EVT_SIZEWINDOW);
926 DEFINE_LOCAL_EVENT_TYPE(EVT_UPDATEDISPLAY);
927 
928 BEGIN_EVENT_TABLE(VSTEffect, wxEvtHandler)
929  EVT_COMMAND_RANGE(ID_Sliders, ID_Sliders + 999, wxEVT_COMMAND_SLIDER_UPDATED, VSTEffect::OnSlider)
930 
931  // Events from the audioMaster callback
932  EVT_COMMAND(wxID_ANY, EVT_SIZEWINDOW, VSTEffect::OnSizeWindow)
934 
935 // Needed to support shell plugins...sucks, but whatcha gonna do???
936 intptr_t VSTEffect::mCurrentEffectID;
937 
938 typedef AEffect *(*vstPluginMain)(audioMasterCallback audioMaster);
939 
940 intptr_t VSTEffect::AudioMaster(AEffect * effect,
941  int32_t opcode,
942  int32_t index,
943  intptr_t value,
944  void * ptr,
945  float opt)
946 {
947  VSTEffect *vst = (effect ? (VSTEffect *) effect->ptr2 : NULL);
948 
949  // Handles operations during initialization...before VSTEffect has had a
950  // chance to set its instance pointer.
951  switch (opcode)
952  {
953  case audioMasterVersion:
954  return (intptr_t) 2400;
955 
957  return mCurrentEffectID;
958 
960  strcpy((char *) ptr, "Audacity Team"); // Do not translate, max 64 + 1 for null terminator
961  return 1;
962 
964  strcpy((char *) ptr, "Audacity"); // Do not translate, max 64 + 1 for null terminator
965  return 1;
966 
968  return (intptr_t) (AUDACITY_VERSION << 24 |
969  AUDACITY_RELEASE << 16 |
970  AUDACITY_REVISION << 8 |
971  AUDACITY_MODLEVEL);
972 
973  // Some (older) effects depend on an effIdle call when requested. An
974  // example is the Antress Modern plugins which uses the call to update
975  // the editors display when the program (preset) changes.
976  case audioMasterNeedIdle:
977  if (vst)
978  {
979  vst->NeedIdle();
980  return 1;
981  }
982  return 0;
983 
984  // We would normally get this if the effect editor is dipslayed and something "major"
985  // has changed (like a program change) instead of multiple automation calls.
986  // Since we don't do anything with the parameters while the editor is displayed,
987  // there's no need for us to do anything.
989  if (vst)
990  {
991  vst->UpdateDisplay();
992  return 1;
993  }
994  return 0;
995 
996  // Return the current time info.
997  case audioMasterGetTime:
998  if (vst)
999  {
1000  return (intptr_t) vst->GetTimeInfo();
1001  }
1002  return 0;
1003 
1004  // Inputs, outputs, or initial delay has changed...all we care about is initial delay.
1005  case audioMasterIOChanged:
1006  if (vst)
1007  {
1008  vst->SetBufferDelay(effect->initialDelay);
1009  return 1;
1010  }
1011  return 0;
1012 
1014  if (vst)
1015  {
1016  return (intptr_t) vst->GetSampleRate();
1017  }
1018  return 0;
1019 
1020  case audioMasterIdle:
1021  wxYieldIfNeeded();
1022  return 1;
1023 
1025  if (vst)
1026  {
1027  return vst->GetProcessLevel();
1028  }
1029  return 0;
1030 
1032  return kVstLangEnglish;
1033 
1034  // We always replace, never accumulate
1036  return 1;
1037 
1038  // Resize the window to accommodate the effect size
1039  case audioMasterSizeWindow:
1040  if (vst)
1041  {
1042  vst->SizeWindow(index, value);
1043  }
1044  return 1;
1045 
1046  case audioMasterCanDo:
1047  {
1048  char *s = (char *) ptr;
1049  if (strcmp(s, "acceptIOChanges") == 0 ||
1050  strcmp(s, "sendVstTimeInfo") == 0 ||
1051  strcmp(s, "startStopProcess") == 0 ||
1052  strcmp(s, "shellCategory") == 0 ||
1053  strcmp(s, "sizeWindow") == 0)
1054  {
1055  return 1;
1056  }
1057 
1058 #if defined(VST_DEBUG)
1059 #if defined(__WXMSW__)
1060  wxLogDebug(wxT("VST canDo: %s"), wxString::FromAscii((char *)ptr));
1061 #else
1062  wxPrintf(wxT("VST canDo: %s\n"), wxString::FromAscii((char *)ptr));
1063 #endif
1064 #endif
1065 
1066  return 0;
1067  }
1068 
1069  case audioMasterBeginEdit:
1070  case audioMasterEndEdit:
1071  return 0;
1072 
1073  case audioMasterAutomate:
1074  if (vst)
1075  {
1076  vst->Automate(index, opt);
1077  }
1078  return 0;
1079 
1080  // We're always connected (sort of)
1082 
1083  // We don't do MIDI yet
1084  case audioMasterWantMidi:
1086 
1087  // Don't need to see any messages about these
1088  return 0;
1089  }
1090 
1091 #if defined(VST_DEBUG)
1092 #if defined(__WXMSW__)
1093  wxLogDebug(wxT("vst: %p opcode: %d index: %d value: %p ptr: %p opt: %f user: %p"),
1094  effect, (int) opcode, (int) index, (void *) value, ptr, opt, vst);
1095 #else
1096  wxPrintf(wxT("vst: %p opcode: %d index: %d value: %p ptr: %p opt: %f user: %p\n"),
1097  effect, (int) opcode, (int) index, (void *) value, ptr, opt, vst);
1098 #endif
1099 #endif
1100 
1101  return 0;
1102 }
1103 
1104 #if !defined(__WXMSW__)
1106 {
1107  if (p)
1108  dlclose(p);
1109 }
1110 #endif
1111 
1112 #if defined(__WXMAC__)
1113 void VSTEffect::BundleDeleter::operator() (void* p) const
1114 {
1115  if (p)
1116  CFRelease(static_cast<CFBundleRef>(p));
1117 }
1118 
1119 void VSTEffect::ResourceHandle::reset()
1120 {
1121  if (mpHandle)
1122  CFBundleCloseBundleResourceMap(mpHandle, mNum);
1123  mpHandle = nullptr;
1124  mNum = 0;
1125 }
1126 #endif
1127 
1129 : mPath(path),
1130  mMaster(master)
1131 {
1132  mHost = NULL;
1133  mModule = NULL;
1134  mAEffect = NULL;
1135  mDialog = NULL;
1136 
1137  mTimer = std::make_unique<VSTEffectTimer>(this);
1138  mTimerGuard = 0;
1139 
1140  mInteractive = false;
1141  mAudioIns = 0;
1142  mAudioOuts = 0;
1143  mMidiIns = 0;
1144  mMidiOuts = 0;
1145  mSampleRate = 44100;
1146  mBlockSize = mUserBlockSize = 8192;
1147  mBufferDelay = 0;
1148  mProcessLevel = 1; // in GUI thread
1149  mHasPower = false;
1150  mWantsIdle = false;
1151  mWantsEditIdle = false;
1152  mUseLatency = true;
1153  mReady = false;
1154 
1155  memset(&mTimeInfo, 0, sizeof(mTimeInfo));
1156  mTimeInfo.samplePos = 0.0;
1157  mTimeInfo.sampleRate = 44100.0; // this is a bogus value, but it's only for the display
1158  mTimeInfo.nanoSeconds = wxGetUTCTimeMillis().ToDouble();
1159  mTimeInfo.tempo = 120.0;
1163 
1164  // UI
1165 
1166  mGui = false;
1167  mContainer = NULL;
1168 
1169  // If we're a slave then go ahead a load immediately
1170  if (mMaster)
1171  {
1172  Load();
1173  }
1174 }
1175 
1177 {
1178  if (mDialog)
1179  {
1180  mDialog->Close();
1181  }
1182 
1183  Unload();
1184 }
1185 
1186 // ============================================================================
1187 // ComponentInterface Implementation
1188 // ============================================================================
1189 
1191 {
1192  return mPath;
1193 }
1194 
1196 {
1197  return mName;
1198 }
1199 
1201 {
1202  return { mVendor };
1203 }
1204 
1206 {
1207  wxString version;
1208 
1209  bool skipping = true;
1210  for (int i = 0, s = 0; i < 4; i++, s += 8)
1211  {
1212  int dig = (mVersion >> s) & 0xff;
1213  if (dig != 0 || !skipping)
1214  {
1215  version += !skipping ? wxT(".") : wxT("");
1216  version += wxString::Format(wxT("%d"), dig);
1217  skipping = false;
1218  }
1219  }
1220 
1221  return version;
1222 }
1223 
1225 {
1226  // VST does have a product string opcode and some effects return a short
1227  // description, but most do not or they just return the name again. So,
1228  // try to provide some sort of useful information.
1229  return XO("Audio In: %d, Audio Out: %d").Format( mAudioIns, mAudioOuts );
1230 }
1231 
1232 // ============================================================================
1233 // EffectDefinitionInterface Implementation
1234 // ============================================================================
1235 
1237 {
1238  if (mAudioIns == 0 && mAudioOuts == 0 && mMidiIns == 0 && mMidiOuts == 0)
1239  {
1240  return EffectTypeTool;
1241  }
1242 
1243  if (mAudioIns == 0 && mMidiIns == 0)
1244  {
1245  return EffectTypeGenerate;
1246  }
1247 
1248  if (mAudioOuts == 0 && mMidiOuts == 0)
1249  {
1250  return EffectTypeAnalyze;
1251  }
1252 
1253  return EffectTypeProcess;
1254 }
1255 
1256 
1258 {
1259  return VSTPLUGINTYPE;
1260 }
1261 
1263 {
1264  return mInteractive;
1265 }
1266 
1268 {
1269  return false;
1270 }
1271 
1273 {
1274  return false;
1275 }
1276 
1278 {
1279  return GetType() == EffectTypeProcess;
1280 }
1281 
1283 {
1284  return mAutomatable;
1285 }
1286 
1287 // ============================================================================
1288 // EffectClientInterface Implementation
1289 // ============================================================================
1290 
1292 {
1293  mHost = host;
1294 
1295  if (!mAEffect)
1296  {
1297  Load();
1298  }
1299 
1300  if (!mAEffect)
1301  {
1302  return false;
1303  }
1304 
1305  // If we have a master then there's no need to load settings since the master will feed
1306  // us everything we need.
1307  if (mMaster)
1308  {
1309  return true;
1310  }
1311 
1312  if (mHost)
1313  {
1314  int userBlockSize;
1315  mHost->GetSharedConfig(wxT("Options"), wxT("BufferSize"), userBlockSize, 8192);
1316  mUserBlockSize = std::max( 1, userBlockSize );
1317  mHost->GetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency, true);
1318 
1320 
1321  bool haveDefaults;
1322  mHost->GetPrivateConfig(mHost->GetFactoryDefaultsGroup(), wxT("Initialized"), haveDefaults, false);
1323  if (!haveDefaults)
1324  {
1326  mHost->SetPrivateConfig(mHost->GetFactoryDefaultsGroup(), wxT("Initialized"), true);
1327  }
1328 
1330  }
1331 
1332  return true;
1333 }
1334 
1336 {
1337  return mAudioIns;
1338 }
1339 
1341 {
1342  return mAudioOuts;
1343 }
1344 
1346 {
1347  return mMidiIns;
1348 }
1349 
1351 {
1352  return mMidiOuts;
1353 }
1354 
1355 size_t VSTEffect::SetBlockSize(size_t maxBlockSize)
1356 {
1357  mBlockSize = std::min( maxBlockSize, mUserBlockSize );
1358  return mBlockSize;
1359 }
1360 
1362 {
1363  return mBlockSize;
1364 }
1365 
1366 void VSTEffect::SetSampleRate(double rate)
1367 {
1368  mSampleRate = (float) rate;
1369 }
1370 
1372 {
1373  if (mUseLatency)
1374  {
1375  // ??? Threading issue ???
1376  auto delay = mBufferDelay;
1377  mBufferDelay = 0;
1378  return delay;
1379  }
1380 
1381  return 0;
1382 }
1383 
1385 {
1386  return 0;
1387 }
1388 
1390 {
1391  return mReady;
1392 }
1393 
1394 bool VSTEffect::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames WXUNUSED(chanMap))
1395 {
1396  // Initialize time info
1397  memset(&mTimeInfo, 0, sizeof(mTimeInfo));
1399  mTimeInfo.nanoSeconds = wxGetUTCTimeMillis().ToDouble();
1400  mTimeInfo.tempo = 120.0;
1404 
1405  // Set processing parameters...power must be off for this
1407  callDispatcher(effSetBlockSize, 0, mBlockSize, NULL, 0.0);
1408 
1409  // Turn on the power
1410  PowerOn();
1411 
1412  // Set the initial buffer delay
1414 
1415  mReady = true;
1416 
1417  return true;
1418 }
1419 
1421 {
1422  mReady = false;
1423 
1424  PowerOff();
1425 
1426  return true;
1427 }
1428 
1429 size_t VSTEffect::ProcessBlock(float **inBlock, float **outBlock, size_t blockLen)
1430 {
1431  // Only call the effect if there's something to do...some do not like zero-length block
1432  if (blockLen)
1433  {
1434  // Go let the plugin moleste the samples
1435  callProcessReplacing(inBlock, outBlock, blockLen);
1436 
1437  // And track the position
1438  mTimeInfo.samplePos += ((double) blockLen / mTimeInfo.sampleRate);
1439  }
1440 
1441  return blockLen;
1442 }
1443 
1445 {
1446  return mNumChannels;
1447 }
1448 
1449 void VSTEffect::SetChannelCount(unsigned numChannels)
1450 {
1451  mNumChannels = numChannels;
1452 }
1453 
1455 {
1458 
1459  return ProcessInitialize(0, NULL);
1460 }
1461 
1462 bool VSTEffect::RealtimeAddProcessor(unsigned numChannels, float sampleRate)
1463 {
1464  mSlaves.push_back(std::make_unique<VSTEffect>(mPath, this));
1465  VSTEffect *const slave = mSlaves.back().get();
1466 
1467  slave->SetBlockSize(mBlockSize);
1468  slave->SetChannelCount(numChannels);
1469  slave->SetSampleRate(sampleRate);
1470 
1471  int clen = 0;
1473  {
1474  void *chunk = NULL;
1475 
1476  clen = (int) callDispatcher(effGetChunk, 1, 0, &chunk, 0.0); // get master's chunk, for the program only
1477  if (clen != 0)
1478  {
1479  slave->callSetChunk(true, clen, chunk); // copy state to slave, for the program only
1480  }
1481  }
1482 
1483  if (clen == 0)
1484  {
1485  callDispatcher(effBeginSetProgram, 0, 0, NULL, 0.0);
1486 
1487  for (int i = 0; i < mAEffect->numParams; i++)
1488  {
1489  slave->callSetParameter(i, callGetParameter(i));
1490  }
1491 
1492  callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
1493  }
1494 
1495  return slave->ProcessInitialize(0, NULL);
1496 }
1497 
1499 {
1500  for (const auto &slave : mSlaves)
1501  slave->ProcessFinalize();
1502  mSlaves.clear();
1503 
1504  mMasterIn.reset();
1505 
1506  mMasterOut.reset();
1507 
1508  return ProcessFinalize();
1509 }
1510 
1512 {
1513  PowerOff();
1514 
1515  for (const auto &slave : mSlaves)
1516  slave->PowerOff();
1517 
1518  return true;
1519 }
1520 
1522 {
1523  PowerOn();
1524 
1525  for (const auto &slave : mSlaves)
1526  slave->PowerOn();
1527 
1528  return true;
1529 }
1530 
1532 {
1533  for (unsigned int i = 0; i < mAudioIns; i++)
1534  memset(mMasterIn[i].get(), 0, mBlockSize * sizeof(float));
1535 
1536  mNumSamples = 0;
1537 
1538  return true;
1539 }
1540 
1541 size_t VSTEffect::RealtimeProcess(int group, float **inbuf, float **outbuf, size_t numSamples)
1542 {
1543  wxASSERT(numSamples <= mBlockSize);
1544 
1545  for (unsigned int c = 0; c < mAudioIns; c++)
1546  {
1547  for (decltype(numSamples) s = 0; s < numSamples; s++)
1548  {
1549  mMasterIn[c][s] += inbuf[c][s];
1550  }
1551  }
1552  mNumSamples = std::max(numSamples, mNumSamples);
1553 
1554  return mSlaves[group]->ProcessBlock(inbuf, outbuf, numSamples);
1555 }
1556 
1558 {
1559  // These casts to float** should be safe...
1560  ProcessBlock(
1561  reinterpret_cast <float**> (mMasterIn.get()),
1562  reinterpret_cast <float**> (mMasterOut.get()),
1563  mNumSamples);
1564 
1565  return true;
1566 }
1567 
1595  wxWindow &parent, const EffectDialogFactory &factory, bool forceModal)
1596 {
1597  if (mDialog)
1598  {
1599  if ( mDialog->Close(true) )
1600  mDialog = nullptr;
1601  return false;
1602  }
1603 
1604  // mDialog is null
1605  auto cleanup = valueRestorer( mDialog );
1606 
1607  // mProcessLevel = 1; // in GUI thread
1608 
1609  // Set some defaults since some VSTs need them...these will be reset when
1610  // normal or realtime processing begins
1611  if (!IsReady())
1612  {
1613  mSampleRate = 44100;
1614  mBlockSize = 8192;
1615  ProcessInitialize(0, NULL);
1616  }
1617 
1618  if ( factory )
1619  mDialog = factory(parent, mHost, this);
1620  if (!mDialog)
1621  {
1622  return false;
1623  }
1624  mDialog->CentreOnParent();
1625 
1626  if (SupportsRealtime() && !forceModal)
1627  {
1628  mDialog->Show();
1629  cleanup.release();
1630 
1631  return false;
1632  }
1633 
1634  bool res = mDialog->ShowModal() != 0;
1635 
1636  return res;
1637 }
1638 
1640 {
1641  for (int i = 0; i < mAEffect->numParams; i++)
1642  {
1643  wxString name = GetString(effGetParamName, i);
1644  if (name.empty())
1645  {
1646  name.Printf(wxT("parm_%d"), i);
1647  }
1648 
1649  float value = callGetParameter(i);
1650  if (!parms.Write(name, value))
1651  {
1652  return false;
1653  }
1654  }
1655 
1656  return true;
1657 }
1658 
1660 {
1661  callDispatcher(effBeginSetProgram, 0, 0, NULL, 0.0);
1662  for (int i = 0; i < mAEffect->numParams; i++)
1663  {
1664  wxString name = GetString(effGetParamName, i);
1665  if (name.empty())
1666  {
1667  name.Printf(wxT("parm_%d"), i);
1668  }
1669 
1670  double d = 0.0;
1671  if (!parms.Read(name, &d))
1672  {
1673  return false;
1674  }
1675 
1676  if (d >= -1.0 && d <= 1.0)
1677  {
1678  callSetParameter(i, d);
1679  for (const auto &slave : mSlaves)
1680  slave->callSetParameter(i, d);
1681  }
1682  }
1683  callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
1684 
1685  return true;
1686 }
1687 
1688 
1690 {
1691  if (!LoadParameters(name))
1692  {
1693  return false;
1694  }
1695 
1697 
1698  return true;
1699 }
1700 
1702 {
1703  return SaveParameters(name);
1704 }
1705 
1707 {
1708  RegistryPaths progs;
1709 
1710  // Some plugins, like Guitar Rig 5, only report 128 programs while they have hundreds. While
1711  // I was able to come up with a hack in the Guitar Rig case to gather all of the program names
1712  // it would not let me set a program outside of the first 128.
1713  if (mVstVersion >= 2)
1714  {
1715  for (int i = 0; i < mAEffect->numPrograms; i++)
1716  {
1717  progs.push_back(GetString(effGetProgramNameIndexed, i));
1718  }
1719  }
1720 
1721  return progs;
1722 }
1723 
1725 {
1726  callSetProgram(id);
1727 
1729 
1730  return true;
1731 }
1732 
1734 {
1736  {
1737  return false;
1738  }
1739 
1741 
1742  return true;
1743 }
1744 
1745 // ============================================================================
1746 // EffectUIClientInterface implementation
1747 // ============================================================================
1748 
1750 {
1751  mUIHost = host;
1752 }
1753 
1755 {
1756  auto parent = S.GetParent();
1757  mDialog = static_cast<wxDialog *>(wxGetTopLevelParent(parent));
1758  mParent = parent;
1759 
1760  mParent->PushEventHandler(this);
1761 
1762  // Determine if the VST editor is supposed to be used or not
1763  mHost->GetSharedConfig(wxT("Options"),
1764  wxT("UseGUI"),
1765  mGui,
1766  true);
1767  mGui = mAEffect->flags & effFlagsHasEditor ? mGui : false;
1768 
1769  // Must use the GUI editor if parameters aren't provided
1770  if (mAEffect->numParams == 0)
1771  {
1772  mGui = true;
1773  }
1774 
1775  // Build the appropriate dialog type
1776  if (mGui)
1777  {
1778  BuildFancy();
1779  }
1780  else
1781  {
1782  BuildPlain();
1783  }
1784 
1785  return true;
1786 }
1787 
1789 {
1790  return mGui;
1791 }
1792 
1794 {
1795  if (!mParent->Validate() || !mParent->TransferDataFromWindow())
1796  {
1797  return false;
1798  }
1799 
1800  if (GetType() == EffectTypeGenerate)
1801  {
1803  }
1804 
1805  return true;
1806 }
1807 
1809 {
1810  return true;
1811 }
1812 
1814 {
1815 #ifdef __WXMAC__
1816 #ifdef __WX_EVTLOOP_BUSY_WAITING__
1817  wxEventLoop::SetBusyWaiting(false);
1818 #endif
1819  mControl->Close();
1820 #endif
1821 
1822  mParent->RemoveEventHandler(this);
1823 
1824  PowerOff();
1825 
1826  NeedEditIdle(false);
1827 
1828  RemoveHandler();
1829 
1830  mNames.reset();
1831  mSliders.reset();
1832  mDisplays.reset();
1833  mLabels.reset();
1834 
1835  mUIHost = NULL;
1836  mParent = NULL;
1837  mDialog = NULL;
1838 
1839  return true;
1840 }
1841 
1843 {
1844  return true;
1845 }
1846 
1847 // Throws exceptions rather than reporting errors.
1849 {
1850  wxString path;
1851 
1852  // Ask the user for the real name
1853  //
1854  // Passing a valid parent will cause some effects dialogs to malfunction
1855  // upon returning from the FileNames::SelectFile().
1856  path = FileNames::SelectFile(FileNames::Operation::Presets,
1857  XO("Save VST Preset As:"),
1858  wxEmptyString,
1859  wxT("preset"),
1860  wxT("xml"),
1861  {
1862  { XO("Standard VST bank file"), { wxT("fxb") }, true },
1863  { XO("Standard VST program file"), { wxT("fxp") }, true },
1864  { XO("Audacity VST preset file"), { wxT("xml") }, true },
1865  },
1866  wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
1867  NULL);
1868 
1869  // User canceled...
1870  if (path.empty())
1871  {
1872  return;
1873  }
1874 
1875  wxFileName fn(path);
1876  wxString ext = fn.GetExt();
1877  if (ext.CmpNoCase(wxT("fxb")) == 0)
1878  {
1879  SaveFXB(fn);
1880  }
1881  else if (ext.CmpNoCase(wxT("fxp")) == 0)
1882  {
1883  SaveFXP(fn);
1884  }
1885  else if (ext.CmpNoCase(wxT("xml")) == 0)
1886  {
1887  // may throw
1888  SaveXML(fn);
1889  }
1890  else
1891  {
1892  // This shouldn't happen, but complain anyway
1894  XO("Unrecognized file extension."),
1895  XO("Error Saving VST Presets"),
1896  wxOK | wxCENTRE,
1897  mParent);
1898 
1899  return;
1900  }
1901 }
1902 
1903 //
1904 // Load an "fxb", "fxp" or Audacuty "xml" file
1905 //
1906 // Based on work by Sven Giermann
1907 //
1909 {
1910  wxString path;
1911 
1912  // Ask the user for the real name
1913  path = FileNames::SelectFile(FileNames::Operation::Presets,
1914  XO("Load VST Preset:"),
1915  wxEmptyString,
1916  wxT("preset"),
1917  wxT("xml"),
1918  { {
1919  XO("VST preset files"),
1920  { wxT("fxb"), wxT("fxp"), wxT("xml") },
1921  true
1922  } },
1923  wxFD_OPEN | wxRESIZE_BORDER,
1924  mParent);
1925 
1926  // User canceled...
1927  if (path.empty())
1928  {
1929  return;
1930  }
1931 
1932  wxFileName fn(path);
1933  wxString ext = fn.GetExt();
1934  bool success = false;
1935  if (ext.CmpNoCase(wxT("fxb")) == 0)
1936  {
1937  success = LoadFXB(fn);
1938  }
1939  else if (ext.CmpNoCase(wxT("fxp")) == 0)
1940  {
1941  success = LoadFXP(fn);
1942  }
1943  else if (ext.CmpNoCase(wxT("xml")) == 0)
1944  {
1945  success = LoadXML(fn);
1946  }
1947  else
1948  {
1949  // This shouldn't happen, but complain anyway
1951  XO("Unrecognized file extension."),
1952  XO("Error Loading VST Presets"),
1953  wxOK | wxCENTRE,
1954  mParent);
1955 
1956  return;
1957  }
1958 
1959  if (!success)
1960  {
1962  XO("Unable to load presets file."),
1963  XO("Error Loading VST Presets"),
1964  wxOK | wxCENTRE,
1965  mParent);
1966 
1967  return;
1968  }
1969 
1971 
1972  return;
1973 }
1974 
1976 {
1977  return true;
1978 }
1979 
1981 {
1983  if (dlg.ShowModal())
1984  {
1985  // Reinitialize configuration settings
1986  int userBlockSize;
1987  mHost->GetSharedConfig(wxT("Options"), wxT("BufferSize"), userBlockSize, 8192);
1988  mUserBlockSize = std::max( 1, userBlockSize );
1989  mHost->GetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency, true);
1990  }
1991 }
1992 
1993 // ============================================================================
1994 // VSTEffect implementation
1995 // ============================================================================
1996 
1998 {
1999  vstPluginMain pluginMain;
2000  bool success = false;
2001 
2002  long effectID = 0;
2003  wxString realPath = mPath.BeforeFirst(wxT(';'));
2004  mPath.AfterFirst(wxT(';')).ToLong(&effectID);
2005  mCurrentEffectID = (intptr_t) effectID;
2006 
2007  mModule = NULL;
2008  mAEffect = NULL;
2009 
2010 #if defined(__WXMAC__)
2011  // Start clean
2012  mBundleRef.reset();
2013 
2014  mResource = ResourceHandle{};
2015 
2016  // Convert the path to a CFSTring
2017  wxCFStringRef path(realPath);
2018 
2019  // Convert the path to a URL
2020  CFURLRef urlRef =
2021  CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
2022  path,
2023  kCFURLPOSIXPathStyle,
2024  true);
2025  if (urlRef == NULL)
2026  {
2027  return false;
2028  }
2029 
2030  // Create the bundle using the URL
2031  BundleHandle bundleRef{ CFBundleCreate(kCFAllocatorDefault, urlRef) };
2032 
2033  // Done with the URL
2034  CFRelease(urlRef);
2035 
2036  // Bail if the bundle wasn't created
2037  if (!bundleRef)
2038  {
2039  return false;
2040  }
2041 
2042  // Retrieve a reference to the executable
2043  CFURLRef exeRef = CFBundleCopyExecutableURL(bundleRef.get());
2044  if (!exeRef)
2045  return false;
2046 
2047  // Convert back to path
2048  UInt8 exePath[PLATFORM_MAX_PATH];
2049  Boolean good = CFURLGetFileSystemRepresentation(exeRef, true, exePath, sizeof(exePath));
2050 
2051  // Done with the executable reference
2052  CFRelease(exeRef);
2053 
2054  // Bail if we couldn't resolve the executable path
2055  if (good == FALSE)
2056  return false;
2057 
2058  // Attempt to open it
2059  mModule.reset((char*)dlopen((char *) exePath, RTLD_NOW | RTLD_LOCAL));
2060  if (!mModule)
2061  return false;
2062 
2063  // Try to locate the NEW plugin entry point
2064  pluginMain = (vstPluginMain) dlsym(mModule.get(), "VSTPluginMain");
2065 
2066  // If not found, try finding the old entry point
2067  if (pluginMain == NULL)
2068  {
2069  pluginMain = (vstPluginMain) dlsym(mModule.get(), "main_macho");
2070  }
2071 
2072  // Must not be a VST plugin
2073  if (pluginMain == NULL)
2074  {
2075  mModule.reset();
2076  return false;
2077  }
2078 
2079  // Need to keep the bundle reference around so we can map the
2080  // resources.
2081  mBundleRef = std::move(bundleRef);
2082 
2083  // Open the resource map ... some plugins (like GRM Tools) need this.
2084  mResource = ResourceHandle{
2085  mBundleRef.get(), CFBundleOpenBundleResourceMap(mBundleRef.get())
2086  };
2087 
2088 #elif defined(__WXMSW__)
2089 
2090  {
2091  wxLogNull nolog;
2092 
2093  // Try to load the library
2094  auto lib = std::make_unique<wxDynamicLibrary>(realPath);
2095  if (!lib)
2096  return false;
2097 
2098  // Bail if it wasn't successful
2099  if (!lib->IsLoaded())
2100  return false;
2101 
2102  // Try to find the entry point, while suppressing error messages
2103  pluginMain = (vstPluginMain) lib->GetSymbol(wxT("VSTPluginMain"));
2104  if (pluginMain == NULL)
2105  {
2106  pluginMain = (vstPluginMain) lib->GetSymbol(wxT("main"));
2107  if (pluginMain == NULL)
2108  return false;
2109  }
2110 
2111  // Save the library reference
2112  mModule = std::move(lib);
2113  }
2114 
2115 #else
2116 
2117  // Attempt to load it
2118  //
2119  // Spent a few days trying to figure out why some VSTs where running okay and
2120  // others were hit or miss. The cause was that we export all of Audacity's
2121  // symbols and some of the loaded libraries were picking up Audacity's and
2122  // not their own.
2123  //
2124  // So far, I've only seen this issue on Linux, but we might just be getting
2125  // lucky on the Mac and Windows. The sooner we stop exporting everything
2126  // the better.
2127  //
2128  // To get around the problem, I just added the RTLD_DEEPBIND flag to the load
2129  // and that "basically" puts Audacity last when the loader needs to resolve
2130  // symbols.
2131  //
2132  // Once we define a proper external API, the flags can be removed.
2133 #ifndef RTLD_DEEPBIND
2134 #define RTLD_DEEPBIND 0
2135 #endif
2136  ModuleHandle lib {
2137  (char*) dlopen((const char *)wxString(realPath).ToUTF8(),
2138  RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND)
2139  };
2140  if (!lib)
2141  {
2142  return false;
2143  }
2144 
2145  // Try to find the entry point, while suppressing error messages
2146  pluginMain = (vstPluginMain) dlsym(lib.get(), "VSTPluginMain");
2147  if (pluginMain == NULL)
2148  {
2149  pluginMain = (vstPluginMain) dlsym(lib.get(), "main");
2150  if (pluginMain == NULL)
2151  return false;
2152  }
2153 
2154  // Save the library reference
2155  mModule = std::move(lib);
2156 
2157 #endif
2158 
2159  // Initialize the plugin
2160  try
2161  {
2162  mAEffect = pluginMain(VSTEffect::AudioMaster);
2163  }
2164  catch (...)
2165  {
2166  wxLogMessage(wxT("VST plugin initialization failed\n"));
2167  mAEffect = NULL;
2168  }
2169 
2170  // Was it successful?
2171  if (mAEffect)
2172  {
2173  // Save a reference to ourselves
2174  //
2175  // Note: Some hosts use "user" and some use "ptr2/resvd2". It might
2176  // be worthwhile to check if user is NULL before using it and
2177  // then falling back to "ptr2/resvd2".
2178  mAEffect->ptr2 = this;
2179 
2180  // Give the plugin an initial sample rate and blocksize
2181  callDispatcher(effSetSampleRate, 0, 0, NULL, 48000.0);
2182  callDispatcher(effSetBlockSize, 0, 512, NULL, 0);
2183 
2184  // Ask the plugin to identify itself...might be needed for older plugins
2185  callDispatcher(effIdentify, 0, 0, NULL, 0);
2186 
2187  // Open the plugin
2188  callDispatcher(effOpen, 0, 0, NULL, 0.0);
2189 
2190  // Get the VST version the plugin understands
2191  mVstVersion = callDispatcher(effGetVstVersion, 0, 0, NULL, 0);
2192 
2193  // Set it again in case plugin ignored it before the effOpen
2194  callDispatcher(effSetSampleRate, 0, 0, NULL, 48000.0);
2195  callDispatcher(effSetBlockSize, 0, 512, NULL, 0);
2196 
2197  // Ensure that it looks like a plugin and can deal with ProcessReplacing
2198  // calls. Also exclude synths for now.
2199  if (mAEffect->magic == kEffectMagic &&
2200  !(mAEffect->flags & effFlagsIsSynth) &&
2202  {
2203  if (mVstVersion >= 2)
2204  {
2206  if (mName.length() == 0)
2207  {
2209  }
2210  }
2211  if (mName.length() == 0)
2212  {
2213  mName = wxFileName{realPath}.GetName();
2214  }
2215 
2216  if (mVstVersion >= 2)
2217  {
2219  mVersion = wxINT32_SWAP_ON_LE(callDispatcher(effGetVendorVersion, 0, 0, NULL, 0));
2220  }
2221  if (mVersion == 0)
2222  {
2223  mVersion = wxINT32_SWAP_ON_LE(mAEffect->version);
2224  }
2225 
2227  {
2228  mInteractive = true;
2229  }
2230 
2233 
2234  mMidiIns = 0;
2235  mMidiOuts = 0;
2236 
2237  // Check to see if parameters can be automated. This isn't a guarantee
2238  // since it could be that the effect simply doesn't support the opcode.
2239  mAutomatable = false;
2240  for (int i = 0; i < mAEffect->numParams; i++)
2241  {
2242  if (callDispatcher(effCanBeAutomated, 0, i, NULL, 0.0))
2243  {
2244  mAutomatable = true;
2245  break;
2246  }
2247  }
2248 
2249  // Make sure we start out with a valid program selection
2250  // I've found one plugin (SoundHack +morphfilter) that will
2251  // crash Audacity when saving the initial default parameters
2252  // with this.
2253  callSetProgram(0);
2254 
2255  // Pretty confident that we're good to go
2256  success = true;
2257  }
2258  }
2259 
2260  if (!success)
2261  {
2262  Unload();
2263  }
2264 
2265  return success;
2266 }
2267 
2269 {
2270  if (mDialog)
2271  {
2272  CloseUI();
2273  }
2274 
2275  if (mAEffect)
2276  {
2277  // Turn the power off
2278  PowerOff();
2279 
2280  // Finally, close the plugin
2281  callDispatcher(effClose, 0, 0, NULL, 0.0);
2282  mAEffect = NULL;
2283  }
2284 
2285  if (mModule)
2286  {
2287 #if defined(__WXMAC__)
2288  mResource.reset();
2289  mBundleRef.reset();
2290 #endif
2291 
2292  mModule.reset();
2293  mAEffect = NULL;
2294  }
2295 }
2296 
2297 std::vector<int> VSTEffect::GetEffectIDs()
2298 {
2299  std::vector<int> effectIDs;
2300 
2301  // Are we a shell?
2303  {
2304  char name[64];
2305  int effectID;
2306 
2307  effectID = (int) callDispatcher(effShellGetNextPlugin, 0, 0, &name, 0);
2308  while (effectID)
2309  {
2310  effectIDs.push_back(effectID);
2311  effectID = (int) callDispatcher(effShellGetNextPlugin, 0, 0, &name, 0);
2312  }
2313  }
2314 
2315  return effectIDs;
2316 }
2317 
2319 {
2320  wxString value;
2321 
2323  mHost->GetPrivateConfig(group, wxT("UniqueID"), info.pluginUniqueID, info.pluginUniqueID);
2324  mHost->GetPrivateConfig(group, wxT("Version"), info.pluginVersion, info.pluginVersion);
2325  mHost->GetPrivateConfig(group, wxT("Elements"), info.numElements, info.numElements);
2326 
2327  if ((info.pluginUniqueID != mAEffect->uniqueID) ||
2328  (info.pluginVersion != mAEffect->version) ||
2329  (info.numElements != mAEffect->numParams))
2330  {
2331  return false;
2332  }
2333 
2334  if (mHost->GetPrivateConfig(group, wxT("Chunk"), value, wxEmptyString))
2335  {
2336  ArrayOf<char> buf{ value.length() / 4 * 3 };
2337 
2338  int len = VSTEffect::b64decode(value, buf.get());
2339  if (len)
2340  {
2341  callSetChunk(true, len, buf.get(), &info);
2342  }
2343 
2344  return true;
2345  }
2346 
2347  wxString parms;
2348  if (!mHost->GetPrivateConfig(group, wxT("Parameters"), parms, wxEmptyString))
2349  {
2350  return false;
2351  }
2352 
2353  CommandParameters eap;
2354  if (!eap.SetParameters(parms))
2355  {
2356  return false;
2357  }
2358 
2359  return SetAutomationParameters(eap);
2360 }
2361 
2363 {
2364  mHost->SetPrivateConfig(group, wxT("UniqueID"), mAEffect->uniqueID);
2365  mHost->SetPrivateConfig(group, wxT("Version"), mAEffect->version);
2366  mHost->SetPrivateConfig(group, wxT("Elements"), mAEffect->numParams);
2367 
2369  {
2370  void *chunk = NULL;
2371  int clen = (int) callDispatcher(effGetChunk, 1, 0, &chunk, 0.0);
2372  if (clen <= 0)
2373  {
2374  return false;
2375  }
2376 
2377  mHost->SetPrivateConfig(group, wxT("Chunk"), VSTEffect::b64encode(chunk, clen));
2378  return true;
2379  }
2380 
2381  CommandParameters eap;
2382  if (!GetAutomationParameters(eap))
2383  {
2384  return false;
2385  }
2386 
2387  wxString parms;
2388  if (!eap.GetParameters(parms))
2389  {
2390  return false;
2391  }
2392 
2393  return mHost->SetPrivateConfig(group, wxT("Parameters"), parms);
2394 }
2395 
2397 {
2398  wxRecursionGuard guard(mTimerGuard);
2399 
2400  // Ignore it if we're recursing
2401  if (guard.IsInside())
2402  {
2403  return;
2404  }
2405 
2406  if (mVstVersion >= 2 && mWantsIdle)
2407  {
2408  int ret = callDispatcher(effIdle, 0, 0, NULL, 0.0);
2409  if (!ret)
2410  {
2411  mWantsIdle = false;
2412  }
2413  }
2414 
2415  if (mWantsEditIdle)
2416  {
2417  callDispatcher(effEditIdle, 0, 0, NULL, 0.0);
2418  }
2419 }
2420 
2422 {
2423  mWantsIdle = true;
2424  mTimer->Start(100);
2425 }
2426 
2427 void VSTEffect::NeedEditIdle(bool state)
2428 {
2429  mWantsEditIdle = state;
2430  mTimer->Start(100);
2431 }
2432 
2434 {
2435  mTimeInfo.nanoSeconds = wxGetUTCTimeMillis().ToDouble();
2436  return &mTimeInfo;
2437 }
2438 
2440 {
2441  return mTimeInfo.sampleRate;
2442 }
2443 
2445 {
2446  return mProcessLevel;
2447 }
2448 
2450 {
2451  if (!mHasPower)
2452  {
2453  // Turn the power on
2454  callDispatcher(effMainsChanged, 0, 1, NULL, 0.0);
2455 
2456  // Tell the effect we're going to start processing
2457  if (mVstVersion >= 2)
2458  {
2459  callDispatcher(effStartProcess, 0, 0, NULL, 0.0);
2460  }
2461 
2462  // Set state
2463  mHasPower = true;
2464  }
2465 }
2466 
2468 {
2469  if (mHasPower)
2470  {
2471  // Tell the effect we're going to stop processing
2472  if (mVstVersion >= 2)
2473  {
2474  callDispatcher(effStopProcess, 0, 0, NULL, 0.0);
2475  }
2476 
2477  // Turn the power off
2478  callDispatcher(effMainsChanged, 0, 0, NULL, 0.0);
2479 
2480  // Set state
2481  mHasPower = false;
2482  }
2483 }
2484 
2485 void VSTEffect::SizeWindow(int w, int h)
2486 {
2487  // Queue the event to make the resizes smoother
2488  if (mParent)
2489  {
2490  wxCommandEvent sw(EVT_SIZEWINDOW);
2491  sw.SetInt(w);
2492  sw.SetExtraLong(h);
2493  mParent->GetEventHandler()->AddPendingEvent(sw);
2494  }
2495 
2496  return;
2497 }
2498 
2500 {
2501 #if 0
2502  // Tell the dialog to refresh effect information
2503  if (mParent)
2504  {
2505  wxCommandEvent ud(EVT_UPDATEDISPLAY);
2506  mParent->GetEventHandler()->AddPendingEvent(ud);
2507  }
2508 #endif
2509  return;
2510 }
2511 
2512 void VSTEffect::Automate(int index, float value)
2513 {
2514  // Just ignore it if we're a slave
2515  if (mMaster)
2516  {
2517  return;
2518  }
2519 
2520  for (const auto &slave : mSlaves)
2521  slave->callSetParameter(index, value);
2522 
2523  return;
2524 }
2525 
2526 void VSTEffect::SetBufferDelay(int samples)
2527 {
2528  // We do not support negative delay
2529  if (samples >= 0 && mUseLatency)
2530  {
2531  mBufferDelay = samples;
2532  }
2533 
2534  return;
2535 }
2536 
2537 int VSTEffect::GetString(wxString & outstr, int opcode, int index)
2538 {
2539  char buf[256];
2540 
2541  memset(buf, 0, sizeof(buf));
2542 
2543  callDispatcher(opcode, index, 0, buf, 0.0);
2544 
2545  outstr = wxString::FromUTF8(buf);
2546 
2547  return 0;
2548 }
2549 
2550 wxString VSTEffect::GetString(int opcode, int index)
2551 {
2552  wxString str;
2553 
2554  GetString(str, opcode, index);
2555 
2556  return str;
2557 }
2558 
2559 void VSTEffect::SetString(int opcode, const wxString & str, int index)
2560 {
2561  char buf[256];
2562  strcpy(buf, str.Left(255).ToUTF8());
2563 
2564  callDispatcher(opcode, index, 0, buf, 0.0);
2565 }
2566 
2567 intptr_t VSTEffect::callDispatcher(int opcode,
2568  int index, intptr_t value, void *ptr, float opt)
2569 {
2570  // Needed since we might be in the dispatcher when the timer pops
2571  wxCRIT_SECT_LOCKER(locker, mDispatcherLock);
2572  return mAEffect->dispatcher(mAEffect, opcode, index, value, ptr, opt);
2573 }
2574 
2576  float **outputs, int sampleframes)
2577 {
2578  mAEffect->processReplacing(mAEffect, inputs, outputs, sampleframes);
2579 }
2580 
2582 {
2583  return mAEffect->getParameter(mAEffect, index);
2584 }
2585 
2586 void VSTEffect::callSetParameter(int index, float value)
2587 {
2588  if (mVstVersion == 0 || callDispatcher(effCanBeAutomated, 0, index, NULL, 0.0))
2589  {
2590  mAEffect->setParameter(mAEffect, index, value);
2591 
2592  for (const auto &slave : mSlaves)
2593  slave->callSetParameter(index, value);
2594  }
2595 }
2596 
2598 {
2599  callDispatcher(effBeginSetProgram, 0, 0, NULL, 0.0);
2600 
2601  callDispatcher(effSetProgram, 0, index, NULL, 0.0);
2602  for (const auto &slave : mSlaves)
2603  slave->callSetProgram(index);
2604 
2605  callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
2606 }
2607 
2608 void VSTEffect::callSetChunk(bool isPgm, int len, void *buf)
2609 {
2610  VstPatchChunkInfo info;
2611 
2612  memset(&info, 0, sizeof(info));
2613  info.version = 1;
2615  info.pluginVersion = mAEffect->version;
2616  info.numElements = isPgm ? mAEffect->numParams : mAEffect->numPrograms;
2617 
2618  callSetChunk(isPgm, len, buf, &info);
2619 }
2620 
2621 void VSTEffect::callSetChunk(bool isPgm, int len, void *buf, VstPatchChunkInfo *info)
2622 {
2623  if (isPgm)
2624  {
2625  // Ask the effect if this is an acceptable program
2626  if (callDispatcher(effBeginLoadProgram, 0, 0, info, 0.0) == -1)
2627  {
2628  return;
2629  }
2630  }
2631  else
2632  {
2633  // Ask the effect if this is an acceptable bank
2634  if (callDispatcher(effBeginLoadBank, 0, 0, info, 0.0) == -1)
2635  {
2636  return;
2637  }
2638  }
2639 
2640  callDispatcher(effBeginSetProgram, 0, 0, NULL, 0.0);
2641  callDispatcher(effSetChunk, isPgm ? 1 : 0, len, buf, 0.0);
2642  callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
2643 
2644  for (const auto &slave : mSlaves)
2645  slave->callSetChunk(isPgm, len, buf, info);
2646 }
2647 
2649 // Base64 en/decoding
2650 //
2651 // Original routines marked as public domain and found at:
2652 //
2653 // http://en.wikibooks.org/wiki/Algorithm_implementation/Miscellaneous/Base64
2654 //
2656 
2657 // Lookup table for encoding
2658 const static wxChar cset[] = wxT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
2659 const static char padc = wxT('=');
2660 
2661 wxString VSTEffect::b64encode(const void *in, int len)
2662 {
2663  unsigned char *p = (unsigned char *) in;
2664  wxString out;
2665 
2666  unsigned long temp;
2667  for (int i = 0; i < len / 3; i++)
2668  {
2669  temp = (*p++) << 16; //Convert to big endian
2670  temp += (*p++) << 8;
2671  temp += (*p++);
2672  out += cset[(temp & 0x00FC0000) >> 18];
2673  out += cset[(temp & 0x0003F000) >> 12];
2674  out += cset[(temp & 0x00000FC0) >> 6];
2675  out += cset[(temp & 0x0000003F)];
2676  }
2677 
2678  switch (len % 3)
2679  {
2680  case 1:
2681  temp = (*p++) << 16; //Convert to big endian
2682  out += cset[(temp & 0x00FC0000) >> 18];
2683  out += cset[(temp & 0x0003F000) >> 12];
2684  out += padc;
2685  out += padc;
2686  break;
2687 
2688  case 2:
2689  temp = (*p++) << 16; //Convert to big endian
2690  temp += (*p++) << 8;
2691  out += cset[(temp & 0x00FC0000) >> 18];
2692  out += cset[(temp & 0x0003F000) >> 12];
2693  out += cset[(temp & 0x00000FC0) >> 6];
2694  out += padc;
2695  break;
2696  }
2697 
2698  return out;
2699 }
2700 
2701 int VSTEffect::b64decode(const wxString &in, void *out)
2702 {
2703  int len = in.length();
2704  unsigned char *p = (unsigned char *) out;
2705 
2706  if (len % 4) //Sanity check
2707  {
2708  return 0;
2709  }
2710 
2711  int padding = 0;
2712  if (len)
2713  {
2714  if (in[len - 1] == padc)
2715  {
2716  padding++;
2717  }
2718 
2719  if (in[len - 2] == padc)
2720  {
2721  padding++;
2722  }
2723  }
2724 
2725  //const char *a = in.mb_str();
2726  //Setup a vector to hold the result
2727  unsigned long temp = 0; //Holds decoded quanta
2728  int i = 0;
2729  while (i < len)
2730  {
2731  for (int quantumPosition = 0; quantumPosition < 4; quantumPosition++)
2732  {
2733  unsigned char c = in[i];
2734  temp <<= 6;
2735 
2736  if (c >= 0x41 && c <= 0x5A)
2737  {
2738  temp |= c - 0x41;
2739  }
2740  else if (c >= 0x61 && c <= 0x7A)
2741  {
2742  temp |= c - 0x47;
2743  }
2744  else if (c >= 0x30 && c <= 0x39)
2745  {
2746  temp |= c + 0x04;
2747  }
2748  else if (c == 0x2B)
2749  {
2750  temp |= 0x3E;
2751  }
2752  else if (c == 0x2F)
2753  {
2754  temp |= 0x3F;
2755  }
2756  else if (c == padc)
2757  {
2758  switch (len - i)
2759  {
2760  case 1: //One pad character
2761  *p++ = (temp >> 16) & 0x000000FF;
2762  *p++ = (temp >> 8) & 0x000000FF;
2763  return p - (unsigned char *) out;
2764  case 2: //Two pad characters
2765  *p++ = (temp >> 10) & 0x000000FF;
2766  return p - (unsigned char *) out;
2767  }
2768  }
2769  i++;
2770  }
2771  *p++ = (temp >> 16) & 0x000000FF;
2772  *p++ = (temp >> 8) & 0x000000FF;
2773  *p++ = temp & 0x000000FF;
2774  }
2775 
2776  return p - (unsigned char *) out;
2777 }
2778 
2780 {
2781 }
2782 
2783 static void OnSize(wxSizeEvent & evt)
2784 {
2785  evt.Skip();
2786 
2787  // Once the parent dialog reaches its final size as indicated by
2788  // a non-default minimum size, we set the maximum size to match.
2789  // This is a bit of a hack to prevent VSTs GUI windows from resizing
2790  // there's no real reason to allow it. But, there should be a better
2791  // way of handling it.
2792  wxWindow *w = (wxWindow *) evt.GetEventObject();
2793  wxSize sz = w->GetMinSize();
2794 
2795  if (sz != wxDefaultSize)
2796  {
2797  w->SetMaxSize(sz);
2798  }
2799 }
2800 
2802 {
2803  // Turn the power on...some effects need this when the editor is open
2804  PowerOn();
2805 
2806  auto control = Destroy_ptr<VSTControl>{ safenew VSTControl };
2807  if (!control)
2808  {
2809  return;
2810  }
2811 
2812  if (!control->Create(mParent, this))
2813  {
2814  return;
2815  }
2816 
2817  {
2818  auto mainSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
2819 
2820  mainSizer->Add((mControl = control.release()), 0, wxALIGN_CENTER);
2821 
2822  mParent->SetMinSize(wxDefaultSize);
2823  mParent->SetSizer(mainSizer.release());
2824  }
2825 
2826  NeedEditIdle(true);
2827 
2828  mDialog->Bind(wxEVT_SIZE, OnSize);
2829 
2830 #ifdef __WXMAC__
2831 #ifdef __WX_EVTLOOP_BUSY_WAITING__
2832  wxEventLoop::SetBusyWaiting(true);
2833 #endif
2834 #endif
2835 
2836  return;
2837 }
2838 
2840 {
2841  wxASSERT(mParent); // To justify safenew
2842  wxScrolledWindow *const scroller = safenew wxScrolledWindow(mParent,
2843  wxID_ANY,
2844  wxDefaultPosition,
2845  wxDefaultSize,
2846  wxVSCROLL | wxTAB_TRAVERSAL);
2847 
2848  {
2849  auto mainSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
2850 
2851  // Try to give the window a sensible default/minimum size
2852  scroller->SetMinSize(wxSize(wxMax(600, mParent->GetSize().GetWidth() * 2 / 3),
2853  mParent->GetSize().GetHeight() / 2));
2854  scroller->SetScrollRate(0, 20);
2855 
2856  // This fools NVDA into not saying "Panel" when the dialog gets focus
2857  scroller->SetName(wxT("\a"));
2858  scroller->SetLabel(wxT("\a"));
2859 
2860  mainSizer->Add(scroller, 1, wxEXPAND | wxALL, 5);
2861  mParent->SetSizer(mainSizer.release());
2862  }
2863 
2864  mNames.reinit(static_cast<size_t>(mAEffect->numParams));
2865  mSliders.reinit(static_cast<size_t>(mAEffect->numParams));
2866  mDisplays.reinit(static_cast<size_t>(mAEffect->numParams));
2867  mLabels.reinit(static_cast<size_t>(mAEffect->numParams));
2868 
2869  {
2870  auto paramSizer = std::make_unique<wxStaticBoxSizer>(wxVERTICAL, scroller, _("Effect Settings"));
2871 
2872  {
2873  auto gridSizer = std::make_unique<wxFlexGridSizer>(4, 0, 0);
2874  gridSizer->AddGrowableCol(1);
2875 
2876  // Add the duration control for generators
2877  if (GetType() == EffectTypeGenerate)
2878  {
2879  wxControl *item = safenew wxStaticText(scroller, 0, _("Duration:"));
2880  gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
2881  mDuration = safenew
2882  NumericTextCtrl(scroller, ID_Duration,
2885  mHost->GetDuration(),
2886  mSampleRate,
2888  .AutoPos(true));
2889  mDuration->SetName( XO("Duration") );
2890  gridSizer->Add(mDuration, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2891  gridSizer->Add(1, 1, 0);
2892  gridSizer->Add(1, 1, 0);
2893  }
2894 
2895  // Find the longest parameter name.
2896  int namew = 0;
2897  int w;
2898  int h;
2899  for (int i = 0; i < mAEffect->numParams; i++)
2900  {
2901  wxString text = GetString(effGetParamName, i);
2902 
2903  if (text.Right(1) != wxT(':'))
2904  {
2905  text += wxT(':');
2906  }
2907 
2908  scroller->GetTextExtent(text, &w, &h);
2909  if (w > namew)
2910  {
2911  namew = w;
2912  }
2913  }
2914 
2915  scroller->GetTextExtent(wxT("HHHHHHHH"), &w, &h);
2916 
2917  for (int i = 0; i < mAEffect->numParams; i++)
2918  {
2919  mNames[i] = safenew wxStaticText(scroller,
2920  wxID_ANY,
2921  wxEmptyString,
2922  wxDefaultPosition,
2923  wxSize(namew, -1),
2924  wxALIGN_RIGHT | wxST_NO_AUTORESIZE);
2925  gridSizer->Add(mNames[i], 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
2926 
2927  mSliders[i] = safenew wxSliderWrapper(scroller,
2928  ID_Sliders + i,
2929  0,
2930  0,
2931  1000,
2932  wxDefaultPosition,
2933  wxSize(200, -1));
2934  gridSizer->Add(mSliders[i], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5);
2935 #if wxUSE_ACCESSIBILITY
2936  // so that name can be set on a standard control
2937  mSliders[i]->SetAccessible(safenew WindowAccessible(mSliders[i]));
2938 #endif
2939 
2940  mDisplays[i] = safenew wxStaticText(scroller,
2941  wxID_ANY,
2942  wxEmptyString,
2943  wxDefaultPosition,
2944  wxSize(w, -1),
2945  wxALIGN_RIGHT | wxST_NO_AUTORESIZE);
2946  gridSizer->Add(mDisplays[i], 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
2947 
2948  mLabels[i] = safenew wxStaticText(scroller,
2949  wxID_ANY,
2950  wxEmptyString,
2951  wxDefaultPosition,
2952  wxSize(w, -1),
2953  wxALIGN_LEFT | wxST_NO_AUTORESIZE);
2954  gridSizer->Add(mLabels[i], 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 5);
2955  }
2956 
2957  paramSizer->Add(gridSizer.release(), 1, wxEXPAND | wxALL, 5);
2958  }
2959  scroller->SetSizer(paramSizer.release());
2960  }
2961 
2963 
2964  mSliders[0]->SetFocus();
2965 }
2966 
2968 {
2969  if (!mNames)
2970  {
2971  return;
2972  }
2973 
2974  for (int i = 0; i < mAEffect->numParams; i++)
2975  {
2976  wxString text = GetString(effGetParamName, i);
2977 
2978  text = text.Trim(true).Trim(false);
2979 
2980  wxString name = text;
2981 
2982  if (text.Right(1) != wxT(':'))
2983  {
2984  text += wxT(':');
2985  }
2986  mNames[i]->SetLabel(text);
2987 
2988  // For some parameters types like on/off, setting the slider value has
2989  // a side effect that causes it to only move when the parameter changes
2990  // from off to on. However, this prevents changing the value using the
2991  // keyboard, so we skip the active slider if any.
2992  if (i != skip)
2993  {
2994  mSliders[i]->SetValue(callGetParameter(i) * 1000);
2995  }
2996  name = text;
2997 
2998  text = GetString(effGetParamDisplay, i);
2999  if (text.empty())
3000  {
3001  text.Printf(wxT("%.5g"),callGetParameter(i));
3002  }
3003  mDisplays[i]->SetLabel(wxString::Format(wxT("%8s"), text));
3004  name += wxT(' ') + text;
3005 
3006  text = GetString(effGetParamDisplay, i);
3007  if (!text.empty())
3008  {
3009  text.Printf(wxT("%-8s"), GetString(effGetParamLabel, i));
3010  mLabels[i]->SetLabel(wxString::Format(wxT("%8s"), text));
3011  name += wxT(' ') + text;
3012  }
3013 
3014  mSliders[i]->SetName(name);
3015  }
3016 }
3017 
3018 void VSTEffect::OnSizeWindow(wxCommandEvent & evt)
3019 {
3020  if (!mControl)
3021  {
3022  return;
3023  }
3024 
3025  mControl->SetMinSize(wxSize(evt.GetInt(), (int) evt.GetExtraLong()));
3026  mControl->SetSize(wxSize(evt.GetInt(), (int) evt.GetExtraLong()));
3027 
3028  // DO NOT CHANGE THE ORDER OF THESE
3029  //
3030  // Guitar Rig (and possibly others) Cocoa VSTs can resize too large
3031  // if the bounds are unlimited.
3032  mDialog->SetMinSize(wxDefaultSize);
3033  mDialog->SetMaxSize(wxDefaultSize);
3034  mDialog->Layout();
3035  mDialog->SetMinSize(mDialog->GetBestSize());
3036  mDialog->SetMaxSize(mDialog->GetBestSize());
3037  mDialog->Fit();
3038 }
3039 
3040 void VSTEffect::OnSlider(wxCommandEvent & evt)
3041 {
3042  wxSlider *s = (wxSlider *) evt.GetEventObject();
3043  int i = s->GetId() - ID_Sliders;
3044 
3045  callSetParameter(i, s->GetValue() / 1000.0);
3046 
3047  RefreshParameters(i);
3048 }
3049 
3050 bool VSTEffect::LoadFXB(const wxFileName & fn)
3051 {
3052  bool ret = false;
3053 
3054  // Try to open the file...will be closed automatically when method returns
3055  wxFFile f(fn.GetFullPath(), wxT("rb"));
3056  if (!f.IsOpened())
3057  {
3058  return false;
3059  }
3060 
3061  // Allocate memory for the contents
3062  ArrayOf<unsigned char> data{ size_t(f.Length()) };
3063  if (!data)
3064  {
3066  XO("Unable to allocate memory when loading presets file."),
3067  XO("Error Loading VST Presets"),
3068  wxOK | wxCENTRE,
3069  mParent);
3070  return false;
3071  }
3072  unsigned char *bptr = data.get();
3073 
3074  do
3075  {
3076  // Read in the whole file
3077  ssize_t len = f.Read((void *) bptr, f.Length());
3078  if (f.Error())
3079  {
3081  XO("Unable to read presets file."),
3082  XO("Error Loading VST Presets"),
3083  wxOK | wxCENTRE,
3084  mParent);
3085  break;
3086  }
3087 
3088  // Most references to the data are via an "int" array
3089  int32_t *iptr = (int32_t *) bptr;
3090 
3091  // Verify that we have at least enough for the header
3092  if (len < 156)
3093  {
3094  break;
3095  }
3096 
3097  // Verify that we probably have an FX file
3098  if (wxINT32_SWAP_ON_LE(iptr[0]) != CCONST('C', 'c', 'n', 'K'))
3099  {
3100  break;
3101  }
3102 
3103  // Ignore the size...sometimes it's there, other times it's zero
3104 
3105  // Get the version and verify
3106  int version = wxINT32_SWAP_ON_LE(iptr[3]);
3107  if (version != 1 && version != 2)
3108  {
3109  break;
3110  }
3111 
3112  VstPatchChunkInfo info =
3113  {
3114  1,
3115  wxINT32_SWAP_ON_LE(iptr[4]),
3116  wxINT32_SWAP_ON_LE(iptr[5]),
3117  wxINT32_SWAP_ON_LE(iptr[6]),
3118  ""
3119  };
3120 
3121  // Ensure this program looks to belong to the current plugin
3122  if ((info.pluginUniqueID != mAEffect->uniqueID) &&
3123  (info.pluginVersion != mAEffect->version) &&
3124  (info.numElements != mAEffect->numPrograms))
3125  {
3126  break;
3127  }
3128 
3129  // Get the number of programs
3130  int numProgs = info.numElements;
3131 
3132  // Get the current program index
3133  int curProg = 0;
3134  if (version >= 2)
3135  {
3136  curProg = wxINT32_SWAP_ON_LE(iptr[7]);
3137  if (curProg < 0 || curProg >= numProgs)
3138  {
3139  break;
3140  }
3141  }
3142 
3143  // Is it a bank of programs?
3144  if (wxINT32_SWAP_ON_LE(iptr[2]) == CCONST('F', 'x', 'B', 'k'))
3145  {
3146  // Drop the header
3147  bptr += 156;
3148  len -= 156;
3149 
3150  unsigned char *tempPtr = bptr;
3151  ssize_t tempLen = len;
3152 
3153  // Validate all of the programs
3154  for (int i = 0; i < numProgs; i++)
3155  {
3156  if (!LoadFXProgram(&tempPtr, tempLen, i, true))
3157  {
3158  break;
3159  }
3160  }
3161 
3162  // Ask the effect if this is an acceptable bank
3163  if (callDispatcher(effBeginLoadBank, 0, 0, &info, 0.0) == -1)
3164  {
3165  return false;
3166  }
3167 
3168  // Start loading the individual programs
3169  for (int i = 0; i < numProgs; i++)
3170  {
3171  ret = LoadFXProgram(&bptr, len, i, false);
3172  }
3173  }
3174  // Or maybe a bank chunk?
3175  else if (wxINT32_SWAP_ON_LE(iptr[2]) == CCONST('F', 'B', 'C', 'h'))
3176  {
3177  // Can't load programs chunks if the plugin doesn't support it
3179  {
3180  break;
3181  }
3182 
3183  // Verify that we have enough to grab the chunk size
3184  if (len < 160)
3185  {
3186  break;
3187  }
3188 
3189  // Get the chunk size
3190  int size = wxINT32_SWAP_ON_LE(iptr[39]);
3191 
3192  // We finally know the full length of the program
3193  int proglen = 160 + size;
3194 
3195  // Verify that we have enough for the entire program
3196  if (len < proglen)
3197  {
3198  break;
3199  }
3200 
3201  // Set the entire bank in one shot
3202  callSetChunk(false, size, &iptr[40], &info);
3203 
3204  // Success
3205  ret = true;
3206  }
3207  // Unrecognizable type
3208  else
3209  {
3210  break;
3211  }
3212 
3213  // Set the active program
3214  if (ret && version >= 2)
3215  {
3216  callSetProgram(curProg);
3217  }
3218  } while (false);
3219 
3220  return ret;
3221 }
3222 
3223 bool VSTEffect::LoadFXP(const wxFileName & fn)
3224 {
3225  bool ret = false;
3226 
3227  // Try to open the file...will be closed automatically when method returns
3228  wxFFile f(fn.GetFullPath(), wxT("rb"));
3229  if (!f.IsOpened())
3230  {
3231  return false;
3232  }
3233 
3234  // Allocate memory for the contents
3235  ArrayOf<unsigned char> data{ size_t(f.Length()) };
3236  if (!data)
3237  {
3239  XO("Unable to allocate memory when loading presets file."),
3240  XO("Error Loading VST Presets"),
3241  wxOK | wxCENTRE,
3242  mParent);
3243  return false;
3244  }
3245  unsigned char *bptr = data.get();
3246 
3247  do
3248  {
3249  // Read in the whole file
3250  ssize_t len = f.Read((void *) bptr, f.Length());
3251  if (f.Error())
3252  {
3254  XO("Unable to read presets file."),
3255  XO("Error Loading VST Presets"),
3256  wxOK | wxCENTRE,
3257  mParent);
3258  break;
3259  }
3260 
3261  // Get (or default) currently selected program
3262  int i = 0; //mProgram->GetCurrentSelection();
3263  if (i < 0)
3264  {
3265  i = 0; // default to first program
3266  }
3267 
3268  // Go verify and set the program
3269  ret = LoadFXProgram(&bptr, len, i, false);
3270  } while (false);
3271 
3272  return ret;
3273 }
3274 
3275 bool VSTEffect::LoadFXProgram(unsigned char **bptr, ssize_t & len, int index, bool dryrun)
3276 {
3277  // Most references to the data are via an "int" array
3278  int32_t *iptr = (int32_t *) *bptr;
3279 
3280  // Verify that we have at least enough for a program without parameters
3281  if (len < 28)
3282  {
3283  return false;
3284  }
3285 
3286  // Verify that we probably have an FX file
3287  if (wxINT32_SWAP_ON_LE(iptr[0]) != CCONST('C', 'c', 'n', 'K'))
3288  {
3289  return false;
3290  }
3291 
3292  // Ignore the size...sometimes it's there, other times it's zero
3293 
3294  // Get the version and verify
3295 #if defined(IS_THIS_AN_FXP_ARTIFICAL_LIMITATION)
3296  int version = wxINT32_SWAP_ON_LE(iptr[3]);
3297  if (version != 1)
3298  {
3299  return false;
3300  }
3301 #endif
3302 
3303  VstPatchChunkInfo info =
3304  {
3305  1,
3306  wxINT32_SWAP_ON_LE(iptr[4]),
3307  wxINT32_SWAP_ON_LE(iptr[5]),
3308  wxINT32_SWAP_ON_LE(iptr[6]),
3309  ""
3310  };
3311 
3312  // Ensure this program looks to belong to the current plugin
3313  if ((info.pluginUniqueID != mAEffect->uniqueID) &&
3314  (info.pluginVersion != mAEffect->version) &&
3315  (info.numElements != mAEffect->numParams))
3316  {
3317  return false;
3318  }
3319 
3320  // Get the number of parameters
3321  int numParams = info.numElements;
3322 
3323  // At this point, we have to have enough to include the program name as well
3324  if (len < 56)
3325  {
3326  return false;
3327  }
3328 
3329  // Get the program name
3330  wxString progName(wxString::From8BitData((char *)&iptr[7]));
3331 
3332  // Might be a regular program
3333  if (wxINT32_SWAP_ON_LE(iptr[2]) == CCONST('F', 'x', 'C', 'k'))
3334  {
3335  // We finally know the full length of the program
3336  int proglen = 56 + (numParams * sizeof(float));
3337 
3338  // Verify that we have enough for all of the parameter values
3339  if (len < proglen)
3340  {
3341  return false;
3342  }
3343 
3344  // Validate all of the parameter values
3345  for (int i = 0; i < numParams; i++)
3346  {
3347  uint32_t ival = wxUINT32_SWAP_ON_LE(iptr[14 + i]);
3348  float val = reinterpretAsFloat(ival);
3349  if (val < 0.0 || val > 1.0)
3350  {
3351  return false;
3352  }
3353  }
3354 
3355  // They look okay...time to start changing things
3356  if (!dryrun)
3357  {
3358  // Ask the effect if this is an acceptable program
3359  if (callDispatcher(effBeginLoadProgram, 0, 0, &info, 0.0) == -1)
3360  {
3361  return false;
3362  }
3363 
3364  // Load all of the parameters
3365  callDispatcher(effBeginSetProgram, 0, 0, NULL, 0.0);
3366  for (int i = 0; i < numParams; i++)
3367  {
3368  wxUint32 val = wxUINT32_SWAP_ON_LE(iptr[14 + i]);
3370  }
3371  callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
3372  }
3373 
3374  // Update in case we're loading an "FxBk" format bank file
3375  *bptr += proglen;
3376  len -= proglen;
3377  }
3378  // Maybe we have a program chunk
3379  else if (wxINT32_SWAP_ON_LE(iptr[2]) == CCONST('F', 'P', 'C', 'h'))
3380  {
3381  // Can't load programs chunks if the plugin doesn't support it
3383  {
3384  return false;
3385  }
3386 
3387  // Verify that we have enough to grab the chunk size
3388  if (len < 60)
3389  {
3390  return false;
3391  }
3392 
3393  // Get the chunk size
3394  int size = wxINT32_SWAP_ON_LE(iptr[14]);
3395 
3396  // We finally know the full length of the program
3397  int proglen = 60 + size;
3398 
3399  // Verify that we have enough for the entire program
3400  if (len < proglen)
3401  {
3402  return false;
3403  }
3404 
3405  // Set the entire program in one shot
3406  if (!dryrun)
3407  {
3408  callSetChunk(true, size, &iptr[15], &info);
3409  }
3410 
3411  // Update in case we're loading an "FxBk" format bank file
3412  *bptr += proglen;
3413  len -= proglen;
3414  }
3415  else
3416  {
3417  // Unknown type
3418  return false;
3419  }
3420 
3421  if (!dryrun)
3422  {
3423  SetString(effSetProgramName, wxString(progName), index);
3424  }
3425 
3426  return true;
3427 }
3428 
3429 bool VSTEffect::LoadXML(const wxFileName & fn)
3430 {
3431  mInChunk = false;
3432  mInSet = false;
3433 
3434  // default to read as XML file
3435  // Load the program
3436  XMLFileReader reader;
3437  bool ok = reader.Parse(this, fn.GetFullPath());
3438 
3439  // Something went wrong with the file, clean up
3440  if (mInSet)
3441  {
3442  callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
3443 
3444  mInSet = false;
3445  }
3446 
3447  if (!ok)
3448  {
3449  // Inform user of load failure
3451  reader.GetErrorStr(),
3452  XO("Error Loading VST Presets"),
3453  wxOK | wxCENTRE,
3454  mParent);
3455  return false;
3456  }
3457 
3458  return true;
3459 }
3460 
3461 void VSTEffect::SaveFXB(const wxFileName & fn)
3462 {
3463  // Create/Open the file
3464  const wxString fullPath{fn.GetFullPath()};
3465  wxFFile f(fullPath, wxT("wb"));
3466  if (!f.IsOpened())
3467  {
3469  XO("Could not open file: \"%s\"").Format( fullPath ),
3470  XO("Error Saving VST Presets"),
3471  wxOK | wxCENTRE,
3472  mParent);
3473  return;
3474  }
3475 
3476  wxMemoryBuffer buf;
3477  wxInt32 subType;
3478  void *chunkPtr = nullptr;
3479  int chunkSize = 0;
3480  int dataSize = 148;
3481  wxInt32 tab[8];
3482  int curProg = 0 ; //mProgram->GetCurrentSelection();
3483 
3485  {
3486  subType = CCONST('F', 'B', 'C', 'h');
3487 
3488  chunkSize = callDispatcher(effGetChunk, 0, 0, &chunkPtr, 0.0);
3489  dataSize += 4 + chunkSize;
3490  }
3491  else
3492  {
3493  subType = CCONST('F', 'x', 'B', 'k');
3494 
3495  for (int i = 0; i < mAEffect->numPrograms; i++)
3496  {
3497  SaveFXProgram(buf, i);
3498  }
3499 
3500  dataSize += buf.GetDataLen();
3501  }
3502 
3503  tab[0] = wxINT32_SWAP_ON_LE(CCONST('C', 'c', 'n', 'K'));
3504  tab[1] = wxINT32_SWAP_ON_LE(dataSize);
3505  tab[2] = wxINT32_SWAP_ON_LE(subType);
3506  tab[3] = wxINT32_SWAP_ON_LE(curProg >= 0 ? 2 : 1);
3507  tab[4] = wxINT32_SWAP_ON_LE(mAEffect->uniqueID);
3508  tab[5] = wxINT32_SWAP_ON_LE(mAEffect->version);
3509  tab[6] = wxINT32_SWAP_ON_LE(mAEffect->numPrograms);
3510  tab[7] = wxINT32_SWAP_ON_LE(curProg >= 0 ? curProg : 0);
3511 
3512  f.Write(tab, sizeof(tab));
3513  if (!f.Error())
3514  {
3515  char padding[124];
3516  memset(padding, 0, sizeof(padding));
3517  f.Write(padding, sizeof(padding));
3518 
3519  if (!f.Error())
3520  {
3522  {
3523  wxInt32 size = wxINT32_SWAP_ON_LE(chunkSize);
3524  f.Write(&size, sizeof(size));
3525  f.Write(chunkPtr, chunkSize);
3526  }
3527  else
3528  {
3529  f.Write(buf.GetData(), buf.GetDataLen());
3530  }
3531  }
3532  }
3533 
3534  if (f.Error())
3535  {
3537  XO("Error writing to file: \"%s\"").Format( fullPath ),
3538  XO("Error Saving VST Presets"),
3539  wxOK | wxCENTRE,
3540  mParent);
3541  }
3542 
3543  f.Close();
3544 
3545  return;
3546 }
3547 
3548 void VSTEffect::SaveFXP(const wxFileName & fn)
3549 {
3550  // Create/Open the file
3551  const wxString fullPath{ fn.GetFullPath() };
3552  wxFFile f(fullPath, wxT("wb"));
3553  if (!f.IsOpened())
3554  {
3556  XO("Could not open file: \"%s\"").Format( fullPath ),
3557  XO("Error Saving VST Presets"),
3558  wxOK | wxCENTRE,
3559  mParent);
3560  return;
3561  }
3562 
3563  wxMemoryBuffer buf;
3564 
3565  int ndx = callDispatcher(effGetProgram, 0, 0, NULL, 0.0);
3566  SaveFXProgram(buf, ndx);
3567 
3568  f.Write(buf.GetData(), buf.GetDataLen());
3569  if (f.Error())
3570  {
3572  XO("Error writing to file: \"%s\"").Format( fullPath ),
3573  XO("Error Saving VST Presets"),
3574  wxOK | wxCENTRE,
3575  mParent);
3576  }
3577 
3578  f.Close();
3579 
3580  return;
3581 }
3582 
3583 void VSTEffect::SaveFXProgram(wxMemoryBuffer & buf, int index)
3584 {
3585  wxInt32 subType;
3586  void *chunkPtr;
3587  int chunkSize;
3588  int dataSize = 48;
3589  char progName[28];
3590  wxInt32 tab[7];
3591 
3592  callDispatcher(effGetProgramNameIndexed, index, 0, &progName, 0.0);
3593  progName[27] = '\0';
3594  chunkSize = strlen(progName);
3595  memset(&progName[chunkSize], 0, sizeof(progName) - chunkSize);
3596 
3598  {
3599  subType = CCONST('F', 'P', 'C', 'h');
3600 
3601  chunkSize = callDispatcher(effGetChunk, 1, 0, &chunkPtr, 0.0);
3602  dataSize += 4 + chunkSize;
3603  }
3604  else
3605  {
3606  subType = CCONST('F', 'x', 'C', 'k');
3607 
3608  dataSize += (mAEffect->numParams << 2);
3609  }
3610 
3611  tab[0] = wxINT32_SWAP_ON_LE(CCONST('C', 'c', 'n', 'K'));
3612  tab[1] = wxINT32_SWAP_ON_LE(dataSize);
3613  tab[2] = wxINT32_SWAP_ON_LE(subType);
3614  tab[3] = wxINT32_SWAP_ON_LE(1);
3615  tab[4] = wxINT32_SWAP_ON_LE(mAEffect->uniqueID);
3616  tab[5] = wxINT32_SWAP_ON_LE(mAEffect->version);
3617  tab[6] = wxINT32_SWAP_ON_LE(mAEffect->numParams);
3618 
3619  buf.AppendData(tab, sizeof(tab));
3620  buf.AppendData(progName, sizeof(progName));
3621 
3623  {
3624  wxInt32 size = wxINT32_SWAP_ON_LE(chunkSize);
3625  buf.AppendData(&size, sizeof(size));
3626  buf.AppendData(chunkPtr, chunkSize);
3627  }
3628  else
3629  {
3630  for (int i = 0; i < mAEffect->numParams; i++)
3631  {
3632  float val = callGetParameter(i);
3633  wxUint32 ival = wxUINT32_SWAP_ON_LE(reinterpretAsUint32(val));
3634  buf.AppendData(&ival, sizeof(ival));
3635  }
3636  }
3637 
3638  return;
3639 }
3640 
3641 // Throws exceptions rather than giving error return.
3642 void VSTEffect::SaveXML(const wxFileName & fn)
3643 // may throw
3644 {
3645  XMLFileWriter xmlFile{ fn.GetFullPath(), XO("Error Saving Effect Presets") };
3646 
3647  xmlFile.StartTag(wxT("vstprogrampersistence"));
3648  xmlFile.WriteAttr(wxT("version"), wxT("2"));
3649 
3650  xmlFile.StartTag(wxT("effect"));
3651  // Use internal name only in persistent information
3652  xmlFile.WriteAttr(wxT("name"), GetSymbol().Internal());
3653  xmlFile.WriteAttr(wxT("uniqueID"), mAEffect->uniqueID);
3654  xmlFile.WriteAttr(wxT("version"), mAEffect->version);
3655  xmlFile.WriteAttr(wxT("numParams"), mAEffect->numParams);
3656 
3657  xmlFile.StartTag(wxT("program"));
3658  xmlFile.WriteAttr(wxT("name"), wxEmptyString); //mProgram->GetValue());
3659 
3660  int clen = 0;
3662  {
3663  void *chunk = NULL;
3664 
3665  clen = (int) callDispatcher(effGetChunk, 1, 0, &chunk, 0.0);
3666  if (clen != 0)
3667  {
3668  xmlFile.StartTag(wxT("chunk"));
3669  xmlFile.WriteSubTree(VSTEffect::b64encode(chunk, clen) + wxT('\n'));
3670  xmlFile.EndTag(wxT("chunk"));
3671  }
3672  }
3673 
3674  if (clen == 0)
3675  {
3676  for (int i = 0; i < mAEffect->numParams; i++)
3677  {
3678  xmlFile.StartTag(wxT("param"));
3679 
3680  xmlFile.WriteAttr(wxT("index"), i);
3681  xmlFile.WriteAttr(wxT("name"),
3683  xmlFile.WriteAttr(wxT("value"),
3684  wxString::Format(wxT("%f"),
3685  callGetParameter(i)));
3686 
3687  xmlFile.EndTag(wxT("param"));
3688  }
3689  }
3690 
3691  xmlFile.EndTag(wxT("program"));
3692 
3693  xmlFile.EndTag(wxT("effect"));
3694 
3695  xmlFile.EndTag(wxT("vstprogrampersistence"));
3696 
3697  xmlFile.Commit();
3698 }
3699 
3700 bool VSTEffect::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
3701 {
3702  if (wxStrcmp(tag, wxT("vstprogrampersistence")) == 0)
3703  {
3704  while (*attrs)
3705  {
3706  const wxChar *attr = *attrs++;
3707  const wxChar *value = *attrs++;
3708 
3709  if (!value)
3710  {
3711  break;
3712  }
3713 
3714  const wxString strValue = value;
3715 
3716  if (wxStrcmp(attr, wxT("version")) == 0)
3717  {
3718  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&mXMLVersion))
3719  {
3720  return false;
3721  }
3722 
3723  if (mXMLVersion < 1 || mXMLVersion > 2)
3724  {
3725  return false;
3726  }
3727  }
3728  else
3729  {
3730  return false;
3731  }
3732  }
3733 
3734  return true;
3735  }
3736 
3737  if (wxStrcmp(tag, wxT("effect")) == 0)
3738  {
3739  memset(&mXMLInfo, 0, sizeof(mXMLInfo));
3740  mXMLInfo.version = 1;
3744 
3745  while (*attrs)
3746  {
3747  const wxChar *attr = *attrs++;
3748  const wxChar *value = *attrs++;
3749 
3750  if (!value)
3751  {
3752  break;
3753  }
3754 
3755  const wxString strValue = value;
3756 
3757  if (wxStrcmp(attr, wxT("name")) == 0)
3758  {
3759  if (!XMLValueChecker::IsGoodString(strValue))
3760  {
3761  return false;
3762  }
3763 
3764  if (value != GetSymbol().Internal())
3765  {
3766  auto msg = XO("This parameter file was saved from %s. Continue?")
3767  .Format( value );
3768  int result = AudacityMessageBox(
3769  msg,
3770  XO("Confirm"),
3771  wxYES_NO,
3772  mParent );
3773  if (result == wxNO)
3774  {
3775  return false;
3776  }
3777  }
3778  }
3779  else if (wxStrcmp(attr, wxT("version")) == 0)
3780  {
3781  long version;
3782  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&version))
3783  {
3784  return false;
3785  }
3786 
3787  mXMLInfo.pluginVersion = (int) version;
3788  }
3789  else if (mXMLVersion > 1 && wxStrcmp(attr, wxT("uniqueID")) == 0)
3790  {
3791  long uniqueID;
3792  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&uniqueID))
3793  {
3794  return false;
3795  }
3796 
3797  mXMLInfo.pluginUniqueID = (int) uniqueID;
3798  }
3799  else if (mXMLVersion > 1 && wxStrcmp(attr, wxT("numParams")) == 0)
3800  {
3801  long numParams;
3802  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&numParams))
3803  {
3804  return false;
3805  }
3806 
3807  mXMLInfo.numElements = (int) numParams;
3808  }
3809  else
3810  {
3811  return false;
3812  }
3813  }
3814 
3815  return true;
3816  }
3817 
3818  if (wxStrcmp(tag, wxT("program")) == 0)
3819  {
3820  while (*attrs)
3821  {
3822  const wxChar *attr = *attrs++;
3823  const wxChar *value = *attrs++;
3824 
3825  if (!value)
3826  {
3827  break;
3828  }
3829 
3830  const wxString strValue = value;
3831 
3832  if (wxStrcmp(attr, wxT("name")) == 0)
3833  {
3834  if (!XMLValueChecker::IsGoodString(strValue))
3835  {
3836  return false;
3837  }
3838 
3839  if (strValue.length() > 24)
3840  {
3841  return false;
3842  }
3843 
3844  int ndx = 0; //mProgram->GetCurrentSelection();
3845  if (ndx == wxNOT_FOUND)
3846  {
3847  ndx = 0;
3848  }
3849 
3850  SetString(effSetProgramName, strValue, ndx);
3851  }
3852  else
3853  {
3854  return false;
3855  }
3856  }
3857 
3858  mInChunk = false;
3859 
3860  if (callDispatcher(effBeginLoadProgram, 0, 0, &mXMLInfo, 0.0) == -1)
3861  {
3862  return false;
3863  }
3864 
3865  callDispatcher(effBeginSetProgram, 0, 0, NULL, 0.0);
3866 
3867  mInSet = true;
3868 
3869  return true;
3870  }
3871 
3872  if (wxStrcmp(tag, wxT("param")) == 0)
3873  {
3874  long ndx = -1;
3875  double val = -1.0;
3876  while (*attrs)
3877  {
3878  const wxChar *attr = *attrs++;
3879  const wxChar *value = *attrs++;
3880 
3881  if (!value)
3882  {
3883  break;
3884  }
3885 
3886  const wxString strValue = value;
3887 
3888  if (wxStrcmp(attr, wxT("index")) == 0)
3889  {
3890  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&ndx))
3891  {
3892  return false;
3893  }
3894 
3895  if (ndx < 0 || ndx >= mAEffect->numParams)
3896  {
3897  // Could be a different version of the effect...probably should
3898  // tell the user
3899  return false;
3900  }
3901  }
3902  else if (wxStrcmp(attr, wxT("name")) == 0)
3903  {
3904  if (!XMLValueChecker::IsGoodString(strValue))
3905  {
3906  return false;
3907  }
3908  // Nothing to do with it for now
3909  }
3910  else if (wxStrcmp(attr, wxT("value")) == 0)
3911  {
3912  if (!XMLValueChecker::IsGoodInt(strValue) ||
3913  !Internat::CompatibleToDouble(strValue, &val))
3914  {
3915  return false;
3916  }
3917 
3918  if (val < 0.0 || val > 1.0)
3919  {
3920  return false;
3921  }
3922  }
3923  }
3924 
3925  if (ndx == -1 || val == -1.0)
3926  {
3927  return false;
3928  }
3929 
3930  callSetParameter(ndx, val);
3931 
3932  return true;
3933  }
3934 
3935  if (wxStrcmp(tag, wxT("chunk")) == 0)
3936  {
3937  mInChunk = true;
3938  return true;
3939  }
3940 
3941  return false;
3942 }
3943 
3944 void VSTEffect::HandleXMLEndTag(const wxChar *tag)
3945 {
3946  if (wxStrcmp(tag, wxT("chunk")) == 0)
3947  {
3948  if (mChunk.length())
3949  {
3950  ArrayOf<char> buf{ mChunk.length() / 4 * 3 };
3951 
3952  int len = VSTEffect::b64decode(mChunk, buf.get());
3953  if (len)
3954  {
3955  callSetChunk(true, len, buf.get(), &mXMLInfo);
3956  }
3957 
3958  mChunk.clear();
3959  }
3960  mInChunk = false;
3961  }
3962 
3963  if (wxStrcmp(tag, wxT("program")) == 0)
3964  {
3965  if (mInSet)
3966  {
3967  callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
3968 
3969  mInSet = false;
3970  }
3971  }
3972 }
3973 
3974 void VSTEffect::HandleXMLContent(const wxString & content)
3975 {
3976  if (mInChunk)
3977  {
3978  mChunk += wxString(content).Trim(true).Trim(false);
3979  }
3980 }
3981 
3983 {
3984  if (wxStrcmp(tag, wxT("vstprogrampersistence")) == 0)
3985  {
3986  return this;
3987  }
3988 
3989  if (wxStrcmp(tag, wxT("effect")) == 0)
3990  {
3991  return this;
3992  }
3993 
3994  if (wxStrcmp(tag, wxT("program")) == 0)
3995  {
3996  return this;
3997  }
3998 
3999  if (wxStrcmp(tag, wxT("param")) == 0)
4000  {
4001  return this;
4002  }
4003 
4004  if (wxStrcmp(tag, wxT("chunk")) == 0)
4005  {
4006  return this;
4007  }
4008 
4009  return NULL;
4010 }
4011 
4012 #endif // USE_VST
RTLD_DEEPBIND
#define RTLD_DEEPBIND
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
VSTEffect::GetAudioInCount
unsigned GetAudioInCount() override
Definition: VSTEffect.cpp:1335
VSTEffect::ProcessInitialize
bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap=NULL) override
Definition: VSTEffect.cpp:1394
VSTEffect::PowerOn
void PowerOn()
Definition: VSTEffect.cpp:2449
VSTSubProcess::IsLegacy
bool IsLegacy() override
Definition: VSTEffect.cpp:279
FilePath
wxString FilePath
Definition: Identifier.h:227
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
AEffect::dispatcher
intptr_t(* dispatcher)(AEffect *, int, int, intptr_t, void *, float)
Definition: aeffectx.h:264
audioMasterSizeWindow
const int audioMasterSizeWindow
Definition: aeffectx.h:49
VSTEffect::mInChunk
bool mInChunk
Definition: VSTEffect.h:387
VSTEffectsModule::GetVersion
wxString GetVersion() override
Definition: VSTEffect.cpp:337
CommandParameters
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the Shuttle cla...
Definition: EffectAutomationParameters.h:67
VSTEffect::mMasterIn
FloatBuffers mMasterIn
Definition: VSTEffect.h:368
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:38
VSTEffect::mDialog
wxDialog * mDialog
Definition: VSTEffect.h:372
CommandParameters::SetParameters
bool SetParameters(const wxString &parms)
Definition: EffectAutomationParameters.h:286
VSTEffect::mPath
PluginPath mPath
Definition: VSTEffect.h:288
TranslatableString::empty
bool empty() const
Definition: TranslatableString.h:72
valueRestorer
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
Definition: MemoryX.h:354
VSTEffect::mBlockSize
unsigned mBlockSize
Definition: VSTEffect.h:352
VstTimeInfo::flags
int flags
Definition: aeffectx.h:331
audioMasterEndEdit
const int audioMasterEndEdit
Definition: aeffectx.h:79
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1184
EffectTypeProcess
@ EffectTypeProcess
Definition: EffectInterface.h:59
wxSliderWrapper
wxSlider wxSliderWrapper
Definition: ShuttleGui.h:105
audioMasterGetTime
const int audioMasterGetTime
Definition: aeffectx.h:41
VSTEffect::mModule
ModuleHandle mModule
Definition: VSTEffect.h:307
VSTEffect::IsLegacy
bool IsLegacy() override
Definition: VSTEffect.cpp:1272
VSTEffect::callDispatcher
intptr_t callDispatcher(int opcode, int index, intptr_t value, void *ptr, float opt) override
Definition: VSTEffect.cpp:2567
VSTEffect::mUseLatency
bool mUseLatency
Definition: VSTEffect.h:349
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption=XO("Message"), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: AudacityMessageBox.h:20
audioMasterUpdateDisplay
const int audioMasterUpdateDisplay
Definition: aeffectx.h:77
VstTimeInfo::samplePos
double samplePos
Definition: aeffectx.h:309
BasicUI::ProgressResult::Success
@ Success
VSTEffect::SetBufferDelay
void SetBufferDelay(int samples)
Definition: VSTEffect.cpp:2526
effFlagsCanReplacing
const int effFlagsCanReplacing
Definition: aeffectx.h:87
effSetBlockSize
const int effSetBlockSize
Definition: aeffectx.h:103
VSTEffectsModule
Definition: VSTEffect.h:404
VSTEffectsModule::GetFileExtensions
const FileExtensions & GetFileExtensions() override
Definition: VSTEffect.cpp:373
VstPatchChunkInfo::numElements
int32_t numElements
Definition: aeffectx.h:358
Optional
Like a smart pointer, allows for object to not exist (nullptr)
Definition: MemoryX.h:144
kKeyInteractive
@ kKeyInteractive
Definition: VSTEffect.cpp:212
ID_Sliders
@ ID_Sliders
Definition: VSTEffect.cpp:922
kKeyAutomatable
@ kKeyAutomatable
Definition: VSTEffect.cpp:213
audioMasterWantMidi
const int audioMasterWantMidi
Definition: aeffectx.h:40
NumericTextCtrl::Options::AutoPos
Options & AutoPos(bool enable)
Definition: NumericTextCtrl.h:190
eIsGettingFromDialog
@ eIsGettingFromDialog
Definition: ShuttleGui.h:39
ComponentInterfaceSymbol::Translation
const wxString Translation() const
Definition: ComponentInterfaceSymbol.h:58
EffectHostInterface
EffectHostInterface is a decorator of a EffectUIClientInterface. It adds virtual (abstract) functions...
Definition: EffectInterface.h:121
fn
static const auto fn
Definition: WaveformView.cpp:1114
VSTEffect.h
VstTimeInfo::nanoSeconds
double nanoSeconds
Definition: aeffectx.h:313
VSTEffectsModule::Terminate
void Terminate() override
Definition: VSTEffect.cpp:358
VSTEffect::b64decode
static int b64decode(const wxString &in, void *out)
Definition: VSTEffect.cpp:2701
VSTEffect::GetVendor
VendorSymbol GetVendor() override
Definition: VSTEffect.cpp:1200
VSTEffect::mAutomatable
bool mAutomatable
Definition: VSTEffect.h:293
VSTEffect::SaveFXP
void SaveFXP(const wxFileName &fn)
Definition: VSTEffect.cpp:3548
VSTEffect::mMasterOut
FloatBuffers mMasterOut
Definition: VSTEffect.h:368
XMLValueChecker::IsGoodInt
static bool IsGoodInt(const wxString &strInt)
Check that the supplied string can be converted to a long (32bit) integer.
Definition: XMLTagHandler.cpp:160
VSTEffect::LoadUserPreset
bool LoadUserPreset(const RegistryPath &name) override
Definition: VSTEffect.cpp:1689
VSTEffectsModule::GetOptionalFamilySymbol
EffectFamilySymbol GetOptionalFamilySymbol() override
Definition: VSTEffect.cpp:364
CCONST
#define CCONST(a, b, c, d)
Definition: aeffectx.h:29
VSTEffect::mNumChannels
unsigned mNumChannels
Definition: VSTEffect.h:367
EVT_COMMAND
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:91
VSTEffect::HasOptions
bool HasOptions() override
Definition: VSTEffect.cpp:1975
VSTEffect::mName
wxString mName
Definition: VSTEffect.h:296
IMPLEMENT_DYNAMIC_CLASS
IMPLEMENT_DYNAMIC_CLASS(VSTSubEntry, wxModule)
VSTEffect::HandleXMLContent
void HandleXMLContent(const wxString &content) override
Definition: VSTEffect.cpp:3974
VSTEffect::mMidiIns
int mMidiIns
Definition: VSTEffect.h:291
VSTEffect::mUIHost
EffectUIHostInterface * mUIHost
Definition: VSTEffect.h:374
VSTEffect::UpdateDisplay
void UpdateDisplay()
Definition: VSTEffect.cpp:2499
effGetParamName
const int effGetParamName
Definition: aeffectx.h:101
VSTEffect::Unload
void Unload()
Definition: VSTEffect.cpp:2268
Effect
Base class for many of the effects in Audacity.
Definition: Effect.h:72
VSTEffect::mSampleRate
float mSampleRate
Definition: VSTEffect.h:294
EffectTypeGenerate
@ EffectTypeGenerate
Definition: EffectInterface.h:58
VSTEffect::mWantsEditIdle
bool mWantsEditIdle
Definition: VSTEffect.h:357
AEffect::numPrograms
int numPrograms
Definition: aeffectx.h:272
VSTEffect::PopulateUI
bool PopulateUI(ShuttleGui &S) override
Definition: VSTEffect.cpp:1754
VSTEffect::RefreshParameters
void RefreshParameters(int skip=-1)
Definition: VSTEffect.cpp:2967
RegistryPaths
std::vector< RegistryPath > RegistryPaths
Definition: Identifier.h:219
ShuttleGuiBase::TieCheckBox
wxCheckBox * TieCheckBox(const TranslatableString &Prompt, bool &Var)
Definition: ShuttleGui.cpp:1629
audioMasterGetSampleRate
const int audioMasterGetSampleRate
Definition: aeffectx.h:50
PluginPath
wxString PluginPath
type alias for identifying a Plugin supplied by a module, each module defining its own interpretation...
Definition: Identifier.h:214
VSTEffect::IsReady
bool IsReady() override
Definition: VSTEffect.cpp:1389
kKeySubIDs
@ kKeySubIDs
Definition: VSTEffect.cpp:204
Format
Abstract base class used in importing a file.
VstPatchChunkInfo::pluginVersion
int32_t pluginVersion
Definition: aeffectx.h:357
ID_Duration
@ ID_Duration
Definition: VSTEffect.cpp:921
VSTSubProcess::VSTSubProcess
VSTSubProcess()
Definition: VSTEffect.cpp:227
ArrayOf::reinit
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
VSTEffect::GetAutomationParameters
bool GetAutomationParameters(CommandParameters &parms) override
Definition: VSTEffect.cpp:1639
VSTEffectsModule::DiscoverPluginsAtPath
unsigned DiscoverPluginsAtPath(const PluginPath &path, TranslatableString &errMsg, const RegistrationCallback &callback) override
Definition: VSTEffect.cpp:502
VSTEffect::mGui
bool mGui
Definition: VSTEffect.h:376
VSTEffect::mVendor
wxString mVendor
Definition: VSTEffect.h:297
effBeginSetProgram
const int effBeginSetProgram
Definition: aeffectx.h:130
VSTEffect::LoadFXB
bool LoadFXB(const wxFileName &fn)
Definition: VSTEffect.cpp:3050
VSTEffect::LoadFXP
bool LoadFXP(const wxFileName &fn)
Definition: VSTEffect.cpp:3223
VSTEffect::OnSlider
void OnSlider(wxCommandEvent &evt)
Definition: VSTEffect.cpp:3040
NumericTextCtrl::SetName
void SetName(const TranslatableString &name)
Definition: NumericTextCtrl.cpp:1420
VSTSubProcess::SupportsRealtime
bool SupportsRealtime() override
Definition: VSTEffect.cpp:284
VSTSubProcess::GetFamily
EffectFamilySymbol GetFamily() override
Definition: VSTEffect.cpp:259
kVstLangEnglish
const int kVstLangEnglish
Definition: aeffectx.h:145
audioMasterCanDo
const int audioMasterCanDo
Definition: aeffectx.h:72
XO
#define XO(s)
Definition: Internat.h:31
VSTEffect::ShowOptions
void ShowOptions() override
Definition: VSTEffect.cpp:1980
DECLARE_MODULE_ENTRY
DECLARE_MODULE_ENTRY(AudacityModule)
Definition: VSTEffect.cpp:143
VSTEffect::GetChannelCount
unsigned GetChannelCount()
Definition: VSTEffect.cpp:1444
VstTimeInfo::timeSigDenominator
int timeSigDenominator
Definition: aeffectx.h:327
VSTEffectsModule::GetDescription
TranslatableString GetDescription() override
Definition: VSTEffect.cpp:343
EffectHostInterface::GetCurrentSettingsGroup
virtual RegistryPath GetCurrentSettingsGroup()=0
effSetSampleRate
const int effSetSampleRate
Definition: aeffectx.h:102
VSTSubProcess::GetVendor
VendorSymbol GetVendor() override
Definition: VSTEffect.cpp:244
audioMasterBeginEdit
const int audioMasterBeginEdit
Definition: aeffectx.h:78
VSTEffect::~VSTEffect
virtual ~VSTEffect()
Definition: VSTEffect.cpp:1176
VstPlugCategory
VstPlugCategory
Definition: aeffectx.h:364
VSTEffect::mWantsIdle
bool mWantsIdle
Definition: VSTEffect.h:356
VSTEffect::VSTEffect
VSTEffect(const PluginPath &path, VSTEffect *master=NULL)
Definition: VSTEffect.cpp:1128
VSTEffect::SupportsAutomation
bool SupportsAutomation() override
Definition: VSTEffect.cpp:1282
CommandParameters::GetParameters
bool GetParameters(wxString &parms)
Definition: EffectAutomationParameters.h:258
VSTEffect::ImportPresets
void ImportPresets() override
Definition: VSTEffect.cpp:1908
VSTEffect::SupportsRealtime
bool SupportsRealtime() override
Definition: VSTEffect.cpp:1277
audioMasterWillReplaceOrAccumulate
const int audioMasterWillReplaceOrAccumulate
Definition: aeffectx.h:56
VstTimeInfo::tempo
double tempo
Definition: aeffectx.h:317
VstPatchChunkInfo
Definition: aeffectx.h:354
VSTEffect::ValidateUI
bool ValidateUI() override
Definition: VSTEffect.cpp:1793
VSTEffectsModule::GetPath
PluginPath GetPath() override
Definition: VSTEffect.cpp:322
VstPatchChunkInfo::version
int32_t version
Definition: aeffectx.h:355
VSTSubProcess::mDescription
TranslatableString mDescription
Definition: VSTEffect.cpp:299
VSTEffect::SetHost
bool SetHost(EffectHostInterface *host) override
Definition: VSTEffect.cpp:1291
VSTCMDKEY
#define VSTCMDKEY
Definition: VSTEffect.h:31
VSTEffect::LoadFactoryDefaults
bool LoadFactoryDefaults() override
Definition: VSTEffect.cpp:1733
effSetChunk
const int effSetChunk
Definition: aeffectx.h:112
NumericTextCtrl
Definition: NumericTextCtrl.h:172
VSTEffect::RealtimeSuspend
bool RealtimeSuspend() override
Definition: VSTEffect.cpp:1511
kKeyName
@ kKeyName
Definition: VSTEffect.cpp:206
OnSize
static void OnSize(wxSizeEvent &evt)
Definition: VSTEffect.cpp:2783
VSTEffect::HandleXMLChild
XMLTagHandler * HandleXMLChild(const wxChar *tag) override
Definition: VSTEffect.cpp:3982
VSTEffectsModule::IsPluginValid
bool IsPluginValid(const PluginPath &path, bool bFast) override
Definition: VSTEffect.cpp:680
VSTEffectsModule::AutoRegisterPlugins
bool AutoRegisterPlugins(PluginManagerInterface &pm) override
Definition: VSTEffect.cpp:387
wxArrayStringEx
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Definition: wxArrayStringEx.h:18
VSTEffect::RealtimeAddProcessor
bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) override
Definition: VSTEffect.cpp:1462
VSTEffect::callSetParameter
void callSetParameter(int index, float value)
Definition: VSTEffect.cpp:2586
VSTSubProcess::mName
wxString mName
Definition: VSTEffect.cpp:296
VSTEffect::HandleXMLEndTag
void HandleXMLEndTag(const wxChar *tag) override
Definition: VSTEffect.cpp:3944
ComponentInterfaceSymbol
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Definition: ComponentInterfaceSymbol.h:27
VSTEffect::ShowInterface
bool ShowInterface(wxWindow &parent, const EffectDialogFactory &factory, bool forceModal=false) override
Definition: VSTEffect.cpp:1594
XMLValueChecker::IsGoodString
static bool IsGoodString(const wxString &str)
Definition: XMLTagHandler.cpp:41
kKeyPath
@ kKeyPath
Definition: VSTEffect.cpp:207
NumericTextCtrl::Options
Definition: NumericTextCtrl.h:178
AEffect::flags
int flags
Definition: aeffectx.h:280
VSTEffect::RealtimeFinalize
bool RealtimeFinalize() override
Definition: VSTEffect.cpp:1498
VSTEffect::ProcessFinalize
bool ProcessFinalize() override
Definition: VSTEffect.cpp:1420
VSTEffect::SetSampleRate
void SetSampleRate(double rate) override
Definition: VSTEffect.cpp:1366
VSTEffect::mNumSamples
size_t mNumSamples
Definition: VSTEffect.h:369
VSTEffect::PowerOff
void PowerOff()
Definition: VSTEffect.cpp:2467
XMLFileReader::Parse
bool Parse(XMLTagHandler *baseHandler, const FilePath &fname)
Definition: XMLFileReader.cpp:42
effGetChunk
const int effGetChunk
Definition: aeffectx.h:111
VSTEffect::GetDescription
TranslatableString GetDescription() override
Definition: VSTEffect.cpp:1224
effFlagsIsSynth
const int effFlagsIsSynth
Definition: aeffectx.h:89
VSTEffect::mHasPower
bool mHasPower
Definition: VSTEffect.h:355
AEffect::setParameter
void(* setParameter)(AEffect *, int, float)
Definition: aeffectx.h:268
VSTEffect::callSetChunk
void callSetChunk(bool isPgm, int len, void *buf)
Definition: VSTEffect.cpp:2608
effGetVstVersion
const int effGetVstVersion
Definition: aeffectx.h:128
VSTEffect::mSlaves
VSTEffectArray mSlaves
Definition: VSTEffect.h:366
ArraysOf::reinit
void reinit(Integral count)
Definition: MemoryX.h:109
SampleCount.h
DEFINE_LOCAL_EVENT_TYPE
DEFINE_LOCAL_EVENT_TYPE(EVT_SIZEWINDOW)
VSTEffect::mHost
EffectHostInterface * mHost
Definition: VSTEffect.h:286
AEffect::numInputs
int numInputs
Definition: aeffectx.h:276
VSTEffect::GetVersion
wxString GetVersion() override
Definition: VSTEffect.cpp:1205
VSTEffect::SetHostUI
void SetHostUI(EffectUIHostInterface *host) override
Definition: VSTEffect.cpp:1749
VSTEffect::LoadXML
bool LoadXML(const wxFileName &fn)
Definition: VSTEffect.cpp:3429
VSTEffect::LoadParameters
bool LoadParameters(const RegistryPath &group)
Definition: VSTEffect.cpp:2318
VSTEffectsModule::InstallPath
FilePath InstallPath() override
Definition: VSTEffect.cpp:379
VSTEffectTimer::~VSTEffectTimer
~VSTEffectTimer()
Definition: VSTEffect.cpp:901
VSTEffect::GetPath
PluginPath GetPath() override
Definition: VSTEffect.cpp:1190
XXO
#define XXO(s)
Definition: Internat.h:44
kVstTempoValid
const int kVstTempoValid
Definition: aeffectx.h:150
VSTEffect::GetMidiOutCount
int GetMidiOutCount() override
Definition: VSTEffect.cpp:1350
VstTimeInfo::timeSigNumerator
int timeSigNumerator
Definition: aeffectx.h:325
EffectHostInterface::GetDuration
virtual double GetDuration()=0
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1177
VSTEffect::ModuleHandle
std::unique_ptr< char, ModuleDeleter > ModuleHandle
Definition: VSTEffect.h:283
XMLFileReader::GetErrorStr
const TranslatableString & GetErrorStr() const
Definition: XMLFileReader.cpp:178
effIdle
const int effIdle
Definition: aeffectx.h:127
PluginManagerInterface
Definition: PluginInterface.h:55
VSTEffect::mMaster
VSTEffect * mMaster
Definition: VSTEffect.h:365
VSTEffectsModule::VSTEffectsModule
VSTEffectsModule()
Definition: VSTEffect.cpp:310
VSTSubProcess::mVersion
wxString mVersion
Definition: VSTEffect.cpp:298
factory
static RegisteredToolbarFactory factory
Definition: ControlToolBar.cpp:806
VSTSubProcess::GetVersion
wxString GetVersion() override
Definition: VSTEffect.cpp:249
VSTEffect::mInteractive
bool mInteractive
Definition: VSTEffect.h:300
VSTEffect::mInSet
bool mInSet
Definition: VSTEffect.h:386
reinterpretAsFloat
static float reinterpretAsFloat(uint32_t x)
Definition: VSTEffect.cpp:112
VSTEffect::callProcessReplacing
void callProcessReplacing(float **inputs, float **outputs, int sampleframes)
Definition: VSTEffect.cpp:2575
VSTSubProcess::IsDefault
bool IsDefault() override
Definition: VSTEffect.cpp:274
VSTEffect::ExportPresets
void ExportPresets() override
Definition: VSTEffect.cpp:1848
VSTEffect::HandleXMLTag
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override
Definition: VSTEffect.cpp:3700
VSTEffect::GetFamily
EffectFamilySymbol GetFamily() override
Definition: VSTEffect.cpp:1257
VSTEffect::IsInteractive
bool IsInteractive() override
Definition: VSTEffect.cpp:1262
audioMasterPinConnected
const int audioMasterPinConnected
Definition: aeffectx.h:38
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1167
VSTEffect::mXMLInfo
VstPatchChunkInfo mXMLInfo
Definition: VSTEffect.h:390
VSTEffect::NeedIdle
void NeedIdle()
Definition: VSTEffect.cpp:2421
VSTEffect::mDisplays
ArrayOf< wxStaticText * > mDisplays
Definition: VSTEffect.h:383
effFlagsHasEditor
const int effFlagsHasEditor
Definition: aeffectx.h:86
audioMasterIOChanged
const int audioMasterIOChanged
Definition: aeffectx.h:47
VSTEffect::GetBlockSize
size_t GetBlockSize() const override
Definition: VSTEffect.cpp:1361
VSTEffectTimer
Definition: VSTEffect.cpp:893
VSTEffect::mAudioIns
unsigned mAudioIns
Definition: VSTEffect.h:289
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1203
VSTEffect::IsGraphicalUI
bool IsGraphicalUI() override
Definition: VSTEffect.cpp:1788
audioMasterGetVendorVersion
const int audioMasterGetVendorVersion
Definition: aeffectx.h:69
kEffectMagic
const int kEffectMagic
Definition: aeffectx.h:144
kKeyEffectType
@ kKeyEffectType
Definition: VSTEffect.cpp:211
VSTEffect::callGetParameter
float callGetParameter(int index)
Definition: VSTEffect.cpp:2581
VSTEffectTimer::VSTEffectTimer
VSTEffectTimer(VSTEffect *effect)
Definition: VSTEffect.cpp:895
VSTEffect::SizeWindow
void SizeWindow(int w, int h)
Definition: VSTEffect.cpp:2485
VSTEffect::mVersion
int mVersion
Definition: VSTEffect.h:299
VSTEffect::mLabels
ArrayOf< wxStaticText * > mLabels
Definition: VSTEffect.h:384
VSTEffect::mProcessLevel
int mProcessLevel
Definition: VSTEffect.h:354
effGetVendorVersion
const int effGetVendorVersion
Definition: aeffectx.h:124
VSTControl
Definition: VSTControlGTK.h:25
effCanBeAutomated
const int effCanBeAutomated
Definition: aeffectx.h:115
VSTEffect::RealtimeInitialize
bool RealtimeInitialize() override
Definition: VSTEffect.cpp:1454
VSTEffect::SetChannelCount
void SetChannelCount(unsigned numChannels)
Definition: VSTEffect.cpp:1449
effGetVendorString
const int effGetVendorString
Definition: aeffectx.h:122
kVstNanosValid
const int kVstNanosValid
Definition: aeffectx.h:148
effSetProgram
const int effSetProgram
Definition: aeffectx.h:93
VSTEffect::mCurrentEffectID
static intptr_t mCurrentEffectID
Definition: VSTEffect.h:303
cset
static const wxChar cset[]
Definition: VSTEffect.cpp:2658
VSTEffect::BuildPlain
void BuildPlain()
Definition: VSTEffect.cpp:2839
name
const TranslatableString name
Definition: Distortion.cpp:98
VSTEffect::RealtimeProcess
size_t RealtimeProcess(int group, float **inbuf, float **outbuf, size_t numSamples) override
Definition: VSTEffect.cpp:1541
NumericConverter::TIME
@ TIME
Definition: NumericTextCtrl.h:52
VSTEffect::mControl
VSTControl * mControl
Definition: VSTEffect.h:378
VSTEffect::AudioMaster
static intptr_t AudioMaster(AEffect *effect, int32_t opcode, int32_t index, intptr_t value, void *ptr, float opt)
Definition: VSTEffect.cpp:940
VSTEffect::mNames
ArrayOf< wxStaticText * > mNames
Definition: VSTEffect.h:381
EffectTypeTool
@ EffectTypeTool
Definition: EffectInterface.h:61
effGetEffectName
const int effGetEffectName
Definition: aeffectx.h:120
VSTEffect::SaveUserPreset
bool SaveUserPreset(const RegistryPath &name) override
Definition: VSTEffect.cpp:1701
VSTEffect::mContainer
wxSizerItem * mContainer
Definition: VSTEffect.h:375
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:496
VSTEffect::RealtimeProcessEnd
bool RealtimeProcessEnd() override
Definition: VSTEffect.cpp:1557
effGetPlugCategory
const int effGetPlugCategory
Definition: aeffectx.h:119
VSTEffectOptionsDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: VSTEffect.cpp:795
ShuttleGui::Validator
ShuttleGui & Validator(const Factory &f)
Definition: ShuttleGui.h:678
VSTEffect::GetEffectIDs
std::vector< int > GetEffectIDs()
Definition: VSTEffect.cpp:2297
effSetProgramName
const int effSetProgramName
Definition: aeffectx.h:96
audioMasterAutomate
const int audioMasterAutomate
Definition: aeffectx.h:34
VSTEffect::mSliders
ArrayOf< wxSlider * > mSliders
Definition: VSTEffect.h:382
WindowAccessible
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
VSTEffect::ProcessBlock
size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen) override
Definition: VSTEffect.cpp:1429
PluginManagerInterface::FindFilesInPathList
virtual void FindFilesInPathList(const wxString &pattern, const FilePaths &pathList, FilePaths &files, bool directories=false)=0
VSTEffect::SetAutomationParameters
bool SetAutomationParameters(CommandParameters &parms) override
Definition: VSTEffect.cpp:1659
VSTEffectOptionsDialog::~VSTEffectOptionsDialog
virtual ~VSTEffectOptionsDialog()
Definition: VSTEffect.cpp:791
VSTEffectTimer::mEffect
VSTEffect * mEffect
Definition: VSTEffect.cpp:911
EffectClientInterface::EffectDialogFactory
std::function< wxDialog *(wxWindow &parent, EffectHostInterface *, EffectUIClientInterface *) > EffectDialogFactory
Definition: EffectInterface.h:190
kKeyDescription
@ kKeyDescription
Definition: VSTEffect.cpp:210
audioMasterGetVendorString
const int audioMasterGetVendorString
Definition: aeffectx.h:67
EffectHostInterface::GetDurationFormat
virtual NumericFormatSymbol GetDurationFormat()=0
VSTEffect::BuildFancy
void BuildFancy()
Definition: VSTEffect.cpp:2801
reinterpretAsUint32
static uint32_t reinterpretAsUint32(float f)
Definition: VSTEffect.cpp:120
VSTEffect::SaveParameters
bool SaveParameters(const RegistryPath &group)
Definition: VSTEffect.cpp:2362
VSTEffect::mTimeInfo
VstTimeInfo mTimeInfo
Definition: VSTEffect.h:347
ConfigClientInterface::GetSharedConfig
virtual bool GetSharedConfig(const RegistryPath &group, const RegistryPath &key, wxString &value, const wxString &defval)=0
VSTSubEntry::OnExit
void OnExit()
Definition: VSTEffect.cpp:192
ChannelNames
enum ChannelName * ChannelNames
VSTEffectTimer::Notify
void Notify()
Definition: VSTEffect.cpp:905
kKeyEnd
@ kKeyEnd
Definition: VSTEffect.cpp:214
audioMasterGetLanguage
const int audioMasterGetLanguage
Definition: aeffectx.h:73
audioMasterGetCurrentProcessLevel
const int audioMasterGetCurrentProcessLevel
Definition: aeffectx.h:57
VSTEffect::RealtimeResume
bool RealtimeResume() override
Definition: VSTEffect.cpp:1521
EffectUIHostInterface
EffectUIHostInterface has nothing in it. It is provided so that an Effect can call SetHostUI passing ...
Definition: EffectInterface.h:257
VSTEffect::Load
bool Load()
Definition: VSTEffect.cpp:1997
VSTEffect::b64encode
static wxString b64encode(const void *in, int len)
Definition: VSTEffect.cpp:2661
audioMasterVersion
const int audioMasterVersion
Definition: aeffectx.h:35
audioMasterCurrentId
const int audioMasterCurrentId
Definition: aeffectx.h:36
effShellGetNextPlugin
const int effShellGetNextPlugin
Definition: aeffectx.h:134
XMLTagHandler
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:80
RegistryPath
wxString RegistryPath
Definition: Identifier.h:218
effGetProgram
const int effGetProgram
Definition: aeffectx.h:94
VSTSubProcess::mType
EffectType mType
Definition: VSTEffect.cpp:300
VSTSubProcess::GetType
EffectType GetType() override
Definition: VSTEffect.cpp:264
AEffect::uniqueID
int32_t uniqueID
Definition: aeffectx.h:295
kKeyBegin
@ kKeyBegin
Definition: VSTEffect.cpp:205
VstPatchChunkInfo::pluginUniqueID
int32_t pluginUniqueID
Definition: aeffectx.h:356
effBeginLoadProgram
const int effBeginLoadProgram
Definition: aeffectx.h:138
VSTEffect::NeedEditIdle
void NeedEditIdle(bool state)
Definition: VSTEffect.cpp:2427
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:893
ConfigInterface.h
VSTEffect::mDuration
NumericTextCtrl * mDuration
Definition: VSTEffect.h:380
VSTEffect::RemoveHandler
void RemoveHandler()
Definition: VSTEffect.cpp:2779
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
kVstTransportPlaying
const int kVstTransportPlaying
Definition: aeffectx.h:157
VSTEffect::IsDefault
bool IsDefault() override
Definition: VSTEffect.cpp:1267
VSTSubProcess::GetSymbol
ComponentInterfaceSymbol GetSymbol() override
Definition: VSTEffect.cpp:239
VSTEffect::GetTailSize
size_t GetTailSize() override
Definition: VSTEffect.cpp:1384
effOpen
const int effOpen
Definition: aeffectx.h:91
wxDialogWrapper
Definition: wxPanelWrapper.h:81
VSTControlMSW.h
effClose
const int effClose
Definition: aeffectx.h:92
VSTEffect::mAEffect
AEffect * mAEffect
Definition: VSTEffect.h:345
PluginPaths
std::vector< PluginPath > PluginPaths
Definition: Identifier.h:215
VSTEffect::SaveFXB
void SaveFXB(const wxFileName &fn)
Definition: VSTEffect.cpp:3461
EffectDefinitionInterface
EffectDefinitionInterface is a ComponentInterface that additionally tracks flag-functions for interac...
Definition: EffectInterface.h:76
VSTEffectOptionsDialog::OnOk
void OnOk(wxCommandEvent &evt)
Definition: VSTEffect.cpp:868
VSTEffect::CloseUI
bool CloseUI() override
Definition: VSTEffect.cpp:1813
VSTEffect::mVstVersion
int mVstVersion
Definition: VSTEffect.h:301
key
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: CommandManager.cpp:197
ConfigClientInterface::SetPrivateConfig
virtual bool SetPrivateConfig(const RegistryPath &group, const RegistryPath &key, const wxString &value)=0
effGetProductString
const int effGetProductString
Definition: aeffectx.h:123
XMLFileReader
Reads a file and passes the results through an XMLTagHandler.
Definition: XMLFileReader.h:20
FileNames::SelectFile
AUDACITY_DLL_API FilePath SelectFile(Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
VSTEffectsModule::Check
static void Check(const wxChar *path)
Definition: VSTEffect.cpp:707
VSTEffectOptionsDialog::mBufferSize
int mBufferSize
Definition: VSTEffect.cpp:767
AEffect::magic
int magic
Definition: aeffectx.h:262
effMainsChanged
const int effMainsChanged
Definition: aeffectx.h:104
_
#define _(s)
Definition: Internat.h:75
VSTEffect::mXMLVersion
long mXMLVersion
Definition: VSTEffect.h:389
vstPluginMain
AEffect *(* vstPluginMain)(audioMasterCallback audioMaster)
Definition: VSTEffect.cpp:938
VSTSubProcess::GetDescription
TranslatableString GetDescription() override
Definition: VSTEffect.cpp:254
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
EffectTypeAnalyze
@ EffectTypeAnalyze
Definition: EffectInterface.h:60
VSTEffect::GetProcessLevel
int GetProcessLevel()
Definition: VSTEffect.cpp:2444
ConfigClientInterface::SetSharedConfig
virtual bool SetSharedConfig(const RegistryPath &group, const RegistryPath &key, const wxString &value)=0
XMLFileWriter
Wrapper to output XML data to files.
Definition: XMLWriter.h:81
VSTEffect::SetString
void SetString(int opcode, const wxString &str, int index=0)
Definition: VSTEffect.cpp:2559
VSTEffect::mMidiOuts
int mMidiOuts
Definition: VSTEffect.h:292
VSTEffectOptionsDialog
Definition: VSTEffect.cpp:756
VSTSubProcess
Definition: VSTEffect.cpp:225
VSTEffectsModule::CreateInstance
std::unique_ptr< ComponentInterface > CreateInstance(const PluginPath &path) override
Definition: VSTEffect.cpp:689
OUTPUTKEY
#define OUTPUTKEY
Definition: VSTEffect.cpp:201
VSTEffect::GetType
EffectType GetType() override
Definition: VSTEffect.cpp:1236
AEffect::getParameter
float(* getParameter)(AEffect *, int)
Definition: aeffectx.h:270
VSTSubEntry
Definition: VSTEffect.cpp:168
effEditIdle
const int effEditIdle
Definition: aeffectx.h:108
VSTEffect
Definition: VSTEffect.h:97
VSTEffect::GetLatency
sampleCount GetLatency() override
Definition: VSTEffect.cpp:1371
ComponentInterfaceSymbol::Internal
const wxString & Internal() const
Definition: ComponentInterfaceSymbol.h:55
VstTimeInfo::sampleRate
double sampleRate
Definition: aeffectx.h:311
VSTEffect::mUserBlockSize
size_t mUserBlockSize
Definition: VSTEffect.h:295
PLATFORM_MAX_PATH
#define PLATFORM_MAX_PATH
Definition: FileNames.h:25
kPlugCategShell
@ kPlugCategShell
Definition: aeffectx.h:375
VSTEffect::HideUI
bool HideUI() override
Definition: VSTEffect.cpp:1808
VSTEffect::Automate
void Automate(int index, float value)
Definition: VSTEffect.cpp:2512
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
AEffect::numOutputs
int numOutputs
Definition: aeffectx.h:278
VSTEffect::GetAudioOutCount
unsigned GetAudioOutCount() override
Definition: VSTEffect.cpp:1340
VSTSubProcess::IsInteractive
bool IsInteractive() override
Definition: VSTEffect.cpp:269
ExceptionType::Internal
@ Internal
Indicates internal failure from Audacity.
VSTEffect::GetString
int GetString(wxString &outstr, int opcode, int index=0)
Definition: VSTEffect.cpp:2537
kKeyVendor
@ kKeyVendor
Definition: VSTEffect.cpp:208
AEffect::initialDelay
int initialDelay
Definition: aeffectx.h:284
VSTEffect::ModuleDeleter::operator()
void operator()(void *) const
Definition: VSTEffect.cpp:1105
VSTEffect::mReady
bool mReady
Definition: VSTEffect.h:305
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2432
VSTEffectOptionsDialog::mUseGUI
bool mUseGUI
Definition: VSTEffect.cpp:769
VSTEffect::mBufferDelay
int mBufferDelay
Definition: VSTEffect.h:350
VSTEffect::mTimerGuard
int mTimerGuard
Definition: VSTEffect.h:362
VSTEffect::OnSizeWindow
void OnSizeWindow(wxCommandEvent &evt)
Definition: VSTEffect.cpp:3018
audioMasterCallback
intptr_t(* audioMasterCallback)(AEffect *, int32_t, int32_t, intptr_t, void *, float)
Definition: aeffectx.h:337
VSTEffect::SetBlockSize
size_t SetBlockSize(size_t maxBlockSize) override
Definition: VSTEffect.cpp:1355
effStopProcess
const int effStopProcess
Definition: aeffectx.h:142
kKeyVersion
@ kKeyVersion
Definition: VSTEffect.cpp:209
AEffect
VST Effects class, conforming to VST layout.
Definition: aeffectx.h:258
TranslatableString::Translation
wxString Translation() const
Definition: TranslatableString.h:79
effStartProcess
const int effStartProcess
Definition: aeffectx.h:141
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:489
VSTControl::Close
void Close()
AEffect::version
int32_t version
Definition: aeffectx.h:296
InfoKeys
InfoKeys
Definition: VSTEffect.cpp:203
VSTEffect::GetSymbol
ComponentInterfaceSymbol GetSymbol() override
Definition: VSTEffect.cpp:1195
VSTEffect::SaveFXProgram
void SaveFXProgram(wxMemoryBuffer &buf, int index)
Definition: VSTEffect.cpp:3583
VSTEffect::mChunk
wxString mChunk
Definition: VSTEffect.h:388
VSTControlGTK.h
VSTEffectOptionsDialog::mHost
EffectHostInterface * mHost
Definition: VSTEffect.cpp:766
VSTSubEntry::OnInit
bool OnInit()
Definition: VSTEffect.cpp:170
effGetParamDisplay
const int effGetParamDisplay
Definition: aeffectx.h:100
ShuttleGuiBase::AddVariableText
wxStaticText * AddVariableText(const TranslatableString &Str, bool bCenter=false, int PositionFlags=0, int wrapWidth=0)
Definition: ShuttleGui.cpp:463
VSTPLUGINTYPE
#define VSTPLUGINTYPE
Definition: VSTEffect.h:34
VSTEffect::LoadFXProgram
bool LoadFXProgram(unsigned char **bptr, ssize_t &len, int index, bool dryrun)
Definition: VSTEffect.cpp:3275
ConfigClientInterface::GetPrivateConfig
virtual bool GetPrivateConfig(const RegistryPath &group, const RegistryPath &key, wxString &value, const wxString &defval)=0
VSTEffect::CanExportPresets
bool CanExportPresets() override
Definition: VSTEffect.cpp:1842
audioMasterProcessEvents
const int audioMasterProcessEvents
Definition: aeffectx.h:42
VSTEffect::mParent
wxWindow * mParent
Definition: VSTEffect.h:373
ModuleInterface::RegistrationCallback
std::function< const PluginID &(ModuleInterface *, ComponentInterface *) > RegistrationCallback
Definition: ModuleInterface.h:123
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:922
VSTControlOSX.h
Destroy_ptr
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:290
AEffect::ptr2
void * ptr2
Definition: aeffectx.h:283
audioMasterIdle
const int audioMasterIdle
Definition: aeffectx.h:37
VSTEffect::mAudioOuts
unsigned mAudioOuts
Definition: VSTEffect.h:290
VSTSubProcess::GetPath
PluginPath GetPath() override
Definition: VSTEffect.cpp:234
VSTSubProcess::mPath
wxString mPath
Definition: VSTEffect.cpp:295
EffectType
EffectType
Definition: EffectInterface.h:55
safenew
#define safenew
Definition: MemoryX.h:10
VSTEffect::callSetProgram
void callSetProgram(int index)
Definition: VSTEffect.cpp:2597
VSTEffect::GetSampleRate
float GetSampleRate()
Definition: VSTEffect.cpp:2439
VSTEffect::OnTimer
void OnTimer()
Definition: VSTEffect.cpp:2396
NumericConverter::GetValue
double GetValue()
Definition: NumericTextCtrl.cpp:1172
VSTSubProcess::mInteractive
bool mInteractive
Definition: VSTEffect.cpp:301
VSTEffect::GetTimeInfo
VstTimeInfo * GetTimeInfo()
Definition: VSTEffect.cpp:2433
anonymous_namespace{Menus.cpp}::Options
std::vector< CommandFlagOptions > & Options()
Definition: Menus.cpp:526
VSTEffectOptionsDialog::mUseLatency
bool mUseLatency
Definition: VSTEffect.cpp:768
VSTEffectsModule::Initialize
bool Initialize() override
Definition: VSTEffect.cpp:352
PlatformCompatibility::GetExecutablePath
static const FilePath & GetExecutablePath()
Definition: PlatformCompatibility.cpp:33
END_EVENT_TABLE
END_EVENT_TABLE()
VSTSubProcess::mVendor
wxString mVendor
Definition: VSTEffect.cpp:297
VstTimeInfo
Definition: aeffectx.h:306
VSTSubProcess::SupportsAutomation
bool SupportsAutomation() override
Definition: VSTEffect.cpp:289
ArrayOf< char >
AEffect::numParams
int numParams
Definition: aeffectx.h:274
VSTEffectsModule::~VSTEffectsModule
virtual ~VSTEffectsModule()
Definition: VSTEffect.cpp:314
effEndSetProgram
const int effEndSetProgram
Definition: aeffectx.h:132
VSTEffect::RealtimeProcessStart
bool RealtimeProcessStart() override
Definition: VSTEffect.cpp:1531
effIdentify
const int effIdentify
Definition: aeffectx.h:110
effFlagsProgramChunks
const int effFlagsProgramChunks
Definition: aeffectx.h:88
EVT_COMMAND_RANGE
EVT_COMMAND_RANGE(ID_Slider, ID_Slider+NUMBER_OF_BANDS - 1, wxEVT_COMMAND_SLIDER_UPDATED, EffectEqualization::OnSlider) EffectEqualization
Definition: Equalization.cpp:218
effGetProgramNameIndexed
const int effGetProgramNameIndexed
Definition: aeffectx.h:117
VSTEffect::mTimer
std::unique_ptr< VSTEffectTimer > mTimer
Definition: VSTEffect.h:361
VSTEffectsModule::FindPluginPaths
PluginPaths FindPluginPaths(PluginManagerInterface &pm) override
Definition: VSTEffect.cpp:393
effGetParamLabel
const int effGetParamLabel
Definition: aeffectx.h:99
AEffect::processReplacing
void(* processReplacing)(AEffect *, float **, float **, int)
Definition: aeffectx.h:298
EffectHostInterface::SetDuration
virtual void SetDuration(double seconds)=0
audioMasterNeedIdle
const int audioMasterNeedIdle
Definition: aeffectx.h:48
VSTEffectOptionsDialog::VSTEffectOptionsDialog
VSTEffectOptionsDialog(wxWindow *parent, EffectHostInterface *host)
Definition: VSTEffect.cpp:778
padc
static const char padc
Definition: VSTEffect.cpp:2659
VSTEffect::GetMidiInCount
int GetMidiInCount() override
Definition: VSTEffect.cpp:1345
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
EffectHostInterface::GetFactoryDefaultsGroup
virtual RegistryPath GetFactoryDefaultsGroup()=0
Internat::CompatibleToDouble
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
Definition: Internat.cpp:134
VSTSubProcess::mAutomatable
bool mAutomatable
Definition: VSTEffect.cpp:302
VSTEffect::GetFactoryPresets
RegistryPaths GetFactoryPresets() override
Definition: VSTEffect.cpp:1706
VSTEffectsModule::GetSymbol
ComponentInterfaceSymbol GetSymbol() override
Definition: VSTEffect.cpp:327
DECLARE_BUILTIN_MODULE
DECLARE_BUILTIN_MODULE(VSTBuiltin)
effBeginLoadBank
const int effBeginLoadBank
Definition: aeffectx.h:136
VSTEffect::SaveXML
void SaveXML(const wxFileName &fn)
Definition: VSTEffect.cpp:3642
VSTEffectsModule::GetVendor
VendorSymbol GetVendor() override
Definition: VSTEffect.cpp:332
audioMasterGetProductString
const int audioMasterGetProductString
Definition: aeffectx.h:68
VSTEffect::LoadFactoryPreset
bool LoadFactoryPreset(int id) override
Definition: VSTEffect.cpp:1724