Audacity 3.2.0
VSTEffectsModule.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 VSTEffectsModule.cpp
6
7 Dominic Mazzoni
8
9 Paul Licameli split from VSTEffect.cpp
10
11
12*//********************************************************************/
13#include "VSTEffectsModule.h"
14
15#include "ModuleManager.h"
16#include "wxArrayStringEx.h"
17
18#if defined(__WXMSW__)
19#include <Windows.h>
20#include <shlwapi.h>
21#endif
22
23#include <wx/tokenzr.h>
24#include <wx/utils.h>
25
26// ============================================================================
27//
28// Module registration entry point
29//
30// This is the symbol that Audacity looks for when the module is built as a
31// dynamic library.
32//
33// When the module is builtin to Audacity, we use the same function, but it is
34// declared static so as not to clash with other builtin modules.
35//
36// ============================================================================
38{
39 // Create our effects module and register
40 // Trust the module manager not to leak this
41 return std::make_unique<VSTEffectsModule>();
42}
43
44// ============================================================================
45//
46// Register this as a builtin module
47//
48// We also take advantage of the fact that wxModules are initialized before
49// the wxApp::OnInit() method is called. We check to see if Audacity was
50// executed to scan a VST effect in a different process.
51//
52// ============================================================================
54
55
61
63{
64}
65
67{
68}
69
70// ============================================================================
71// ComponentInterface implementation
72// ============================================================================
73
75{
76 return {};
77}
78
80{
81 return XO("VST Effects");
82}
83
85{
86 return XO("The Audacity Team");
87}
88
90{
91 // This "may" be different if this were to be maintained as a separate DLL
92 return AUDACITY_VERSION_STRING;
93}
94
96{
97 return XO("Adds the ability to use VST effects in Audacity.");
98}
99
100// ============================================================================
101// PluginProvider implementation
102// ============================================================================
103
105{
106 // Nothing to do here
107 return true;
108}
109
111{
112 // Nothing to do here
113 return;
114}
115
117{
118 return true;
119}
120
122{
123 return VSTPLUGINTYPE;
124}
125
127{
128 static FileExtensions result{{ _T("vst") }};
129 return result;
130}
131
133{
134 // Not yet ready for VST drag-and-drop...
135 // return FileNames::PlugInDir();
136
137 return {};
138}
139
141{
142}
143
145{
146 FilePaths pathList;
147 FilePaths files;
148
149 // Check for the VST_PATH environment variable
150 wxString vstpath = wxString::FromUTF8(getenv("VST_PATH"));
151 if (!vstpath.empty())
152 {
153 wxStringTokenizer tok(vstpath, wxPATH_SEP);
154 while (tok.HasMoreTokens())
155 {
156 pathList.push_back(tok.GetNextToken());
157 }
158 }
159
160 const auto AddCustomPaths = [](PluginManagerInterface& pm, VSTEffectsModule& module, FilePaths& pathList)
161 {
162 const auto customPaths = pm.ReadCustomPaths(module);
163 std::copy(customPaths.begin(), customPaths.end(), std::back_inserter(pathList));
164 };
165
166#if defined(__WXMAC__)
167#define VSTPATH wxT("/Library/Audio/Plug-Ins/VST")
168
169 // Look in ~/Library/Audio/Plug-Ins/VST and /Library/Audio/Plug-Ins/VST
170 pathList.push_back(wxGetHomeDir() + wxFILE_SEP_PATH + VSTPATH);
171 pathList.push_back(VSTPATH);
172
173 AddCustomPaths(pm, *this, pathList);
174
175 // Recursively search all paths for Info.plist files. This will identify all
176 // bundles.
177 pm.FindFilesInPathList(wxT("Info.plist"), pathList, files, true);
178
179 // Remove the 'Contents/Info.plist' portion of the names
180 for (size_t i = 0; i < files.size(); i++)
181 {
182 files[i] = wxPathOnly(wxPathOnly(files[i]));
183 if (!files[i].EndsWith(wxT(".vst")))
184 {
185 files.erase( files.begin() + i-- );
186 }
187 }
188
189#elif defined(__WXMSW__)
190
191 TCHAR dpath[MAX_PATH];
192 TCHAR tpath[MAX_PATH];
193 DWORD len;
194
195 // Try HKEY_CURRENT_USER registry key first
196 len = WXSIZEOF(tpath);
197 if (SHRegGetUSValue(wxT("Software\\VST"),
198 wxT("VSTPluginsPath"),
199 NULL,
200 tpath,
201 &len,
202 FALSE,
203 NULL,
204 0) == ERROR_SUCCESS)
205 {
206 tpath[len] = 0;
207 dpath[0] = 0;
208 ExpandEnvironmentStrings(tpath, dpath, WXSIZEOF(dpath));
209 pathList.push_back(dpath);
210 }
211
212 // Then try HKEY_LOCAL_MACHINE registry key
213 len = WXSIZEOF(tpath);
214 if (SHRegGetUSValue(wxT("Software\\VST"),
215 wxT("VSTPluginsPath"),
216 NULL,
217 tpath,
218 &len,
219 TRUE,
220 NULL,
221 0) == ERROR_SUCCESS)
222 {
223 tpath[len] = 0;
224 dpath[0] = 0;
225 ExpandEnvironmentStrings(tpath, dpath, WXSIZEOF(dpath));
226 pathList.push_back(dpath);
227 }
228
229 // Add the default path last
230 dpath[0] = 0;
231 ExpandEnvironmentStrings(wxT("%ProgramFiles%\\Steinberg\\VSTPlugins"),
232 dpath,
233 WXSIZEOF(dpath));
234 pathList.push_back(dpath);
235
236 dpath[0] = 0;
237 ExpandEnvironmentStrings(wxT("%COMMONPROGRAMFILES%\\VST2"),
238 dpath,
239 WXSIZEOF(dpath));
240 pathList.push_back(dpath);
241
242 AddCustomPaths(pm, *this, pathList);
243
244 // Recursively scan for all DLLs
245 pm.FindFilesInPathList(wxT("*.dll"), pathList, files, true);
246
247#else
248
249 // Nothing specified in the VST_PATH environment variable...provide defaults
250 if (vstpath.empty())
251 {
252 // We add this "non-default" one
253 pathList.push_back(wxT(LIBDIR) wxT("/vst"));
254
255 // These are the defaults used by other hosts
256 pathList.push_back(wxT("/usr/lib/vst"));
257 pathList.push_back(wxT("/usr/local/lib/vst"));
258 pathList.push_back(wxGetHomeDir() + wxFILE_SEP_PATH + wxT(".vst"));
259 }
260
261 AddCustomPaths(pm, *this, pathList);
262
263 // Recursively scan for all shared objects
264 pm.FindFilesInPathList(wxT("*.so"), pathList, files, true);
265
266#endif
267
268 return { files.begin(), files.end() };
269}
270
272 const PluginPath & path, TranslatableString &errMsg,
273 const RegistrationCallback &callback)
274{
275
276 VSTEffectBase effect(path);
277 if(effect.InitializePlugin())
278 {
279 auto effectIDs = effect.GetEffectIDs();
280 if(effectIDs.empty())
281 //Each VST plugin path in Audacity should have id(index) part in it
282 effectIDs.push_back(0);
283
284 for(auto id : effectIDs)
285 {
286 //Subsequent VSTEffect::Load may seem like overhead, but we need
287 //to initialize EffectDefinitionInterface part, which includes
288 //properly formatted plugin path
289 VSTEffectBase subeffect(wxString::Format("%s;%d", path, id));
290 subeffect.Load();
291 if(callback)
292 callback(this, &subeffect);
293 }
294 return effectIDs.size();
295 }
296 errMsg = XO("Could not load the library");
297 return 0;
298}
299
300std::unique_ptr<ComponentInterface>
302{
303 // Acquires a resource for the application.
304 // For us, the ID is simply the path to the effect
305 auto result = Factory::Call(path);
306 if (!result->InitializePlugin())
307 result.reset();
308 return result;
309}
310
312{
313 const auto modulePath = path.BeforeFirst(wxT(';'));
314 return wxFileName::FileExists(modulePath) || wxFileName::DirExists(modulePath);
315}
wxT("CloseDown"))
XO("Cut/Copy/Paste")
std::vector< PluginPath > PluginPaths
Definition: Identifier.h:215
wxString PluginPath
type alias for identifying a Plugin supplied by a module, each module defining its own interpretation...
Definition: Identifier.h:214
wxString FilePath
Definition: Project.h:21
#define VSTPLUGINTYPE
Definition: VSTEffectBase.h:22
#define VSTPATH
DECLARE_PROVIDER_ENTRY(AudacityModule)
DECLARE_BUILTIN_PROVIDER(VSTBuiltin)
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
virtual PluginPaths ReadCustomPaths(const PluginProvider &provider)=0
virtual void FindFilesInPathList(const wxString &pattern, const FilePaths &pathList, FilePaths &files, bool directories=false)=0
std::function< const PluginID &(PluginProvider *, ComponentInterface *) > RegistrationCallback
Further expand a path reported by FindModulePaths.
Holds a msgid for the translation catalog; may also bind format arguments.
bool InitializePlugin()
std::vector< int > GetEffectIDs()
const FileExtensions & GetFileExtensions() override
File types associated with this protocol.
bool Initialize() override
Called immediately after creation. Let provider initialize.
EffectFamilySymbol GetOptionalFamilySymbol() override
A symbol identifying the family of plug-ins provided by this.
bool SupportsCustomModulePaths() const override
FilePath InstallPath() override
Where plug-in files should be copied to install them.
PluginPaths FindModulePaths(PluginManagerInterface &pm) override
TranslatableString GetDescription() const override
void AutoRegisterPlugins(PluginManagerInterface &pm) override
Called so that a provider of a static set of plug-ins can register them.
virtual ~VSTEffectsModule()
bool CheckPluginExist(const PluginPath &path) const override
Performs plugin/module existence check, still plugin may fail to load. Implementation should avoid lo...
VendorSymbol GetVendor() const override
PluginPath GetPath() const override
wxString GetVersion() const override
std::unique_ptr< ComponentInterface > LoadPlugin(const PluginPath &path) override
Load the plug-in at a path reported by DiscoverPluginsAtPath.
unsigned DiscoverPluginsAtPath(const PluginPath &path, TranslatableString &errMsg, const RegistrationCallback &callback) override
ComponentInterfaceSymbol GetSymbol() const override
void Terminate() override
Called just prior to deletion to allow releasing any resources.
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40
bool Load()
Definition: VSTWrapper.cpp:307