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 VSTPLUGINTYPE;
119}
120
122{
123 static FileExtensions result{{ _T("vst") }};
124 return result;
125}
126
128{
129 // Not yet ready for VST drag-and-drop...
130 // return FileNames::PlugInDir();
131
132 return {};
133}
134
136{
137}
138
140{
141 FilePaths pathList;
142 FilePaths files;
143
144 // Check for the VST_PATH environment variable
145 wxString vstpath = wxString::FromUTF8(getenv("VST_PATH"));
146 if (!vstpath.empty())
147 {
148 wxStringTokenizer tok(vstpath, wxPATH_SEP);
149 while (tok.HasMoreTokens())
150 {
151 pathList.push_back(tok.GetNextToken());
152 }
153 }
154
155#if defined(__WXMAC__)
156#define VSTPATH wxT("/Library/Audio/Plug-Ins/VST")
157
158 // Look in ~/Library/Audio/Plug-Ins/VST and /Library/Audio/Plug-Ins/VST
159 pathList.push_back(wxGetHomeDir() + wxFILE_SEP_PATH + VSTPATH);
160 pathList.push_back(VSTPATH);
161
162 // Recursively search all paths for Info.plist files. This will identify all
163 // bundles.
164 pm.FindFilesInPathList(wxT("Info.plist"), pathList, files, true);
165
166 // Remove the 'Contents/Info.plist' portion of the names
167 for (size_t i = 0; i < files.size(); i++)
168 {
169 files[i] = wxPathOnly(wxPathOnly(files[i]));
170 if (!files[i].EndsWith(wxT(".vst")))
171 {
172 files.erase( files.begin() + i-- );
173 }
174 }
175
176#elif defined(__WXMSW__)
177
178 TCHAR dpath[MAX_PATH];
179 TCHAR tpath[MAX_PATH];
180 DWORD len;
181
182 // Try HKEY_CURRENT_USER registry key first
183 len = WXSIZEOF(tpath);
184 if (SHRegGetUSValue(wxT("Software\\VST"),
185 wxT("VSTPluginsPath"),
186 NULL,
187 tpath,
188 &len,
189 FALSE,
190 NULL,
191 0) == ERROR_SUCCESS)
192 {
193 tpath[len] = 0;
194 dpath[0] = 0;
195 ExpandEnvironmentStrings(tpath, dpath, WXSIZEOF(dpath));
196 pathList.push_back(dpath);
197 }
198
199 // Then try HKEY_LOCAL_MACHINE registry key
200 len = WXSIZEOF(tpath);
201 if (SHRegGetUSValue(wxT("Software\\VST"),
202 wxT("VSTPluginsPath"),
203 NULL,
204 tpath,
205 &len,
206 TRUE,
207 NULL,
208 0) == ERROR_SUCCESS)
209 {
210 tpath[len] = 0;
211 dpath[0] = 0;
212 ExpandEnvironmentStrings(tpath, dpath, WXSIZEOF(dpath));
213 pathList.push_back(dpath);
214 }
215
216 // Add the default path last
217 dpath[0] = 0;
218 ExpandEnvironmentStrings(wxT("%ProgramFiles%\\Steinberg\\VSTPlugins"),
219 dpath,
220 WXSIZEOF(dpath));
221 pathList.push_back(dpath);
222
223 dpath[0] = 0;
224 ExpandEnvironmentStrings(wxT("%COMMONPROGRAMFILES%\\VST2"),
225 dpath,
226 WXSIZEOF(dpath));
227 pathList.push_back(dpath);
228
229 // Recursively scan for all DLLs
230 pm.FindFilesInPathList(wxT("*.dll"), pathList, files, true);
231
232#else
233
234 // Nothing specified in the VST_PATH environment variable...provide defaults
235 if (vstpath.empty())
236 {
237 // We add this "non-default" one
238 pathList.push_back(wxT(LIBDIR) wxT("/vst"));
239
240 // These are the defaults used by other hosts
241 pathList.push_back(wxT("/usr/lib/vst"));
242 pathList.push_back(wxT("/usr/local/lib/vst"));
243 pathList.push_back(wxGetHomeDir() + wxFILE_SEP_PATH + wxT(".vst"));
244 }
245
246 // Recursively scan for all shared objects
247 pm.FindFilesInPathList(wxT("*.so"), pathList, files, true);
248
249#endif
250
251 return { files.begin(), files.end() };
252}
253
255 const PluginPath & path, TranslatableString &errMsg,
256 const RegistrationCallback &callback)
257{
258
259 VSTEffectBase effect(path);
260 if(effect.InitializePlugin())
261 {
262 auto effectIDs = effect.GetEffectIDs();
263 if(effectIDs.empty())
264 //Each VST plugin path in Audacity should have id(index) part in it
265 effectIDs.push_back(0);
266
267 for(auto id : effectIDs)
268 {
269 //Subsequent VSTEffect::Load may seem like overhead, but we need
270 //to initialize EffectDefinitionInterface part, which includes
271 //properly formatted plugin path
272 VSTEffectBase subeffect(wxString::Format("%s;%d", path, id));
273 subeffect.Load();
274 if(callback)
275 callback(this, &subeffect);
276 }
277 return effectIDs.size();
278 }
279 errMsg = XO("Could not load the library");
280 return 0;
281}
282
283std::unique_ptr<ComponentInterface>
285{
286 // Acquires a resource for the application.
287 // For us, the ID is simply the path to the effect
288 auto result = Factory::Call(path);
289 if (!result->InitializePlugin())
290 result.reset();
291 return result;
292}
293
295{
296 const auto modulePath = path.BeforeFirst(wxT(';'));
297 return wxFileName::FileExists(modulePath) || wxFileName::DirExists(modulePath);
298}
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 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.
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.
bool Load()
Definition: VSTWrapper.cpp:307