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