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