Audacity 3.2.0
LoadLV2.cpp
Go to the documentation of this file.
1/*!********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file LoadLV2.cpp
6
7 Audacity(R) is copyright (c) 1999-2008 Audacity Team.
8 License: GPL v2 or later. See License.txt.
9
10*******************************************************************//*******************************************************************/
16#include "LV2Wrapper.h"
17#include "PluginHost.h"
18#include "PluginInterface.h"
19#if defined(USE_LV2)
20
21#if defined(__GNUC__)
22#pragma GCC diagnostic ignored "-Wparentheses"
23#endif
24
25#include "LoadLV2.h"
26#include "ModuleManager.h"
27
28#include <cstdlib>
29#include <cstring>
30#include <iostream>
31
32#include <wx/dynlib.h>
33#include <wx/filename.h>
34#include <wx/log.h>
35#include <wx/utils.h>
36
37#include "Internat.h"
38#include "wxArrayStringEx.h"
39
40#include <unordered_map>
41
42// ============================================================================
43// Module registration entry point
44//
45// This is the symbol that Audacity looks for when the module is built as a
46// dynamic library.
47//
48// When the module is builtin to Audacity, we use the same function, but it is
49// declared static so as not to clash with other builtin modules.
50// ============================================================================
52{
53 // Create and register the importer
54 // Trust the module manager not to leak this
55 return std::make_unique<LV2EffectsModule>();
56}
57
58// ============================================================================
59// Register this as a builtin module
60// ============================================================================
61DECLARE_BUILTIN_PROVIDER(LV2sEffectBuiltin);
62
64//
65// LV2EffectsModule
66//
68using UriHash = std::unordered_map<wxString, LilvNode*>;
69
71{
72}
73
75{
76}
77
78// ============================================================================
79// ComponentInterface implementation
80// ============================================================================
81
83{
84 return {};
85}
86
88{
89 return XO("LV2 Effects");
90}
91
93{
94 return XO("The Audacity Team");
95}
96
98{
99 // This "may" be different if this were to be maintained as a separate DLL
100 return LV2EFFECTS_VERSION;
101}
102
104{
105 return XO("Provides LV2 Effects support to Audacity");
106}
107
108// ============================================================================
109// PluginProvider implementation
110// ============================================================================
111
113{
115 return false;
116
117 wxGetEnv(wxT("LV2_PATH"), &mStartupPathVar);
118
120 {
121 //Plugin validation process does not call `AutoRegisterPlugins`
122 //Register plugins from `LV2_PATH` here
123 lilv_world_load_all(LV2Symbols::gWorld);
124 }
125 return true;
126}
127
129{
131}
132
134{
135 return true;
136}
137
139{
140#if USE_LV2
141 return LV2EFFECTS_FAMILY;
142#else
143 return {};
144#endif
145}
146
148{
149 static FileExtensions empty;
150 return empty;
151}
152
154{
155 //Plugins aren't registered in PluginManager here, but
156 //instead we update `LV2_PATH` and run `lilv_world_load_all`
157 //to register bundles within LV2 module.
158
159 wxString newVar;
160
161#if defined(__WXMAC__)
162#define LV2PATH wxT("/Library/Audio/Plug-Ins/LV2")
163
164 wxFileName libdir;
165// libdir.AssignDir(wxT(LIBDIR));
166 libdir.AppendDir(wxT("lv2"));
167
168 newVar += wxT(":$HOME/.lv2");
169
170 // Look in ~/Library/Audio/Plug-Ins/lv2 and /Library/Audio/Plug-Ins/lv2
171 newVar += wxT(":$HOME") LV2PATH;
172 newVar += wxT(":") LV2PATH;
173
174 newVar += wxT(":/usr/local/lib/lv2");
175 newVar += wxT(":/usr/lib/lv2");
176 newVar += wxT(":") + libdir.GetPath();
177
178#elif defined(__WXMSW__)
179
180 newVar += wxT(";%APPDATA%\\LV2");
181 newVar += wxT(";%COMMONPROGRAMFILES%\\LV2");
182 newVar += wxT(";%COMMONPROGRAMFILES(x86)%\\LV2");
183
184#else
185
186 wxFileName libdir;
187 libdir.AssignDir(wxT(LIBDIR));
188 libdir.AppendDir(wxT("lv2"));
189
190 newVar += wxT(":$HOME/.lv2");
191#if defined(__LP64__)
192 newVar += wxT(":/usr/local/lib64/lv2");
193 newVar += wxT(":/usr/lib64/lv2");
194#endif
195 newVar += wxT(":/usr/local/lib/lv2");
196 newVar += wxT(":/usr/lib/lv2");
197 newVar += wxT(":") + libdir.GetPath();
198
199 // Tell SUIL where to find his GUI support modules
200 wxSetEnv(wxT("SUIL_MODULE_DIR"), wxT(PKGLIBDIR));
201#endif
202
203 {
204 auto customPaths = pluginManager.ReadCustomPaths(*this);
205 if(!customPaths.empty())
206 {
207 wxArrayString wxarr;
208 std::copy(customPaths.begin(), customPaths.end(), std::back_inserter(wxarr));
209 newVar += wxString::Format(";%s", wxJoin(wxarr, ';'));
210 }
211 }
212 // Start with the LV2_PATH environment variable (if any)
213 wxString pathVar = mStartupPathVar;
214 if (mStartupPathVar.empty())
215 pathVar = newVar.Mid(1);
216 else
217 pathVar += newVar;
218
219 wxSetEnv(wxT("LV2_PATH"), pathVar);
220 lilv_world_load_all(LV2Symbols::gWorld);
221}
222
224{
225 // Retrieve data about all LV2 plugins
226 const LilvPlugins *plugs = lilv_world_get_all_plugins(LV2Symbols::gWorld);
227
228 // Iterate over all plugins retrieve their URI
229 PluginPaths plugins;
230 LILV_FOREACH(plugins, i, plugs)
231 {
232 const LilvPlugin *plug = lilv_plugins_get(plugs, i);
233 const LilvNode *cls = lilv_plugin_class_get_uri(lilv_plugin_get_class(plug));
234 LilvNodePtr name{ lilv_plugin_get_name(plug) };
235
236 // Bypass unsupported plugin types
237 using namespace LV2Symbols;
238 if (lilv_node_equals(cls, node_InstrumentPlugin) ||
239 lilv_node_equals(cls, node_MIDIPlugin) ||
240 lilv_node_equals(cls, node_MathConstants) ||
241 lilv_node_equals(cls, node_MathFunctions))
242 {
243 wxLogInfo(wxT("LV2 plugin '%s' has unsupported type '%s'"), lilv_node_as_string(lilv_plugin_get_uri(plug)), lilv_node_as_string(cls));
244 continue;
245 }
246
247 // If it doesn't have a name or has no ports, then it's not valid
248 if (!name || !lilv_plugin_get_port_by_index(plug, 0))
249 {
250 wxLogInfo(wxT("LV2 plugin '%s' is invalid"), lilv_node_as_string(lilv_plugin_get_uri(plug)));
251 continue;
252 }
253
254 plugins.push_back(LilvString(lilv_plugin_get_uri(plug)));
255 }
256
257 return plugins;
258}
259
261 const PluginPath & path, TranslatableString &errMsg,
262 const RegistrationCallback &callback)
263{
264 errMsg = {};
265 if (const auto plug = GetPlugin(path)) {
266 LV2EffectBase effect(*plug);
267 if (effect.InitializePlugin()) {
268 if (callback)
269 callback( this, &effect );
270 return 1;
271 }
272 }
273
274 errMsg = XO("Could not load the library");
275 return 0;
276}
277
278std::unique_ptr<ComponentInterface>
280{
281 // Acquires a resource for the application.
282 if (const auto plug = GetPlugin(path)) {
283 auto result = Factory::Call(*plug);
284 result->InitializePlugin();
285 return result;
286 }
287 return nullptr;
288}
289
291{
292 return GetPlugin(path) != nullptr;
293}
294
295namespace {
297{
298public:
299 void Validate(ComponentInterface& pluginInterface) override
300 {
301 if(auto lv2effect = dynamic_cast<LV2EffectBase*>(&pluginInterface))
302 {
303 LV2_Atom_Forge forge;
304 lv2_atom_forge_init(&forge, lv2effect->mFeatures.URIDMapFeature());
305
306 LV2PortStates portStates { lv2effect->mPorts };
307 LV2InstanceFeaturesList instanceFeatures { lv2effect->mFeatures };
308
309 auto settings = lv2effect->MakeSettings();
310 auto wrapper = LV2Wrapper::Create(
311 instanceFeatures,
312 lv2effect->mPorts,
313 portStates,
315 44100.0,
316 nullptr);
317
318 if(!wrapper)
319 throw std::runtime_error("Cannot create LV2 instance");
320
321 }
322 else
323 throw std::runtime_error("Not a LV2Effect");
324 }
325};
326}
327
328std::unique_ptr<PluginProvider::Validator> LV2EffectsModule::MakeValidator() const
329{
330 return std::make_unique<LV2PluginValidator>();
331}
332
333// ============================================================================
334// LV2EffectsModule implementation
335// ============================================================================
336
337const LilvPlugin *LV2EffectsModule::GetPlugin(const PluginPath & path)
338{
339 using namespace LV2Symbols;
340 if (LilvNodePtr uri{ lilv_new_uri(gWorld, path.ToUTF8()) })
341 // lilv.h says returns from the following two functions don't need freeing
342 return lilv_plugins_get_by_uri(
343 lilv_world_get_all_plugins(gWorld), uri.get());
344 return nullptr;
345}
346
347#endif
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
#define LV2EFFECTS_FAMILY
Definition: LV2Effect.h:31
#define LV2EFFECTS_VERSION
Definition: LV2Effect.h:28
wxString LilvString(const LilvNode *node)
Definition: LV2Utils.h:37
Lilv_ptr< LilvNode, lilv_node_free > LilvNodePtr
Definition: LV2Utils.h:33
DECLARE_BUILTIN_PROVIDER(LV2sEffectBuiltin)
DECLARE_PROVIDER_ENTRY(AudacityModule)
Definition: LoadLV2.cpp:51
#define LV2PATH
std::unordered_map< wxString, LilvNode * > UriHash
Definition: LoadLV2.cpp:68
Defines the module to handle the LV2 effect protocol.
wxString name
Definition: TagsEditor.cpp:166
static Settings & settings()
Definition: TrackInfo.cpp:51
ComponentInterface provides name / vendor / version functions to identify plugins....
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
std::vector< LV2_Feature > mFeatures
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
bool InitializePlugin()
TranslatableString GetDescription() const override
Definition: LoadLV2.cpp:103
bool CheckPluginExist(const PluginPath &path) const override
Performs plugin/module existence check, still plugin may fail to load. Implementation should avoid lo...
Definition: LoadLV2.cpp:290
unsigned DiscoverPluginsAtPath(const PluginPath &path, TranslatableString &errMsg, const RegistrationCallback &callback) override
Definition: LoadLV2.cpp:260
virtual ~LV2EffectsModule()
Definition: LoadLV2.cpp:74
void Terminate() override
Called just prior to deletion to allow releasing any resources.
Definition: LoadLV2.cpp:128
void AutoRegisterPlugins(PluginManagerInterface &pm) override
Called so that a provider of a static set of plug-ins can register them.
Definition: LoadLV2.cpp:153
EffectFamilySymbol GetOptionalFamilySymbol() override
A symbol identifying the family of plug-ins provided by this.
Definition: LoadLV2.cpp:138
PluginPaths FindModulePaths(PluginManagerInterface &pm) override
Definition: LoadLV2.cpp:223
bool Initialize() override
Called immediately after creation. Let provider initialize.
Definition: LoadLV2.cpp:112
wxString GetVersion() const override
Definition: LoadLV2.cpp:97
bool SupportsCustomModulePaths() const override
Definition: LoadLV2.cpp:133
PluginPath GetPath() const override
Definition: LoadLV2.cpp:82
std::unique_ptr< Validator > MakeValidator() const override
Definition: LoadLV2.cpp:328
std::unique_ptr< ComponentInterface > LoadPlugin(const PluginPath &path) override
Load the plug-in at a path reported by DiscoverPluginsAtPath.
Definition: LoadLV2.cpp:279
const FileExtensions & GetFileExtensions() override
File types associated with this protocol.
Definition: LoadLV2.cpp:147
VendorSymbol GetVendor() const override
Definition: LoadLV2.cpp:92
wxString mStartupPathVar
Definition: LoadLV2.h:81
ComponentInterfaceSymbol GetSymbol() const override
Definition: LoadLV2.cpp:87
static const LilvPlugin * GetPlugin(const PluginPath &path)
Definition: LoadLV2.cpp:337
static std::unique_ptr< LV2Wrapper > Create(LV2InstanceFeaturesList &baseFeatures, const LV2Ports &ports, LV2PortStates &portStates, const LV2EffectSettings &settings, float sampleRate, EffectOutputs *pOutputs)
Factory.
Definition: LV2Wrapper.cpp:32
static bool IsHostProcess()
Returns true if current process is considered to be a plugin host process.
Definition: PluginHost.cpp:202
virtual PluginPaths ReadCustomPaths(const PluginProvider &provider)=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.
void Validate(ComponentInterface &pluginInterface) override
Definition: LoadLV2.cpp:299
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
void FinalizeGWorld()
Call at end of session.
Definition: LV2Symbols.cpp:71
URIDLIST bool InitializeGWorld()
Call before any use of the constants defined in this file.
Definition: LV2Symbols.cpp:48
LilvWorld * gWorld
Definition: LV2Symbols.cpp:31
DynamicRangeProcessorSettings GetSettings(EffectSettingsAccess &access)
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40