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