Audacity 3.2.0
VST3Effect.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file VST3Effect.cpp
6
7 @author Vitaly Sverchinsky
8
9 @brief Part of Audacity VST3 module
10
11**********************************************************************/
12
13#include "VST3Effect.h"
14
15#include "AudacityException.h"
16
17
18#include "BasicUI.h"
20
21#include <wx/log.h>
22#include <wx/stdpaths.h>
23#include <wx/regex.h>
24
25#include <public.sdk/source/vst/hosting/hostclasses.h>
26
27#include "internal/PlugFrame.h"
29
31
32#include "SelectFile.h"
33
34#include "ShuttleGui.h"
35
36#include "VST3Utils.h"
38#include "VST3OptionsDialog.h"
39#include "VST3Wrapper.h"
40
41#ifdef __WXMSW__
42#include <shlobj.h>
43#endif
44
45#include "ConfigInterface.h"
46#include "VST3Instance.h"
47#include "VST3UIValidator.h"
48
49namespace {
50
51
53{
54#ifdef __WXMSW__
55 PWSTR commonFolderPath { nullptr };
56 auto cleanup = finally([&](){ CoTaskMemFree(commonFolderPath); });
57 if(SHGetKnownFolderPath(FOLDERID_ProgramData, KF_FLAG_DEFAULT , NULL, &commonFolderPath) == S_OK)
58 return wxString(commonFolderPath) + "\\VST3 Presets\\";
59 return {};
60#elif __WXMAC__
61 return wxString("Library/Audio/Presets/");
62#elif __WXGTK__
63 return wxString("/usr/local/share/vst3/presets/");
64#endif
65}
66
67wxString GetPresetsPath(const wxString& basePath, const VST3::Hosting::ClassInfo& effectClassInfo)
68{
69 wxRegEx fixName(R"([\\*?/:<>|])");
70 wxString companyName = wxString (effectClassInfo.vendor()).Trim();
71 wxString pluginName = wxString (effectClassInfo.name()).Trim();
72
73 fixName.ReplaceAll( &companyName, { "_" });
74 fixName.ReplaceAll( &pluginName, { "_" });
75
76 wxFileName result;
77 result.SetPath(basePath);
78 result.AppendDir(companyName);
79 result.AppendDir(pluginName);
80 auto path = result.GetPath();
81
82 return path;
83}
84
85wxString GetFactoryPresetsPath(const VST3::Hosting::ClassInfo& effectClassInfo)
86{
87 return GetPresetsPath(
89 effectClassInfo
90 );
91}
92
93}
94
96{
97 return XO("VST3");
98}
99
101{
102 using namespace Steinberg;
103
104 CloseUI();
105}
106
108 std::shared_ptr<VST3::Hosting::Module> module,
109 VST3::Hosting::ClassInfo effectClassInfo)
110 : mModule(std::move(module)), mEffectClassInfo(std::move(effectClassInfo))
111{
112}
113
115{
116 return VST3Utils::MakePluginPathString( { mModule->getPath() }, mEffectClassInfo.ID().toString());
117}
118
120{
121 return wxString { mEffectClassInfo.name() };
122}
123
125{
126 return wxString { mEffectClassInfo.vendor() };
127}
128
130{
131 return mEffectClassInfo.version();
132}
133
135{
136 //i18n-hint VST3 effect description string
137 return XO("SubCategories: %s").Format( mEffectClassInfo.subCategoriesString() );
138}
139
141{
142 using namespace Steinberg::Vst::PlugType;
143 if(mEffectClassInfo.subCategoriesString() == kFxGenerator)
144 return EffectTypeGenerate;
145 const auto& cats = mEffectClassInfo.subCategories();
146
147 if(std::find(cats.begin(), cats.end(), kFx) != cats.end())
148 return EffectTypeProcess;
149
150 return EffectTypeNone;
151}
152
154{
156}
157
159{
160 return true;
161}
162
164{
165 return false;
166}
167
169{
170 return GetType() == EffectTypeProcess
173}
174
176{
177 return true;
178}
179
181 const EffectSettings& settings, CommandParameters& parms) const
182{
184 return true;
185}
186
188 const CommandParameters& parms, EffectSettings& settings) const
189{
191 return true;
192}
193
196{
198}
199
201 const RegistryPath& name, const EffectSettings& settings) const
202{
204 return true;
205}
206
208{
210 return mFactoryPresets;
211
212 wxArrayString paths;
213 wxDir::GetAllFiles(GetFactoryPresetsPath(mEffectClassInfo), &paths);
214
215 RegistryPaths result;
216 for(auto& path : paths)
217 {
218 wxFileName filename(path);
219 result.push_back(filename.GetName());
220 }
221 mFactoryPresets = std::move(result);
222 mRescanFactoryPresets = false;
223
224 return mFactoryPresets;
225}
226
228{
229 if(id >= 0 && id < mFactoryPresets.size())
230 {
231 auto filename = wxFileName(GetFactoryPresetsPath(mEffectClassInfo), mFactoryPresets[id] + ".vstpreset");
232 if (!LoadPreset(filename.GetFullPath(), settings))
233 return {};
234 }
235 return { nullptr };
236}
237
238int VST3Effect::ShowClientInterface(wxWindow& parent, wxDialog& dialog,
239 EffectUIValidator *validator, bool forceModal)
240{
241#ifdef __WXMSW__
242 if(validator->IsGraphicalUI())
243 //Not all platforms support window style change.
244 //Plugins that support resizing provide their own handles,
245 //which may overlap with system handle. Not all plugins
246 //support free sizing (e.g. fixed steps or fixed ratio)
247 dialog.SetWindowStyle(dialog.GetWindowStyle() & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX));
248#endif
249
250 if(forceModal)
251 return dialog.ShowModal();
252
253 dialog.Show();
254 return 0;
255}
256
257std::shared_ptr<EffectInstance> VST3Effect::MakeInstance() const
258{
259 return std::make_shared<VST3Instance>(*this, *mModule, mEffectClassInfo.ID());
260}
261
262std::unique_ptr<EffectUIValidator> VST3Effect::PopulateUI(ShuttleGui& S,
263 EffectInstance& instance, EffectSettingsAccess &access,
264 const EffectOutputs *)
265{
266 bool useGUI { true };
267 GetConfig(*this, PluginSettings::Shared, wxT("Options"),
268 wxT("UseGUI"),
269 useGUI,
270 useGUI);
271
272 const auto vst3instance = dynamic_cast<VST3Instance*>(&instance);
273 mParent = S.GetParent();
274
275 return std::make_unique<VST3UIValidator>(mParent, vst3instance->GetWrapper(), *this, access, useGUI);
276}
277
279{
280 mParent = nullptr;
281 return true;
282}
283
285{
286 return true;
287}
288
290{
291 using namespace Steinberg;
292
293 auto path = SelectFile(FileNames::Operation::Presets,
294 XO("Save VST3 Preset As:"),
295 wxEmptyString,
296 wxEmptyString,
297 wxT(".vstpreset"),
298 {
299 { XO("VST3 preset file"), { wxT("vstpreset") }, true }
300 },
301 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
302 NULL);
303
304 if (path.empty())
305 return;
306
307 auto dialogPlacement = wxWidgetsWindowPlacement { mParent };
308
309 auto fileStream = owned(Vst::FileStream::open(path.c_str(), "wb"));
310 if(!fileStream)
311 {
313 //i18n-hint: VST3 preset export error
314 XO("Cannot open file"),
316 .Caption(XO("Error"))
317 .Parent(&dialogPlacement)
318 );
319 return;
320 }
321
322 auto wrapper = std::make_unique<VST3Wrapper>(*mModule, mEffectClassInfo.ID());
323 auto dummy = EffectSettings { settings };
324 wrapper->FetchSettings(dummy);
325
326 if (!wrapper->SavePreset(fileStream))
327 {
329 XO("Failed to save VST3 preset to file"),
331 .Caption(XO("Error"))
332 .Parent(&dialogPlacement)
333 );
334 }
335}
336
338{
339 using namespace Steinberg;
340
341 auto path = SelectFile(FileNames::Operation::Presets,
342 XO("Load VST3 preset:"),
343 wxEmptyString,
344 wxEmptyString,
345 wxT(".vstpreset"),
346 {
347 { XO("VST3 preset file"), { wxT("vstpreset") }, true }
348 },
349 wxFD_OPEN | wxRESIZE_BORDER,
350 nullptr
351 );
352 if(path.empty())
353 return {};
354
355 if (!LoadPreset(path, settings))
356 return {};
357
358 return { nullptr };
359}
360
362{
363 return true;
364}
365
367{
368 VST3OptionsDialog dlg(mParent, *this);
369 dlg.ShowModal();
370}
371
372bool VST3Effect::LoadPreset(const wxString& path, EffectSettings& settings) const
373{
374 using namespace Steinberg;
375
376 auto dialogPlacement = wxWidgetsWindowPlacement { mParent };
377
378 auto fileStream = owned(Vst::FileStream::open(path.c_str(), "rb"));
379 if(!fileStream)
380 {
382 XO("Cannot open VST3 preset file %s").Format(path),
384 .Caption(XO("Error"))
385 .Parent(&dialogPlacement)
386 );
387 return false;
388 }
389
390 auto wrapper = std::make_unique<VST3Wrapper>(*mModule, mEffectClassInfo.ID());
391
392 if (!wrapper->LoadPreset(fileStream))
393 {
395 XO("Unable to apply VST3 preset file %s").Format(path),
397 .Caption(XO("Error"))
398 .Parent(&dialogPlacement)
399 );
400 return false;
401 }
402
403 wrapper->StoreSettings(settings);
404
405 return true;
406}
407
409{
411}
412
414{
416 return true;
417}
wxT("CloseDown"))
Declare abstract class AudacityException, some often-used subclasses, and GuardedCall.
Toolkit-neutral facade for basic user interface services.
const TranslatableString name
Definition: Distortion.cpp:74
std::optional< std::unique_ptr< EffectSettingsAccess::Message > > OptionalMessage
EffectType
@ EffectTypeGenerate
@ EffectTypeNone
@ EffectTypeProcess
XO("Cut/Copy/Paste")
wxString RegistryPath
Definition: Identifier.h:218
wxString PluginPath
type alias for identifying a Plugin supplied by a module, each module defining its own interpretation...
Definition: Identifier.h:214
std::vector< RegistryPath > RegistryPaths
Definition: Identifier.h:219
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
Definition: SelectFile.cpp:17
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:87
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the SettingsVis...
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
RealtimeSince
In which versions of Audacity was an effect realtime capable?
Performs effect computation.
Hold values to send to effect output meters.
Interface for transferring values from a panel of effect controls.
Definition: EffectPlugin.h:239
virtual bool IsGraphicalUI()
Abstract base class used in importing a file.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
Holds a msgid for the translation catalog; may also bind format arguments.
bool SaveUserPreset(const RegistryPath &name, const EffectSettings &settings) const override
Save settings in the configuration file as a user-named preset.
Definition: VST3Effect.cpp:200
wxWindow * mParent
Definition: VST3Effect.h:47
const VST3::Hosting::ClassInfo mEffectClassInfo
Definition: VST3Effect.h:45
VST3Effect(std::shared_ptr< VST3::Hosting::Module > module, VST3::Hosting::ClassInfo effectClassInfo)
Definition: VST3Effect.cpp:107
ComponentInterfaceSymbol GetSymbol() const override
Definition: VST3Effect.cpp:119
bool IsInteractive() const override
Whether the effect needs a dialog for entry of settings.
Definition: VST3Effect.cpp:158
OptionalMessage LoadUserPreset(const RegistryPath &name, EffectSettings &settings) const override
Definition: VST3Effect.cpp:194
bool IsDefault() const override
Whether the effect sorts "above the line" in the menus.
Definition: VST3Effect.cpp:163
EffectType GetType() const override
Type determines how it behaves.
Definition: VST3Effect.cpp:140
std::unique_ptr< EffectUIValidator > PopulateUI(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Adds controls to a panel that is given as the parent window of S
Definition: VST3Effect.cpp:262
std::shared_ptr< VST3::Hosting::Module > mModule
Definition: VST3Effect.h:44
bool mRescanFactoryPresets
Definition: VST3Effect.h:50
PluginPath GetPath() const override
Definition: VST3Effect.cpp:114
static EffectFamilySymbol GetFamilySymbol()
Definition: VST3Effect.cpp:95
int ShowClientInterface(wxWindow &parent, wxDialog &dialog, EffectUIValidator *pValidator, bool forceModal) override
Definition: VST3Effect.cpp:238
void ExportPresets(const EffectSettings &settings) const override
Definition: VST3Effect.cpp:289
OptionalMessage ImportPresets(EffectSettings &settings) override
Definition: VST3Effect.cpp:337
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
Definition: VST3Effect.cpp:257
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
Definition: VST3Effect.cpp:187
bool CopySettingsContents(const EffectSettings &src, EffectSettings &dst) const override
Update one settings object from another.
Definition: VST3Effect.cpp:413
RegistryPaths GetFactoryPresets() const override
Report names of factory presets.
Definition: VST3Effect.cpp:207
TranslatableString GetDescription() const override
Definition: VST3Effect.cpp:134
bool CanExportPresets() override
Definition: VST3Effect.cpp:284
RegistryPaths mFactoryPresets
Definition: VST3Effect.h:51
EffectSettings MakeSettings() const override
Definition: VST3Effect.cpp:408
OptionalMessage LoadFactoryPreset(int id, EffectSettings &settings) const override
Definition: VST3Effect.cpp:227
void ShowOptions() override
Definition: VST3Effect.cpp:366
bool CloseUI() override
Definition: VST3Effect.cpp:278
wxString GetVersion() const override
Definition: VST3Effect.cpp:129
bool HasOptions() override
Definition: VST3Effect.cpp:361
bool SaveSettings(const EffectSettings &settings, CommandParameters &parms) const override
Store settings as keys and values.
Definition: VST3Effect.cpp:180
~VST3Effect() override
Definition: VST3Effect.cpp:100
VendorSymbol GetVendor() const override
Definition: VST3Effect.cpp:124
bool SupportsAutomation() const override
Whether the effect has any automatable controls.
Definition: VST3Effect.cpp:175
bool LoadPreset(const wxString &path, EffectSettings &settings) const
Definition: VST3Effect.cpp:372
RealtimeSince RealtimeSupport() const override
Since which version of Audacity has the effect supported realtime?
Definition: VST3Effect.cpp:168
EffectFamilySymbol GetFamily() const override
Report identifier and user-visible name of the effect protocol.
Definition: VST3Effect.cpp:153
static wxString MakePluginPathString(const wxString &modulePath, const std::string &effectUIDString)
Definition: VST3Utils.cpp:24
static EffectSettings MakeSettings()
static void SaveUserPreset(const EffectDefinitionInterface &effect, const RegistryPath &name, const EffectSettings &settings)
static void SaveSettings(const EffectSettings &settings, CommandParameters &parms)
static void CopySettingsContents(const EffectSettings &src, EffectSettings &dst)
static void LoadSettings(const CommandParameters &parms, EffectSettings &settings)
static OptionalMessage LoadUserPreset(const EffectDefinitionInterface &effect, const RegistryPath &name, EffectSettings &settings)
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
Definition: BasicUI.h:269
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
wxString GetFactoryPresetsPath(const VST3::Hosting::ClassInfo &effectClassInfo)
Definition: VST3Effect.cpp:85
wxString GetPresetsPath(const wxString &basePath, const VST3::Hosting::ClassInfo &effectClassInfo)
Definition: VST3Effect.cpp:67
STL namespace.
Externalized state of a plug-in.
Window placement information for wxWidgetsBasicUI can be constructed from a wxWindow pointer.