Audacity 3.2.0
VSTEffectBase.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 Paul Licameli split from VSTEffect.cpp
10
11 This class implements a VST Plug-in effect. The plug-in must be
12 loaded in a platform-specific way and passed into the constructor,
13 but from here this class handles the interfacing.
14
15********************************************************************//********************************************************************/
21
22#include "VSTEffectBase.h"
23#include "VSTInstance.h"
24
25#include <wx/time.h>
26
27#include "Base64.h"
28#include "ConfigInterface.h"
29
32{
33 memset(&mTimeInfo, 0, sizeof(mTimeInfo));
34 mTimeInfo.samplePos = 0.0;
35 mTimeInfo.sampleRate = 44100.0; // this is a bogus value, but it's only for the display
36 mTimeInfo.nanoSeconds = wxGetUTCTimeMillis().ToDouble();
37 mTimeInfo.tempo = 120.0;
38 mTimeInfo.timeSigNumerator = 4;
39 mTimeInfo.timeSigDenominator = 4;
40 mTimeInfo.flags = kVstTempoValid | kVstNanosValid;
41}
42
44
46{
47 return mPath;
48}
49
51{
52 return VSTWrapper::GetSymbol();
53}
54
56{
57 return { mVendor };
58}
59
61{
62 wxString version;
63
64 bool skipping = true;
65 for (int i = 0, s = 0; i < 4; i++, s += 8)
66 {
67 int dig = (mVersion >> s) & 0xff;
68 if (dig != 0 || !skipping)
69 {
70 version += !skipping ? wxT(".") : wxT("");
71 version += wxString::Format(wxT("%d"), dig);
72 skipping = false;
73 }
74 }
75
76 return version;
77}
78
80{
81 // VST does have a product string opcode and some effects return a short
82 // description, but most do not or they just return the name again. So,
83 // try to provide some sort of useful information.
84 return XO("Audio In: %d, Audio Out: %d").Format( mAudioIns, mAudioOuts );
85}
86
87// ============================================================================
88// EffectDefinitionInterface Implementation
89// ============================================================================
90
92{
93 if (mAudioIns == 0 && mAudioOuts == 0)
94 {
95 return EffectTypeTool;
96 }
97
98 if (mAudioIns == 0)
99 {
100 return EffectTypeGenerate;
101 }
102
103 if (mAudioOuts == 0)
104 {
105 return EffectTypeAnalyze;
106 }
107
108 return EffectTypeProcess;
109}
110
111
113{
114 return VSTPLUGINTYPE;
115}
116
118{
119 return mInteractive;
120}
121
123{
124 return false;
125}
126
128{
130
131 /* return GetType() == EffectTypeProcess
132 ? RealtimeSince::Always
133 : RealtimeSince::Never; */
134}
135
137{
138 return mAutomatable;
139}
140
142{
143 if (!mAEffect)
144 {
145 Load();
146 }
147
148 if (!mAEffect)
149 {
150 return false;
151 }
152
153 return true;
154}
155
156std::shared_ptr<EffectInstance> VSTEffectBase::MakeInstance() const
157{
158 int userBlockSize;
159 GetConfig(*this, PluginSettings::Shared, wxT("Options"),
160 wxT("BufferSize"), userBlockSize, 8192);
161 size_t userBlockSizeC = std::max( 1, userBlockSize );
162 bool useLatency;
163 GetConfig(*this, PluginSettings::Shared, wxT("Options"),
164 wxT("UseLatency"), useLatency, true);
165
166
167 return std::make_shared<VSTInstance>(
168 *this, mPath, userBlockSizeC, userBlockSizeC, useLatency);
169}
170
172{
173 const VSTSettings& vstSettings = GetSettings(settings);
174
175 for (const auto& item : vstSettings.mParamsMap)
176 {
177 if (item.second)
178 {
179 const auto& name = item.first;
180 const auto& value = *(item.second);
181
182 if (!parms.Write(name, value))
183 {
184 return false;
185 }
186 }
187 }
188
189 return true;
190}
191
193{
194 VSTSettings& vstSettings = GetSettings(settings);
195
196 long index{};
197 wxString key;
198 double value = 0.0;
199 if (parms.GetFirstEntry(key, index))
200 {
201 do
202 {
203 if (parms.Read(key, &value)) {
204 auto &map = vstSettings.mParamsMap;
205 auto iter = map.find(key);
206 if (iter != map.end()) {
207 if (iter->second)
208 // Should be guaranteed by MakeSettings
209 iter->second = value;
210 else {
211 assert(false);
212 }
213 }
214 else
215 // Unknown parameter name in the file
216 return false;
217 }
218 } while (parms.GetNextEntry(key, index));
219 }
220
221 // Loads key-value pairs only from a config file -- no chunk
222 vstSettings.mChunk.resize(0);
223 vstSettings.mVersion = VSTWrapper::mVersion;
226
227 return true;
228}
229
231{
232 RegistryPaths progs;
233
234 // Some plugins, like Guitar Rig 5, only report 128 programs while they have hundreds. While
235 // I was able to come up with a hack in the Guitar Rig case to gather all of the program names
236 // it would not let me set a program outside of the first 128.
237 if (mVstVersion >= 2)
238 {
239 for (int i = 0; i < mAEffect->numPrograms; i++)
240 {
241 progs.push_back(GetString(effGetProgramNameIndexed, i));
242 }
243 }
244
245 return progs;
246}
247
250{
251 // To do: externalize state so const_cast isn't needed
252 bool loadOK = const_cast<VSTEffectBase*>(this)->DoLoadFactoryPreset(id) &&
254 if (!loadOK)
255 return {};
256 return MakeMessageFS(
258}
259
261{
262 callSetProgram(id);
263
264 return true;
265}
266
268{
269 return true;
270}
271
273{
274 return true;
275}
276
278{
279 std::vector<int> effectIDs;
280
281 // Are we a shell?
283 {
284 char name[64];
285 int effectID;
286
287 effectID = (int) callDispatcher(effShellGetNextPlugin, 0, 0, &name, 0);
288 while (effectID)
289 {
290 effectIDs.push_back(effectID);
291 effectID = (int) callDispatcher(effShellGetNextPlugin, 0, 0, &name, 0);
292 }
293 }
294
295 return effectIDs;
296}
297
299 const RegistryPath & group, EffectSettings &settings) const
300{
301 wxString value;
302
303 auto info = GetChunkInfo();
304
305 GetConfig(*this, PluginSettings::Private, group, wxT("UniqueID"),
306 info.pluginUniqueID, info.pluginUniqueID);
307 GetConfig(*this, PluginSettings::Private, group, wxT("Version"),
308 info.pluginVersion, info.pluginVersion);
309 GetConfig(*this, PluginSettings::Private, group, wxT("Elements"),
310 info.numElements, info.numElements);
311
312 if ( ! IsCompatible(info) )
313 {
314 return {};
315 }
316
317 if (GetConfig(*this,
318 PluginSettings::Private, group, wxT("Chunk"), value, wxEmptyString))
319 {
320 ArrayOf<char> buf{ value.length() / 4 * 3 };
321
322 int len = Base64::Decode(value, buf.get());
323 if (len)
324 {
325 callSetChunk(true, len, buf.get(), &info);
327 return {};
328 }
329
330 return MakeMessageFS(
332 }
333
334 wxString parms;
335 if (!GetConfig(*this,
336 PluginSettings::Private, group, wxT("Parameters"), parms, wxEmptyString))
337 {
338 return {};
339 }
340
342 if (!eap.SetParameters(parms))
343 {
344 return {};
345 }
346
347 const bool loadOK = LoadSettings(eap, settings) &&
349 if (!loadOK)
350 return {};
351
352 return MakeMessageFS(
354}
355
357 const RegistryPath & group, const EffectSettings &settings) const
358{
359 const auto& vstSettings = GetSettings(settings);
360
361 if ( ! StoreSettings(vstSettings) )
362 return false;
363
364 SetConfig(*this, PluginSettings::Private, group, wxT("UniqueID"), vstSettings.mUniqueID );
365 SetConfig(*this, PluginSettings::Private, group, wxT("Version"), vstSettings.mVersion );
366 SetConfig(*this, PluginSettings::Private, group, wxT("Elements"), vstSettings.mNumParams);
367
369 {
370 void *chunk = NULL;
371 int clen = (int) constCallDispatcher(effGetChunk, 1, 0, &chunk, 0.0);
372 if (clen <= 0)
373 {
374 return false;
375 }
376
377 SetConfig(*this, PluginSettings::Private, group, wxT("Chunk"),
378 Base64::Encode(chunk, clen));
379 return true;
380 }
381
383 if (!SaveSettings(settings, eap))
384 {
385 return false;
386 }
387
388 wxString parms;
389 if (!eap.GetParameters(parms))
390 {
391 return false;
392 }
393
395 group, wxT("Parameters"), parms);
396}
397
399{
402 return EffectSettings::Make<VSTSettings>(std::move(settings));
403}
wxT("CloseDown"))
EffectType
@ EffectTypeAnalyze
@ EffectTypeGenerate
@ EffectTypeTool
@ EffectTypeProcess
std::optional< std::unique_ptr< EffectSettingsAccess::Message > > OptionalMessage
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
static const AudacityProject::AttachedObjects::RegisteredFactory key
wxString name
Definition: TagsEditor.cpp:166
static Settings & settings()
Definition: TrackInfo.cpp:51
#define VSTPLUGINTYPE
Definition: VSTEffectBase.h:22
VstPlugCategory
Definition: aeffectx.h:364
@ kPlugCategShell
Definition: aeffectx.h:375
const int kVstNanosValid
Definition: aeffectx.h:148
const int effGetChunk
Definition: aeffectx.h:111
const int effShellGetNextPlugin
Definition: aeffectx.h:134
const int effFlagsProgramChunks
Definition: aeffectx.h:88
const int effGetProgramNameIndexed
Definition: aeffectx.h:117
const int effGetPlugCategory
Definition: aeffectx.h:119
const int kVstTempoValid
Definition: aeffectx.h:150
int numParams
Definition: aeffectx.h:274
int flags
Definition: aeffectx.h:280
int numPrograms
Definition: aeffectx.h:272
int32_t uniqueID
Definition: aeffectx.h:295
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the SettingsVis...
bool GetParameters(wxString &parms)
bool SetParameters(const wxString &parms)
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
RealtimeSince
In which versions of Audacity was an effect realtime capable?
Holds a msgid for the translation catalog; may also bind format arguments.
RegistryPaths GetFactoryPresets() const override
Report names of factory presets.
TranslatableString GetDescription() const override
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
bool IsInteractive() const override
Whether the effect needs a dialog for entry of settings.
bool InitializePlugin()
EffectType GetType() const override
Type determines how it behaves.
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
EffectFamilySymbol GetFamily() const override
Report identifier and user-visible name of the effect protocol.
OptionalMessage LoadFactoryPreset(int id, EffectSettings &settings) const override
PluginPath GetPath() const override
VSTEffectBase(const PluginPath &path)
bool DoLoadFactoryPreset(int id)
bool HasOptions() const override
ComponentInterfaceSymbol GetSymbol() const override
OptionalMessage LoadUserPreset(const RegistryPath &name, EffectSettings &settings) const override
~VSTEffectBase() override
bool SupportsAutomation() const override
Whether the effect has any automatable controls.
wxString GetVersion() const override
bool CanExportPresets() const override
Whether the effect supports export of presets to files, and importing too.
VendorSymbol GetVendor() const override
std::vector< int > GetEffectIDs()
RealtimeSince RealtimeSupport() const override
Since which version of Audacity has the effect supported realtime?
EffectSettings MakeSettings() const override
bool SaveSettings(const EffectSettings &settings, CommandParameters &parms) const override
Store settings as keys and values.
bool IsDefault() const override
Whether the effect sorts "above the line" in the menus.
bool SaveUserPreset(const RegistryPath &name, const EffectSettings &settings) const override
Save settings in the configuration file as a user-named preset.
STRINGS_API wxString Encode(const void *in, int len)
Definition: Base64.cpp:27
STRINGS_API int Decode(const wxString &in, void *out)
Definition: Base64.cpp:67
bool SetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, const Value &value)
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
Externalized state of a plug-in.
std::vector< char > mChunk
Definition: VSTWrapper.h:85
std::unordered_map< wxString, std::optional< double > > mParamsMap
Definition: VSTWrapper.h:88
int32_t mVersion
Definition: VSTWrapper.h:76
int32_t mNumParams
Definition: VSTWrapper.h:77
int32_t mUniqueID
Definition: VSTWrapper.h:75
bool mAutomatable
Definition: VSTWrapper.h:224
unsigned mAudioOuts
Definition: VSTWrapper.h:221
int GetString(wxString &outstr, int opcode, int index=0) const
Definition: VSTWrapper.cpp:651
int mVstVersion
Definition: VSTWrapper.h:165
bool FetchSettings(VSTSettings &vst3Settings, bool doFetch=true) const
static VSTSettings & GetSettings(EffectSettings &settings)
Definition: VSTWrapper.h:103
bool StoreSettings(const VSTSettings &vst3settings) const
AEffect * mAEffect
Definition: VSTWrapper.h:124
intptr_t constCallDispatcher(int opcode, int index, intptr_t value, void *ptr, float opt) const
Definition: VSTWrapper.cpp:691
bool IsCompatible(const VstPatchChunkInfo &) const
Definition: VSTWrapper.cpp:609
intptr_t callDispatcher(int opcode, int index, intptr_t value, void *ptr, float opt) override
Definition: VSTWrapper.cpp:682
bool mInteractive
Definition: VSTWrapper.h:219
int mVersion
Definition: VSTWrapper.h:218
bool Load()
Definition: VSTWrapper.cpp:307
void callSetProgram(int index)
Definition: VSTWrapper.cpp:712
std::unique_ptr< EffectInstance::Message > MakeMessageFS(const VSTSettings &settings) const
unsigned mAudioIns
Definition: VSTWrapper.h:220
PluginPath mPath
Definition: VSTWrapper.h:203
VstPatchChunkInfo GetChunkInfo() const
Definition: VSTWrapper.cpp:603
wxString mVendor
Definition: VSTWrapper.h:216
void callSetChunk(bool isPgm, int len, void *buf)
Definition: VSTWrapper.cpp:721
ComponentInterfaceSymbol GetSymbol() const