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