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