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