1 /********************************************************************** 2 3 Audacity: A Digital Audio Editor 4 5 VSTEffect.h 6 7 Dominic Mazzoni 8 9 **********************************************************************/ 10 11 12 13 #if USE_VST 14 15 #include "EffectInterface.h" 16 #include "ModuleInterface.h" 17 #include "PluginInterface.h" 18 19 #include "SampleFormat.h" 20 #include "XMLTagHandler.h" 21 22 class wxSizerItem; 23 class wxSlider; 24 class wxStaticText; 25 26 class NumericTextCtrl; 27 28 class VSTControl; 29 #include "VSTControl.h" 30 31 #define VSTCMDKEY wxT("-checkvst") 32 /* i18n-hint: Abbreviates Virtual Studio Technology, an audio software protocol 33 developed by Steinberg GmbH */ 34 #define VSTPLUGINTYPE XO("VST") 35 36 #define audacityVSTID CCONST('a', 'u', 'D', 'y'); 37 38 typedef intptr_t (*dispatcherFn)(AEffect * effect, 39 int opCode, 40 int index, 41 intptr_t value, 42 void *ptr, 43 float opt); 44 45 typedef void (*processFn)(AEffect * effect, 46 float **inputs, 47 float **outputs, 48 int sampleframes); 49 50 typedef void (*setParameterFn)(AEffect * effect, 51 int index, 52 float parameter); 53 54 typedef float (*getParameterFn)(AEffect * effect, 55 int index); 56 57 typedef AEffect *(*vstPluginMain)(audioMasterCallback audioMaster); 58 59 class VSTEffectTimer; 60 class VSTEffectDialog; 61 class VSTEffect; 62 class wxDynamicLibrary; 63 64 #if defined(__WXMAC__) 65 struct __CFBundle; 66 typedef struct __CFBundle *CFBundleRef; 67 #if __LP64__ 68 typedef int CFBundleRefNum; 69 #else 70 typedef signed short SInt16; 71 typedef SInt16 CFBundleRefNum; 72 #endif 73 #endif 74 75 /////////////////////////////////////////////////////////////////////////////// 76 // 77 // VSTEffect 78 // 79 /////////////////////////////////////////////////////////////////////////////// 80 81 using VSTEffectArray = std::vector < std::unique_ptr<VSTEffect> > ; 82 83 DECLARE_LOCAL_EVENT_TYPE(EVT_SIZEWINDOW, -1); 84 DECLARE_LOCAL_EVENT_TYPE(EVT_UPDATEDISPLAY, -1); 85 86 /////////////////////////////////////////////////////////////////////////////// 87 /// 88 /// VSTEffect is an Audacity EffectClientInterface that forwards actual 89 /// audio processing via a VSTEffectLink 90 /// 91 /////////////////////////////////////////////////////////////////////////////// 92 class VSTEffect final : public wxEvtHandler, 93 public EffectClientInterface, 94 public EffectUIClientInterface, 95 public XMLTagHandler, 96 public VSTEffectLink 97 { 98 public: 99 VSTEffect(const PluginPath & path, VSTEffect *master = NULL); 100 virtual ~VSTEffect(); 101 102 // ComponentInterface implementation 103 104 PluginPath GetPath() override; 105 ComponentInterfaceSymbol GetSymbol() override; 106 VendorSymbol GetVendor() override; 107 wxString GetVersion() override; 108 TranslatableString GetDescription() override; 109 110 // EffectDefinitionInterface implementation 111 112 EffectType GetType() override; 113 EffectFamilySymbol GetFamily() override; 114 bool IsInteractive() override; 115 bool IsDefault() override; 116 bool IsLegacy() override; 117 bool SupportsRealtime() override; 118 bool SupportsAutomation() override; 119 120 // EffectClientInterface implementation 121 122 bool SetHost(EffectHostInterface *host) override; 123 124 unsigned GetAudioInCount() override; 125 unsigned GetAudioOutCount() override; 126 127 int GetMidiInCount() override; 128 int GetMidiOutCount() override; 129 130 sampleCount GetLatency() override; 131 size_t GetTailSize() override; 132 133 void SetSampleRate(double rate) override; 134 size_t SetBlockSize(size_t maxBlockSize) override; 135 size_t GetBlockSize() const override; 136 137 bool IsReady() override; 138 bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap = NULL) override; 139 bool ProcessFinalize() override; 140 size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen) override; 141 142 bool RealtimeInitialize() override; 143 bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) override; 144 bool RealtimeFinalize() override; 145 bool RealtimeSuspend() override; 146 bool RealtimeResume() override; 147 bool RealtimeProcessStart() override; 148 size_t RealtimeProcess(int group, 149 float **inbuf, 150 float **outbuf, 151 size_t numSamples) override; 152 bool RealtimeProcessEnd() override; 153 154 bool ShowInterface( wxWindow &parent, 155 const EffectDialogFactory &factory, bool forceModal = false) override; 156 157 bool GetAutomationParameters(CommandParameters & parms) override; 158 bool SetAutomationParameters(CommandParameters & parms) override; 159 160 bool LoadUserPreset(const RegistryPath & name) override; 161 bool SaveUserPreset(const RegistryPath & name) override; 162 163 RegistryPaths GetFactoryPresets() override; 164 bool LoadFactoryPreset(int id) override; 165 bool LoadFactoryDefaults() override; 166 167 // EffectUIClientInterface implementation 168 169 void SetHostUI(EffectUIHostInterface *host) override; 170 bool PopulateUI(ShuttleGui &S) override; 171 bool IsGraphicalUI() override; 172 bool ValidateUI() override; 173 bool HideUI() override; 174 bool CloseUI() override; 175 176 bool CanExportPresets() override; 177 void ExportPresets() override; 178 void ImportPresets() override; 179 180 bool HasOptions() override; 181 void ShowOptions() override; 182 183 // VSTEffect implementation 184 185 // VST plugin -> host callback 186 static intptr_t AudioMaster(AEffect *effect, 187 int32_t opcode, 188 int32_t index, 189 intptr_t value, 190 void * ptr, 191 float opt); 192 193 void OnTimer(); 194 195 private: 196 // Plugin loading and unloading 197 bool Load(); 198 void Unload(); 199 std::vector<int> GetEffectIDs(); 200 201 // Parameter loading and saving 202 bool LoadParameters(const RegistryPath & group); 203 bool SaveParameters(const RegistryPath & group); 204 205 // Base64 encoding and decoding 206 static wxString b64encode(const void *in, int len); 207 static int b64decode(const wxString &in, void *out); 208 209 // Realtime 210 unsigned GetChannelCount(); 211 void SetChannelCount(unsigned numChannels); 212 213 // UI 214 void OnSlider(wxCommandEvent & evt); 215 void OnSizeWindow(wxCommandEvent & evt); 216 void OnUpdateDisplay(wxCommandEvent & evt); 217 218 void RemoveHandler(); 219 220 void OnProgram(wxCommandEvent & evt); 221 void OnProgramText(wxCommandEvent & evt); 222 void OnLoad(wxCommandEvent & evt); 223 void OnSave(wxCommandEvent & evt); 224 void OnSettings(wxCommandEvent & evt); 225 226 void BuildPlain(); 227 void BuildFancy(); 228 wxSizer *BuildProgramBar(); 229 void RefreshParameters(int skip = -1); 230 231 // Program/Bank loading/saving 232 bool LoadFXB(const wxFileName & fn); 233 bool LoadFXP(const wxFileName & fn); 234 bool LoadXML(const wxFileName & fn); 235 bool LoadFXProgram(unsigned char **bptr, ssize_t & len, int index, bool dryrun); 236 void SaveFXB(const wxFileName & fn); 237 void SaveFXP(const wxFileName & fn); 238 void SaveXML(const wxFileName & fn); 239 void SaveFXProgram(wxMemoryBuffer & buf, int index); 240 241 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override; 242 void HandleXMLEndTag(const std::string_view& tag) override; 243 void HandleXMLContent(const std::string_view& content) override; 244 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override; 245 246 // Utility methods 247 248 VstTimeInfo *GetTimeInfo(); 249 float GetSampleRate(); 250 int GetProcessLevel(); 251 void SetBufferDelay(int samples); 252 void NeedIdle(); 253 void NeedEditIdle(bool state); 254 void SizeWindow(int w, int h); 255 void UpdateDisplay(); 256 void Automate(int index, float value); 257 void PowerOn(); 258 void PowerOff(); 259 260 int GetString(wxString & outstr, int opcode, int index = 0); 261 wxString GetString(int opcode, int index = 0); 262 void SetString(int opcode, const wxString & str, int index = 0); 263 264 // VST methods 265 266 intptr_t callDispatcher(int opcode, int index, 267 intptr_t value, void *ptr, float opt) override; 268 void callProcessReplacing(float **inputs, float **outputs, int sampleframes); 269 void callSetParameter(int index, float value); 270 float callGetParameter(int index); 271 void callSetProgram(int index); 272 void callSetChunk(bool isPgm, int len, void *buf); 273 void callSetChunk(bool isPgm, int len, void *buf, VstPatchChunkInfo *info); 274 275 private: 276 // Define a manager class for a handle to a module 277 #if defined(__WXMSW__) 278 using ModuleHandle = std::unique_ptr<wxDynamicLibrary>; 279 #else 280 struct ModuleDeleter { 281 void operator() (void*) const; 282 }; 283 using ModuleHandle = std::unique_ptr < char, ModuleDeleter > ; 284 #endif 285 286 EffectHostInterface *mHost; 287 PluginID mID; 288 PluginPath mPath; 289 unsigned mAudioIns; 290 unsigned mAudioOuts; 291 int mMidiIns; 292 int mMidiOuts; 293 bool mAutomatable; 294 float mSampleRate; 295 size_t mUserBlockSize; 296 wxString mName; 297 wxString mVendor; 298 wxString mDescription; 299 int mVersion; 300 bool mInteractive; 301 int mVstVersion; 302 303 static intptr_t mCurrentEffectID; 304 305 bool mReady; 306 307 ModuleHandle mModule; 308 309 #if defined(__WXMAC__) 310 // These members must be ordered after mModule 311 312 struct BundleDeleter { 313 void operator() (void*) const; 314 }; 315 using BundleHandle = std::unique_ptr< 316 __CFBundle, BundleDeleter 317 >; 318 319 BundleHandle mBundleRef; 320 321 struct ResourceHandle { 322 ResourceHandle( 323 CFBundleRef pHandle = nullptr, CFBundleRefNum num = 0) 324 : mpHandle{ pHandle }, mNum{ num } 325 {} 326 ResourceHandle& operator=( ResourceHandle &&other ) 327 { 328 if (this != &other) { 329 mpHandle = other.mpHandle; 330 mNum = other.mNum; 331 other.mpHandle = nullptr; 332 other.mNum = 0; 333 } 334 return *this; 335 } ~ResourceHandleResourceHandle336 ~ResourceHandle() { reset(); } 337 void reset(); 338 339 CFBundleRef mpHandle{}; 340 CFBundleRefNum mNum{}; 341 }; 342 ResourceHandle mResource; 343 #endif 344 345 AEffect *mAEffect; 346 347 VstTimeInfo mTimeInfo; 348 349 bool mUseLatency; 350 int mBufferDelay; 351 352 unsigned mBlockSize; 353 354 int mProcessLevel; 355 bool mHasPower; 356 bool mWantsIdle; 357 bool mWantsEditIdle; 358 359 wxCRIT_SECT_DECLARE_MEMBER(mDispatcherLock); 360 361 std::unique_ptr<VSTEffectTimer> mTimer; 362 int mTimerGuard; 363 364 // Realtime processing 365 VSTEffect *mMaster; // non-NULL if a slave 366 VSTEffectArray mSlaves; 367 unsigned mNumChannels; 368 FloatBuffers mMasterIn, mMasterOut; 369 size_t mNumSamples; 370 371 // UI 372 wxDialog *mDialog; 373 wxWindow *mParent; 374 EffectUIHostInterface *mUIHost; 375 wxSizerItem *mContainer; 376 bool mGui; 377 378 VSTControl *mControl; 379 380 NumericTextCtrl *mDuration; 381 ArrayOf<wxStaticText *> mNames; 382 ArrayOf<wxSlider *> mSliders; 383 ArrayOf<wxStaticText *> mDisplays; 384 ArrayOf<wxStaticText *> mLabels; 385 386 bool mInSet; 387 bool mInChunk; 388 wxString mChunk; 389 long mXMLVersion; 390 VstPatchChunkInfo mXMLInfo; 391 392 DECLARE_EVENT_TABLE() 393 394 friend class VSTEffectsModule; 395 }; 396 397 /////////////////////////////////////////////////////////////////////////////// 398 /// 399 /// VSTEffectsModule is an Audacity ModuleInterface, in other words it 400 /// represents one plug in. 401 /// 402 /////////////////////////////////////////////////////////////////////////////// 403 class VSTEffectsModule final : public ModuleInterface 404 { 405 public: 406 VSTEffectsModule(); 407 virtual ~VSTEffectsModule(); 408 409 // ComponentInterface implementation 410 411 PluginPath GetPath() override; 412 ComponentInterfaceSymbol GetSymbol() override; 413 VendorSymbol GetVendor() override; 414 wxString GetVersion() override; 415 TranslatableString GetDescription() override; 416 417 // ModuleInterface implementation 418 419 bool Initialize() override; 420 void Terminate() override; 421 EffectFamilySymbol GetOptionalFamilySymbol() override; 422 423 const FileExtensions &GetFileExtensions() override; 424 FilePath InstallPath() override; 425 426 bool AutoRegisterPlugins(PluginManagerInterface & pm) override; 427 PluginPaths FindPluginPaths(PluginManagerInterface & pm) override; 428 unsigned DiscoverPluginsAtPath( 429 const PluginPath & path, TranslatableString &errMsg, 430 const RegistrationCallback &callback) 431 override; 432 433 bool IsPluginValid(const PluginPath & path, bool bFast) override; 434 435 std::unique_ptr<ComponentInterface> 436 CreateInstance(const PluginPath & path) override; 437 438 // VSTEffectModule implementation 439 440 static void Check(const wxChar *path); 441 }; 442 443 #endif // USE_VST 444