Audacity 3.2.0
LV2Effect.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 LV2Effect.cpp
6
7 Audacity(R) is copyright (c) 1999-2008 Audacity Team.
8 License: GPL v2 or later. See License.txt.
9
10**********************************************************************/
11
12#if defined(USE_LV2)
13
14#if defined(__GNUC__)
15#pragma GCC diagnostic ignored "-Wparentheses"
16#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
17#elif defined(__clang__)
18#pragma clang diagnostic ignored "-Wparentheses"
19#pragma clang diagnostic ignored "-Wdeprecated-declarations"
20#endif
21
22#include "LV2Effect.h"
23#include "LV2Instance.h"
24#include "LV2Validator.h"
25#include "LV2Wrapper.h"
26#include "SampleCount.h"
27
28#include <cmath>
29#include <exception>
30#include <functional>
31
32
33#ifdef __WXMAC__
34#include <wx/evtloop.h>
35#endif
36
37#include "ConfigInterface.h"
38#include "../../widgets/AudacityMessageBox.h"
39
40#if defined(__WXGTK__)
41#include <gtk/gtk.h>
42#endif
43
44#if defined(__WXMSW__)
45#include <wx/msw/wrapwin.h>
46#endif
47
49//
50// LV2Effect
51//
53
54LV2Effect::LV2Effect(const LilvPlugin &plug) : mPlug{ plug }
55{
56}
57
59{
60}
61
62// ============================================================================
63// ComponentInterface Implementation
64// ============================================================================
65
67{
68 return LilvString(lilv_plugin_get_uri(&mPlug));
69}
70
72{
74}
75
77{
78 wxString vendor = LilvStringMove(lilv_plugin_get_author_name(&mPlug));
79
80 if (vendor.empty())
81 {
82 return XO("n/a");
83 }
84
85 return {vendor};
86}
87
88wxString LV2Effect::GetVersion() const
89{
90 return wxT("1.0");
91}
92
94{
95 return XO("n/a");
96}
97
98// ============================================================================
99// EffectDefinitionInterface Implementation
100// ============================================================================
101
103{
104 if (mPorts.mAudioIn == 0 && mPorts.mAudioOut == 0)
105 {
106 return EffectTypeTool;
107 }
108
109 if (mPorts.mAudioIn == 0)
110 {
111 return EffectTypeGenerate;
112 }
113
114 if (mPorts.mAudioOut == 0)
115 {
116 return EffectTypeAnalyze;
117 }
118
119 return EffectTypeProcess;
120}
121
123{
124 return LV2EFFECTS_FAMILY;
125}
126
128{
129 return mPorts.mControlPorts.size() != 0;
130}
131
133{
134 return false;
135}
136
138{
139 // TODO reenable after achieving statelessness
140 return GetType() == EffectTypeProcess
143}
144
146{
147 return true;
148}
149
151{
152 if (!mFeatures.mOk)
153 return false;
154
155 // Do a check only on temporary feature list objects
156 auto instanceFeatures = LV2InstanceFeaturesList{ mFeatures };
157 if (!instanceFeatures.mOk)
158 return false;
159 if (!LV2UIFeaturesList{ LV2WrapperFeaturesList{instanceFeatures},
160 nullptr, lilv_plugin_get_uri(&mPlug)
161 }.mOk)
162 return false;
163
164 // Determine available extensions
166 mWantsStateInterface = false;
167 if (LilvNodesPtr extdata{ lilv_plugin_get_extension_data(&mPlug) }) {
168 LILV_FOREACH(nodes, i, extdata.get()) {
169 const auto node = lilv_nodes_get(extdata.get(), i);
170 const auto uri = lilv_node_as_string(node);
171 if (strcmp(uri, LV2_OPTIONS__interface) == 0)
173 else if (strcmp(uri, LV2_STATE__interface) == 0)
175 }
176 }
177
178 return true;
179}
180
182{
183 auto result = EffectSettings::Make<LV2EffectSettings>();
184 auto &settings = GetSettings(result);
185 settings.values.reserve(mPorts.mControlPorts.size());
186 for (auto &controlPort : mPorts.mControlPorts) {
187 auto &value = settings.values.emplace_back();
188 value = controlPort->mDef;
189 }
190 return result;
191}
192
194 const EffectSettings &src, EffectSettings &dst,
195 SettingsCopyDirection copyDirection) const
196{
197 auto &srcControls = GetSettings(src).values;
198 auto &dstControls = GetSettings(dst).values;
199
200 const auto &controlPorts = mPorts.mControlPorts;
201 const auto portsCount = controlPorts.size();
202 // Do not use the copy constructor of std::vector. Do an in-place rewrite
203 // of the destination vector, which will not allocate memory if dstControls
204 // began with sufficient capacity.
205 // And that will be true if dstControls originated with MakeSettings() or a
206 // copy of it, because the set of control ports does not vary after
207 // initialization of the plug-in.
208 assert(srcControls.size() == portsCount);
209 assert(dstControls.size() == portsCount);
210 // But let's be sure
211 const auto portValuesCount =
212 std::min(srcControls.size(), dstControls.size());
213
214 if (portValuesCount != portsCount)
215 return false;
216
217 const auto copyOutputs = copyDirection == SettingsCopyDirection::WorkerToMain;
218
219 size_t portIndex {};
220
221 for (auto& port : controlPorts)
222 {
223 if (port->mIsInput || copyOutputs)
224 dstControls[portIndex] = srcControls[portIndex];
225
226 ++portIndex;
227 }
228
229 // Ignore mpState
230
231 return true;
232}
233
234std::shared_ptr<EffectInstance> LV2Effect::MakeInstance() const
235{
236 auto result = std::make_shared<LV2Instance>(*this, mFeatures, mPorts);
237 if (result->IsOk())
238 return result;
239 return nullptr;
240}
241
242int LV2Effect::ShowClientInterface(wxWindow &parent, wxDialog &dialog,
243 EffectUIValidator *pValidator, bool forceModal)
244{
245 if (pValidator)
246 // Remember the dialog with a weak pointer, but don't control its lifetime
247 static_cast<LV2Validator*>(pValidator)->mDialog = &dialog;
248 // Try to give the window a sensible default/minimum size
249 dialog.Layout();
250 dialog.Fit();
251 dialog.SetMinSize(dialog.GetSize());
253 dialog.SetMaxSize(dialog.GetSize());
254 if ((SupportsRealtime() || GetType() == EffectTypeAnalyze) && !forceModal) {
255 dialog.Show();
256 return 0;
257 }
258 return dialog.ShowModal();
259}
260
262 const EffectSettings &settings, CommandParameters & parms) const
263{
265 size_t index = 0;
266 for (auto & port : mPorts.mControlPorts) {
267 if (port->mIsInput)
268 if (!parms.Write(port->mName, values[index]))
269 return false;
270 ++index;
271 }
272 return true;
273}
274
276 const CommandParameters & parms, EffectSettings &settings) const
277{
278 // First pass validates values
279 for (auto & port : mPorts.mControlPorts) {
280 if (port->mIsInput) {
281 double d = 0.0;
282 if (!parms.Read(port->mName, &d))
283 return false;
284 // Use unscaled range here
285 if (d < port->mMin || d > port->mMax)
286 return false;
287 }
288 }
289
290 // Second pass actually sets the values
292 size_t index = 0;
293 for (auto & port : mPorts.mControlPorts) {
294 if (port->mIsInput) {
295 double d = 0.0;
296 if (!parms.Read(port->mName, &d))
297 return false;
298 values[index] = d;
299 }
300 ++index;
301 }
302
303 return true;
304}
305
306// ============================================================================
307// EffectUIClientInterface Implementation
308// ============================================================================
309
310// May come here before destructive processing
311// Or maybe not (if you "Repeat Last Effect")
312std::unique_ptr<EffectUIValidator> LV2Effect::PopulateUI(ShuttleGui &S,
313 EffectInstance &instance, EffectSettingsAccess &access)
314{
315 auto &settings = access.Get();
316 auto parent = S.GetParent();
317 mParent = parent;
318
319 auto &myInstance = dynamic_cast<LV2Instance &>(instance);
320 auto pWrapper =
321 myInstance.MakeWrapper(settings, mProjectRate, true);
322 if (!pWrapper) {
323 AudacityMessageBox( XO("Couldn't instantiate effect") );
324 return nullptr;
325 }
326
327 // Determine if the GUI editor is supposed to be used or not
328 bool useGUI = false;
329 LV2Preferences::GetUseGUI(*this, useGUI);
330
331 // Until I figure out where to put the "Duration" control in the
332 // graphical editor, force usage of plain editor.
334 useGUI = false;
335
336 auto result = std::make_unique<LV2Validator>(*this, mPlug,
337 dynamic_cast<LV2Instance&>(instance),
338 access, mProjectRate, mFeatures, mPorts, parent, useGUI);
339
340 if (result->mUseGUI)
341 result->mUseGUI = result->BuildFancy(move(pWrapper), settings);
342 if (!result->mUseGUI && !result->BuildPlain(access))
343 return nullptr;
344 result->UpdateUI();
345
346 return result;
347}
348
350{
351#ifdef __WXMAC__
352#ifdef __WX_EVTLOOP_BUSY_WAITING__
353 wxEventLoop::SetBusyWaiting(false);
354#endif
355#endif
356
357 mParent = nullptr;
358 return true;
359}
360
363{
365}
366
368 const RegistryPath &name, const EffectSettings &settings) const
369{
371}
372
374{
375 using namespace LV2Symbols;
377 return mFactoryPresetNames;
378
379 if (LilvNodesPtr presets{ lilv_plugin_get_related(&mPlug, node_Preset) }) {
380 LILV_FOREACH(nodes, i, presets.get()) {
381 const auto preset = lilv_nodes_get(presets.get(), i);
382
384
385 lilv_world_load_resource(gWorld, preset);
386
387 if (LilvNodesPtr labels{ lilv_world_find_nodes(gWorld, preset,
388 node_Label, nullptr) }) {
389 const auto label = lilv_nodes_get_first(labels.get());
391 }
392 else
393 mFactoryPresetNames.push_back(
394 LilvString(preset).AfterLast(wxT('#')));
395 }
396 }
397
399
400 return mFactoryPresetNames;
401}
402
404{
405 using namespace LV2Symbols;
406 if (id < 0 || id >= (int) mFactoryPresetUris.size())
407 return false;
408
409 LilvNodePtr preset{ lilv_new_uri(gWorld, mFactoryPresetUris[id].ToUTF8()) };
410 if (!preset)
411 return false;
412
413 using LilvStatePtr = Lilv_ptr<LilvState, lilv_state_free>;
414 if (LilvStatePtr state{
415 lilv_state_new_from_world(gWorld,
417 }){
418 auto &mySettings = GetSettings(settings);
419 mPorts.EmitPortValues(*state, mySettings);
420 // Save the state, for whatever might not be contained in port values
421 mySettings.mpState = move(state);
422 return true;
423 }
424 else
425 return false;
426}
427
429{
430 return false;
431}
432
434{
435}
436
438{
439}
440
442{
443 return true;
444}
445
447{
448 LV2Preferences::Dialog{ mParent, *this }.ShowModal();
449}
450
451// ============================================================================
452// LV2Effect Implementation
453// ============================================================================
454
456 const RegistryPath &group, EffectSettings &settings) const
457{
458 wxString parms;
459 if (!GetConfig(*this,
460 PluginSettings::Private, group, wxT("Parameters"), parms, wxEmptyString))
461 return false;
463 if (!eap.SetParameters(parms))
464 return false;
465 return LoadSettings(eap, settings);
466}
467
469 const RegistryPath &group, const EffectSettings &settings) const
470{
471 // PRL: This function just dumps the several control port values to the
472 // config files. Should it be reimplemented with
473 // lilv_state_new_from_instance to capture -- I don't know what -- other
474 // important state?
475
477 if (!SaveSettings(settings, eap))
478 return false;
479
480 wxString parms;
481 if (!eap.GetParameters(parms))
482 return false;
483
484 return SetConfig(*this,
485 PluginSettings::Private, group, wxT("Parameters"), parms);
486}
487#endif
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
int min(int a, int b)
const TranslatableString name
Definition: Distortion.cpp:82
EffectType
@ EffectTypeAnalyze
@ EffectTypeGenerate
@ EffectTypeTool
@ EffectTypeProcess
SettingsCopyDirection
Direction in which settings are copied.
@ WorkerToMain
Worker thread settings replicated to main thread.
const wxChar * values
wxString RegistryPath
Definition: Identifier.h:218
wxString PluginPath
type alias for identifying a Plugin supplied by a module, each module defining its own interpretation...
Definition: Identifier.h:214
std::vector< RegistryPath > RegistryPaths
Definition: Identifier.h:219
#define XO(s)
Definition: Internat.h:31
#define LV2EFFECTS_FAMILY
Definition: LV2Effect.h:32
Lilv_ptr< LilvNodes, lilv_nodes_free > LilvNodesPtr
LV2EffectSettings & GetSettings(EffectSettings &settings)
Definition: LV2Ports.h:215
wxString LilvString(const LilvNode *node)
Definition: LV2Utils.h:37
std::unique_ptr< Type, Lilv_deleter< Type, f > > Lilv_ptr
Generate classes of smart pointers to lv2 resources.
Definition: LV2Utils.h:26
wxString LilvStringMove(LilvNode *node)
Definition: LV2Utils.h:45
Lilv_ptr< LilvNode, lilv_node_free > LilvNodePtr
Definition: LV2Utils.h:33
EffectReverbSettings preset
Definition: Reverb.cpp:46
TranslatableString label
Definition: TagsEditor.cpp:163
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:87
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the SettingsVis...
bool GetParameters(wxString &parms)
bool SetParameters(const wxString &parms)
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
double mProjectRate
Definition: EffectBase.h:99
RealtimeSince
In which versions of Audacity was an effect realtime capable?
Performs effect computation.
virtual const EffectSettings & Get()=0
Interface for transferring values from a panel of effect controls.
virtual ~LV2Effect()
Definition: LV2Effect.cpp:58
VendorSymbol GetVendor() const override
Definition: LV2Effect.cpp:76
std::unique_ptr< EffectUIValidator > PopulateUI(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access) override
Adds controls to a panel that is given as the parent window of S
Definition: LV2Effect.cpp:312
bool mFactoryPresetsLoaded
Definition: LV2Effect.h:127
PluginPath GetPath() const override
Definition: LV2Effect.cpp:66
int ShowClientInterface(wxWindow &parent, wxDialog &dialog, EffectUIValidator *pValidator, bool forceModal) override
Definition: LV2Effect.cpp:242
RegistryPaths GetFactoryPresets() const override
Report names of factory presets.
Definition: LV2Effect.cpp:373
bool SupportsAutomation() const override
Whether the effect has any automatable controls.
Definition: LV2Effect.cpp:145
RealtimeSince RealtimeSupport() const override
Since which version of Audacity has the effect supported realtime?
Definition: LV2Effect.cpp:137
EffectFamilySymbol GetFamily() const override
Report identifier and user-visible name of the effect protocol.
Definition: LV2Effect.cpp:122
void ExportPresets(const EffectSettings &settings) const override
Definition: LV2Effect.cpp:433
bool LoadParameters(const RegistryPath &group, EffectSettings &settings) const
Definition: LV2Effect.cpp:455
void ShowOptions() override
Definition: LV2Effect.cpp:446
bool HasOptions() override
Definition: LV2Effect.cpp:441
bool SaveParameters(const RegistryPath &group, const EffectSettings &settings) const
Definition: LV2Effect.cpp:468
bool InitializePlugin()
Definition: LV2Effect.cpp:150
RegistryPaths mFactoryPresetNames
Definition: LV2Effect.h:128
EffectSettings MakeSettings() const override
Definition: LV2Effect.cpp:181
bool mWantsStateInterface
Definition: LV2Effect.h:115
void ImportPresets(EffectSettings &settings) override
Definition: LV2Effect.cpp:437
bool LoadFactoryPreset(int id, EffectSettings &settings) const override
Change settings to the preset whose name is GetFactoryPresets()[id]
Definition: LV2Effect.cpp:403
bool SaveSettings(const EffectSettings &settings, CommandParameters &parms) const override
Store settings as keys and values.
Definition: LV2Effect.cpp:261
LV2Effect(const LilvPlugin &plug)
Definition: LV2Effect.cpp:54
bool CloseUI() override
Definition: LV2Effect.cpp:349
EffectType GetType() const override
Type determines how it behaves.
Definition: LV2Effect.cpp:102
wxString GetVersion() const override
Definition: LV2Effect.cpp:88
wxArrayString mFactoryPresetUris
Definition: LV2Effect.h:129
bool mWantsOptionsInterface
Definition: LV2Effect.h:114
const LV2Ports mPorts
Definition: LV2Effect.h:112
ComponentInterfaceSymbol GetSymbol() const override
Definition: LV2Effect.cpp:71
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
Definition: LV2Effect.cpp:275
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
Definition: LV2Effect.cpp:234
bool IsInteractive() const override
Whether the effect needs a dialog for entry of settings.
Definition: LV2Effect.cpp:127
const LV2FeaturesList mFeatures
Definition: LV2Effect.h:110
bool CanExportPresets() override
Definition: LV2Effect.cpp:428
bool LoadUserPreset(const RegistryPath &name, EffectSettings &settings) const override
Change settings to a user-named preset.
Definition: LV2Effect.cpp:361
TranslatableString GetDescription() const override
Definition: LV2Effect.cpp:93
bool SaveUserPreset(const RegistryPath &name, const EffectSettings &settings) const override
Save settings in the configuration file as a user-named preset.
Definition: LV2Effect.cpp:367
wxWindow * mParent
Definition: LV2Effect.h:124
bool CopySettingsContents(const EffectSettings &src, EffectSettings &dst, SettingsCopyDirection copyDirection) const override
Update one settings object from another.
Definition: LV2Effect.cpp:193
bool IsDefault() const override
Whether the effect sorts "above the line" in the menus.
Definition: LV2Effect.cpp:132
const LilvPlugin & mPlug
Definition: LV2Effect.h:109
LV2_URID_Map * URIDMapFeature() const
static ComponentInterfaceSymbol GetPluginSymbol(const LilvPlugin &plug)
std::unique_ptr< LV2Wrapper > MakeWrapper(const EffectSettings &settings, double sampleRate, bool useOutput)
Definition: LV2Instance.cpp:57
void EmitPortValues(const LilvState &state, LV2EffectSettings &settings) const
Definition: LV2Ports.cpp:395
unsigned mAudioOut
Definition: LV2Ports.h:264
unsigned mAudioIn
Definition: LV2Ports.h:263
LV2ControlPortArray mControlPorts
Definition: LV2Ports.h:274
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
Holds a msgid for the translation catalog; may also bind format arguments.
bool GetUseGUI(const EffectDefinitionInterface &effect, bool &useGUI)
LilvWorld * gWorld
Definition: LV2Symbols.cpp:31
bool SetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, const Value &value)
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
std::string ToUTF8(const std::wstring &wstr)
Externalized state of a plug-in.
std::vector< float > values
vector of values in correspondence with the control ports
Definition: LV2Ports.h:208