Audacity 3.2.0
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#include "VSTEffect.h"
29#include "VSTEditor.h"
30#include "VSTEffectsModule.h"
31#include "VSTInstance.h"
32#include "SampleCount.h"
33
34#include "ProgressDialog.h"
35
36#include "SelectFile.h"
37#include "ShuttleGui.h"
38#include "AudacityMessageBox.h"
39#include "ConfigInterface.h"
40
41// NOTE: To debug the subprocess, use wxLogDebug and, on Windows, Debugview
42// from TechNet (Sysinternals).
43
45//
46// VSTEffect
47//
49enum
50{
51 ID_Duration = 20000,
52 ID_Sliders = 21000,
53};
54
55wxDEFINE_EVENT(EVT_SIZEWINDOW, wxCommandEvent);
56DEFINE_LOCAL_EVENT_TYPE(EVT_UPDATEDISPLAY);
57
58VSTEffect::~VSTEffect() = default;
59
87 wxWindow &parent, wxDialog &dialog,
88 EffectEditor* pEditor, bool forceModal) const
89{
90 // mProcessLevel = 1; // in GUI thread
91
92 VSTEditor* vstEditor = static_cast<VSTEditor*>(pEditor);
93
94 return vstEditor->ShowDialog(/* nonModal = */ SupportsRealtime() && !forceModal);
95}
96
97std::unique_ptr<EffectEditor> VSTEffect::PopulateUI(const EffectPlugin &,
99 const EffectOutputs *) const
100{
101 auto parent = S.GetParent();
102
103 // Determine whether fancy UI is available
104 bool gui = mGui;
105
106 // Then use fancy UI only if preferences say so
107 if (gui)
108 GetConfig(*this, PluginSettings::Shared, wxT("Options"),
109 wxT("UseGUI"),
110 gui,
111 true);
112
113 auto pParent = S.GetParent();
114
115 auto& vst2Instance = dynamic_cast<VSTInstance&>(instance);
116
117 auto editor = std::make_unique<VSTEditor>(
118 vst2Instance, GetType(), gui, *this, access, pParent, mAEffect->numParams);
119
120 // Also let the instance know about the validator, so it can forward
121 // to it calls coming from the vst callback
122 vst2Instance.SetOwningValidator(editor.get());
123
124
125 // Build the appropriate dialog type
126 if (gui)
127 {
128 editor->BuildFancy(instance);
129 }
130 else
131 {
132 editor->BuildPlain(access, GetType(), mProjectRate);
133 }
134
135
136 return editor;
137}
138
139std::unique_ptr<EffectEditor> VSTEffect::MakeEditor(
141 const EffectOutputs *) const
142{
144 assert(false);
145 return nullptr;
146}
147
148// Throws exceptions rather than reporting errors.
150 const EffectPlugin &, const EffectSettings& settings) const
151{
152 wxString path;
153
154 // Ask the user for the real name
155 //
156 // Passing a valid parent will cause some effects dialogs to malfunction
157 // upon returning from the SelectFile().
158 path = SelectFile(FileNames::Operation::Presets,
159 XO("Save VST Preset As:"),
160 wxEmptyString,
161 wxT("preset"),
162 wxT("xml"),
163 {
164 { XO("Standard VST bank file"), { wxT("fxb") }, true },
165 { XO("Standard VST program file"), { wxT("fxp") }, true },
166 { XO("Audacity VST preset file"), { wxT("xml") }, true },
167 },
168 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
169 NULL);
170
171 // User canceled...
172 if (path.empty())
173 {
174 return;
175 }
176
178 return;
179
180 wxFileName fn(path);
181 wxString ext = fn.GetExt();
182 if (ext.CmpNoCase(wxT("fxb")) == 0)
183 {
184 SaveFXB(fn);
185 }
186 else if (ext.CmpNoCase(wxT("fxp")) == 0)
187 {
188 SaveFXP(fn);
189 }
190 else if (ext.CmpNoCase(wxT("xml")) == 0)
191 {
192 // may throw
193 SaveXML(fn);
194 }
195 else
196 {
197 // This shouldn't happen, but complain anyway
199 XO("Unrecognized file extension."),
200 XO("Error Saving VST Presets"),
201 wxOK | wxCENTRE,
202 nullptr);
203
204 return;
205 }
206}
207
208//
209// Load an "fxb", "fxp" or Audacuty "xml" file
210//
211// Based on work by Sven Giermann
212//
215{
216 auto temp = std::make_unique<VSTEffect>(this->mPath);
217 if (!temp->InitializePlugin())
218 return {};
219 return temp->ImportPresetsNC(settings);
220}
221
223{
224 wxString path;
225
226 // Ask the user for the real name
227 path = SelectFile(FileNames::Operation::Presets,
228 XO("Load VST Preset:"),
229 wxEmptyString,
230 wxT("preset"),
231 wxT("xml"),
232 { {
233 XO("VST preset files"),
234 { wxT("fxb"), wxT("fxp"), wxT("xml") },
235 true
236 } },
237 wxFD_OPEN | wxRESIZE_BORDER,
238 nullptr);
239
240 // User canceled...
241 if (path.empty())
242 {
243 return {};
244 }
245
246 wxFileName fn(path);
247 wxString ext = fn.GetExt();
248 bool success = false;
249 if (ext.CmpNoCase(wxT("fxb")) == 0)
250 {
251 success = LoadFXB(fn);
252 }
253 else if (ext.CmpNoCase(wxT("fxp")) == 0)
254 {
255 success = LoadFXP(fn);
256 }
257 else if (ext.CmpNoCase(wxT("xml")) == 0)
258 {
259 success = LoadXML(fn);
260 }
261 else
262 {
263 // This shouldn't happen, but complain anyway
265 XO("Unrecognized file extension."),
266 XO("Error Loading VST Presets"),
267 wxOK | wxCENTRE,
268 nullptr);
269
270 return {};
271 }
272
273 if (!success)
274 {
276 XO("Unable to load presets file."),
277 XO("Error Loading VST Presets"),
278 wxOK | wxCENTRE,
279 nullptr);
280
281 return {};
282 }
283
285 return {};
286
287 return MakeMessageFS(
289}
290
292{
293 VSTEffectOptionsDialog{ *this }.ShowModal();
294}
295
296// Inject factory hook to make VSTEffect capable of UI
297static VSTEffectsModule::Factory::SubstituteInUnique<VSTEffect> scope;
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
std::optional< std::unique_ptr< EffectSettingsAccess::Message > > OptionalMessage
XO("Cut/Copy/Paste")
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:51
DEFINE_LOCAL_EVENT_TYPE(EVT_UPDATEDISPLAY)
wxDEFINE_EVENT(EVT_SIZEWINDOW, wxCommandEvent)
static VSTEffectsModule::Factory::SubstituteInUnique< VSTEffect > scope
Definition: VSTEffect.cpp:297
@ ID_Duration
Definition: VSTEffect.cpp:51
@ ID_Sliders
Definition: VSTEffect.cpp:52
static const auto fn
int numParams
Definition: aeffectx.h:274
double mProjectRate
Definition: EffectBase.h:119
Performs effect computation.
Hold values to send to effect output meters.
Factory of instances of an effect.
Definition: EffectPlugin.h:36
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
int ShowDialog(bool nonModal)
Definition: VSTEditor.cpp:88
EffectType GetType() const override
Type determines how it behaves.
std::unique_ptr< EffectEditor > PopulateUI(const EffectPlugin &plugin, ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) const override
Adds controls to a panel that is given as the parent window of S
Definition: VSTEffect.cpp:97
int ShowClientInterface(const EffectPlugin &plugin, wxWindow &parent, wxDialog &dialog, EffectEditor *pEditor, bool forceModal) const override
Definition: VSTEffect.cpp:86
OptionalMessage ImportPresetsNC(EffectSettings &settings)
Definition: VSTEffect.cpp:222
virtual std::unique_ptr< EffectEditor > MakeEditor(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) const final
Will never be called.
Definition: VSTEffect.cpp:139
void ShowOptions(const EffectPlugin &plugin) const override
Definition: VSTEffect.cpp:291
void ExportPresets(const EffectPlugin &plugin, const EffectSettings &settings) const override
Definition: VSTEffect.cpp:149
OptionalMessage ImportPresets(const EffectPlugin &plugin, EffectSettings &settings) const override
Definition: VSTEffect.cpp:213
~VSTEffect() override
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
Externalized state of a plug-in.
void SaveFXP(const wxFileName &fn) const
bool FetchSettings(VSTSettings &vst3Settings, bool doFetch=true) const
static VSTSettings & GetSettings(EffectSettings &settings)
Definition: VSTWrapper.h:103
bool LoadXML(const wxFileName &fn)
bool StoreSettings(const VSTSettings &vst3settings) const
AEffect * mAEffect
Definition: VSTWrapper.h:124
void SaveFXB(const wxFileName &fn) const
bool LoadFXP(const wxFileName &fn)
Definition: VSTWrapper.cpp:931
std::unique_ptr< EffectInstance::Message > MakeMessageFS(const VSTSettings &settings) const
void SaveXML(const wxFileName &fn) const
PluginPath mPath
Definition: VSTWrapper.h:203
bool LoadFXB(const wxFileName &fn)
Definition: VSTWrapper.cpp:758