Audacity 3.2.0
LadspaEditor.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 LadspaEditor.cpp
6
7 Dominic Mazzoni
8
9 Paul Licameli split from LadspaEffect.cpp
10
11*//*******************************************************************/
12#include "LadspaEditor.h"
13
14#include <float.h>
15#include <wx/checkbox.h>
16#include <wx/dcclient.h>
17#include <wx/sizer.h>
18#include <wx/stattext.h>
19#include <wx/textctrl.h>
20#include <wx/scrolwin.h>
21#include "ShuttleGui.h"
22#include "../../widgets/NumericTextCtrl.h"
23#include "../../widgets/valnum.h"
24
25#if wxUSE_ACCESSIBILITY
26#include "WindowAccessible.h"
27#endif
28
29// ============================================================================
30// Tolerance to be used when comparing control values.
31constexpr float ControlValueTolerance = 1.0e-5f;
32// ============================================================================
33
34enum
35{
36 ID_Duration = 20000,
37 ID_Toggles = 21000,
38 ID_Sliders = 22000,
39 ID_Texts = 23000,
40};
41
43//
44// LadspaEffectMeter
45//
47
48class LadspaEffectMeter final : public wxWindow
49{
50public:
51 LadspaEffectMeter(wxWindow *parent, const float & val, float min, float max);
52
54 {
55 // Stop using mVal, it might be dangling now
56 mConnected = false;
57 }
58
59 virtual ~LadspaEffectMeter();
60
61private:
62 void OnErase(wxEraseEvent & evt);
63 void OnPaint(wxPaintEvent & evt);
64 void OnIdle(wxIdleEvent & evt);
65 void OnSize(wxSizeEvent & evt);
66
67private:
68 bool mConnected{ true };
69 const float & mVal;
70 float mMin;
71 float mMax;
73
74 DECLARE_EVENT_TABLE()
75};
76
77BEGIN_EVENT_TABLE(LadspaEffectMeter, wxWindow)
79 EVT_ERASE_BACKGROUND(LadspaEffectMeter::OnErase)
83
84LadspaEffectMeter::LadspaEffectMeter(wxWindow *parent, const float & val, float min, float max)
85: wxWindow{ parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
86 wxSIMPLE_BORDER },
87 mVal(val)
88{
89 mMin = min;
90 mMax = max;
91 mLastValue = -mVal;
92 SetBackgroundColour(*wxWHITE);
93 SetMinSize({ 20, 20 });
94}
95
97{
98}
99
100void LadspaEffectMeter::OnIdle(wxIdleEvent &evt)
101{
102 evt.Skip();
103 if (!mConnected)
104 return;
105 if (mLastValue != mVal)
106 Refresh(false);
107}
108
109void LadspaEffectMeter::OnErase(wxEraseEvent & WXUNUSED(evt))
110{
111 // Just ignore it to prevent flashing
112}
113
114void LadspaEffectMeter::OnPaint(wxPaintEvent & WXUNUSED(evt))
115{
116 if (!mConnected)
117 return;
118
119 wxPaintDC dc(this);
120
121 // Cache some metrics
122 wxRect r = GetClientRect();
123 wxCoord x = r.GetLeft();
124 wxCoord y = r.GetTop();
125 wxCoord w = r.GetWidth();
126 wxCoord h = r.GetHeight();
127
128 // These use unscaled value, min, and max
129 float val = mVal;
130 if (val > mMax)
131 val = mMax;
132 if (val < mMin)
133 val = mMin;
134 val -= mMin;
135
136 // Setup for erasing the background
137 dc.SetPen(*wxTRANSPARENT_PEN);
138 dc.SetBrush(wxColour(100, 100, 220));
139 dc.Clear();
140 dc.DrawRectangle(x, y, (w * (val / fabs(mMax - mMin))), h);
141
143}
144
145void LadspaEffectMeter::OnSize(wxSizeEvent & WXUNUSED(evt))
146{
147 Refresh(false);
148}
149
151{
153 return true;
154}
155
157{
158 auto &controls = mSettings.controls;
159 auto parent = S.GetParent();
160
161 mParent = parent;
162
163 const auto &data = *mInstance.mData;
164 mToggles.reinit( data.PortCount );
165 mSliders.reinit( data.PortCount );
166 mFields.reinit( data.PortCount, true);
167 mLabels.reinit( data.PortCount );
168 mMeters.resize( data.PortCount );
169
170 wxASSERT(mParent); // To justify safenew
171 wxScrolledWindow *const w = safenew wxScrolledWindow(mParent,
172 wxID_ANY,
173 wxDefaultPosition,
174 wxDefaultSize,
175 wxVSCROLL | wxTAB_TRAVERSAL);
176
177 {
178 auto mainSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
179 w->SetScrollRate(0, 20);
180
181 // This fools NVDA into not saying "Panel" when the dialog gets focus
182 w->SetName(wxT("\a"));
183 w->SetLabel(wxT("\a"));
184
185 mainSizer->Add(w, 1, wxEXPAND);
186 mParent->SetSizer(mainSizer.release());
187 }
188
189 wxSizer *marginSizer;
190 {
191 auto uMarginSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
192 marginSizer = uMarginSizer.get();
193
194 // Make user-adjustible input controls
195 if (mNumInputControls) {
196 auto paramSizer = std::make_unique<wxStaticBoxSizer>(wxVERTICAL, w, _("Effect Settings"));
197
198 auto gridSizer = std::make_unique<wxFlexGridSizer>(5, 0, 0);
199 gridSizer->AddGrowableCol(3);
200
201 wxControl *item;
202
203 // Add the duration control for generators
204 if (mType == EffectTypeGenerate) {
205 item = safenew wxStaticText(w, 0, _("Duration:"));
206 gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
207 auto &extra = mAccess.Get().extra;
210 w, ID_Duration,
212 extra.GetDurationFormat(),
213 extra.GetDuration(),
215 .AutoPos(true));
216 mDuration->SetName( XO("Duration") );
217 gridSizer->Add(mDuration, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
218 gridSizer->Add(1, 1, 0);
219 gridSizer->Add(1, 1, 0);
220 gridSizer->Add(1, 1, 0);
221 }
222
223 for (unsigned long p = 0; p < data.PortCount; ++p) {
224 LADSPA_PortDescriptor d = data.PortDescriptors[p];
226 {
227 continue;
228 }
229
230 wxString labelText = LAT1CTOWX(data.PortNames[p]);
231 item = safenew wxStaticText(w, 0, wxString::Format(_("%s:"), labelText));
232 gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
233
234 wxString fieldText;
235 LADSPA_PortRangeHint hint = data.PortRangeHints[p];
236
238 mToggles[p] = safenew wxCheckBox(w, ID_Toggles + p, wxT(""));
239 mToggles[p]->SetName(labelText);
240 mToggles[p]->SetValue(controls[p] > 0);
241 BindTo(*mToggles[p],
242 wxEVT_COMMAND_CHECKBOX_CLICKED, &LadspaEditor::OnCheckBox);
243 gridSizer->Add(mToggles[p], 0, wxALL, 5);
244
245 gridSizer->Add(1, 1, 0);
246 gridSizer->Add(1, 1, 0);
247 gridSizer->Add(1, 1, 0);
248 continue;
249 }
250
251 wxString bound;
252 float lower = -FLT_MAX;
253 float upper = FLT_MAX;
254 bool haslo = false;
255 bool hashi = false;
256 bool forceint = false;
257
259 lower = hint.LowerBound;
260 haslo = true;
261 }
262
264 upper = hint.UpperBound;
265 hashi = true;
266 }
267
269 lower *= mSampleRate;
270 upper *= mSampleRate;
271 forceint = true;
272 }
273
274 // Limit to the UI precision
275 lower = ceilf(lower * 1000000.0) / 1000000.0;
276 upper = floorf(upper * 1000000.0) / 1000000.0;
277 controls[p] = roundf(controls[p] * 1000000.0) / 1000000.0;
278
279 if (haslo && controls[p] < lower)
280 controls[p] = lower;
281
282 if (hashi && controls[p] > upper)
283 controls[p] = upper;
284
285 // Don't specify a value at creation time. This prevents unwanted events
286 // being sent to the OnTextCtrl() handler before the associated slider
287 // has been created.
288 mFields[p] = safenew wxTextCtrl(w, ID_Texts + p);
289 mFields[p]->SetName(labelText);
290 BindTo(*mFields[p],
292 gridSizer->Add(mFields[p], 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
293
294 wxString str;
295 if (haslo) {
296 if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
297 {
298 str.Printf(wxT("%d"), (int)(lower + 0.5));
299 }
300 else
301 {
303 }
304 item = safenew wxStaticText(w, 0, str);
305 gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
306 }
307 else
308 gridSizer->Add(1, 1, 0);
309
311 0, 0, 1000,
312 wxDefaultPosition,
313 wxSize(200, -1));
314#if wxUSE_ACCESSIBILITY
315 // so that name can be set on a standard control
316 mSliders[p]->SetAccessible(safenew WindowAccessible(mSliders[p]));
317#endif
318 mSliders[p]->SetName(labelText);
319 BindTo(*mSliders[p],
320 wxEVT_COMMAND_SLIDER_UPDATED, &LadspaEditor::OnSlider);
321 gridSizer->Add(mSliders[p], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5);
322
323 if (hashi) {
324 if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
325 str.Printf(wxT("%d"), (int)(upper + 0.5));
326 else
328 item = safenew wxStaticText(w, 0, str);
329 gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 5);
330 }
331 else
332 gridSizer->Add(1, 1, 0);
333
334 if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint) {
335 fieldText.Printf(wxT("%d"), (int)(controls[p] + 0.5));
336
337 IntegerValidator<float> vld(&controls[p]);
338 vld.SetRange(haslo ? lower : INT_MIN,
339 hashi ? upper : INT_MAX);
340 mFields[p]->SetValidator(vld);
341 }
342 else {
343 fieldText = Internat::ToDisplayString(controls[p]);
344
345 // > 12 decimal places can cause rounding errors in display.
346 FloatingPointValidator<float> vld(6, &controls[p]);
347 vld.SetRange(lower, upper);
348
349 // Set number of decimal places
350 if (upper - lower < 10.0)
351 vld.SetStyle(NumValidatorStyle::THREE_TRAILING_ZEROES);
352 else if (upper - lower < 100.0)
353 vld.SetStyle(NumValidatorStyle::TWO_TRAILING_ZEROES);
354 else
355 vld.SetStyle(NumValidatorStyle::ONE_TRAILING_ZERO);
356
357 mFields[p]->SetValidator(vld);
358 }
359
360 // Set the textctrl value. This will trigger an event so OnTextCtrl()
361 // can update the slider.
362 mFields[p]->SetValue(fieldText);
363 }
364
365 paramSizer->Add(gridSizer.release(), 0, wxEXPAND | wxALL, 5);
366 marginSizer->Add(paramSizer.release(), 0, wxEXPAND | wxALL, 5);
367 }
368
369 // Make output meters
370 if (mNumOutputControls > 0) {
371 auto paramSizer = std::make_unique<wxStaticBoxSizer>(wxVERTICAL, w, _("Effect Output"));
372
373 auto gridSizer = std::make_unique<wxFlexGridSizer>(2, 0, 0);
374 gridSizer->AddGrowableCol(1);
375
376 wxControl *item;
377
378 for (unsigned long p = 0; p < data.PortCount; ++p) {
379 LADSPA_PortDescriptor d = data.PortDescriptors[p];
381 continue;
382
383 wxString labelText = LAT1CTOWX(data.PortNames[p]);
384 item = safenew wxStaticText(
385 w, 0, wxString::Format(_("%s:"), labelText));
386 gridSizer->Add(
387 item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
388
389 //LADSPA_PortRangeHint hint = data.PortRangeHints[p];
390
391 wxString bound;
392 float lower = 0.0;
393 float upper = 1.0;
394
395 // Limit to the UI precision
396 lower = ceilf(lower * 1000000.0) / 1000000.0;
397 upper = floorf(upper * 1000000.0) / 1000000.0;
398 controls[p] = lower;
399
400 // Capture const reference to output control value for later
401 // display update
402 static float sink;
403 auto pOutput = mpOutputs ? &mpOutputs->controls[p] : &sink;
405 w, *pOutput, lower, upper);
406 mMeters[p]->SetLabel(labelText); // for screen readers
407 gridSizer->Add(mMeters[p], 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 5);
408 }
409
410 paramSizer->Add(gridSizer.release(), 0, wxEXPAND | wxALL, 5);
411 marginSizer->Add(paramSizer.release(), 0, wxEXPAND | wxALL, 5);
412 }
413
414 w->SetSizer(uMarginSizer.release());
415 }
416
417 w->Layout();
418
419 // Try to give the window a sensible default/minimum size
420 wxSize sz1 = marginSizer->GetMinSize();
421 wxSize sz2 = mParent->GetMinSize();
422 w->SetMinSize( { std::min(sz1.x, sz2.x), std::min(sz1.y, sz2.y) } );
423
424 // And let the parent reduce to the NEW minimum if possible
425 mParent->SetMinSize({ -1, -1 });
426}
427
429 const LadspaInstance &instance,
430 unsigned numInputControls, unsigned numOutputControls,
431 EffectSettingsAccess &access, double sampleRate, EffectType type,
432 const LadspaEffectOutputs *pOutputs
433) : EffectEditor{ effect, access }
434 , mInstance{ instance }
435 , mNumInputControls{ numInputControls }
436 , mNumOutputControls{ numOutputControls }
437 , mSampleRate{ sampleRate }
438 , mType{ type }
439 // Copy settings
440 , mSettings{ GetSettings(access.Get()) }
441 , mpOutputs{ pOutputs }
442{}
443
445{
448 settings.extra.SetDuration(mDuration->GetValue());
450 return nullptr;
451 });
452 return true;
453}
454
456{
457 for (auto &meter : mMeters)
458 if (meter) {
459 meter->Disconnect();
460 meter = nullptr;
461 }
462}
463
464void LadspaEditor::OnCheckBox(wxCommandEvent & evt)
465{
466 int p = evt.GetId() - ID_Toggles;
467 // 0.5 is a half of the interval
468 UpdateControl(p, mToggles[p]->GetValue(), 0.5f);
469 ValidateUI();
470}
471
472void LadspaEditor::OnSlider(wxCommandEvent & evt)
473{
474 int p = evt.GetId() - ID_Sliders;
475
476 float val;
477 float lower = float(0.0);
478 float upper = float(10.0);
479 float range;
480 bool forceint = false;
481
484 lower = hint.LowerBound;
486 upper = hint.UpperBound;
488 lower *= mSampleRate;
489 upper *= mSampleRate;
490 forceint = true;
491 }
492
493 range = upper - lower;
494 val = (mSliders[p]->GetValue() / 1000.0) * range + lower;
495 wxString str;
496 if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
497 str.Printf(wxT("%d"), (int)(val + 0.5));
498 else
500
501 mFields[p]->SetValue(str);
502
504 ValidateUI();
505}
506
507void LadspaEditor::OnTextCtrl(wxCommandEvent & evt)
508{
509 int p = evt.GetId() - ID_Texts;
510
511 float val;
512 float lower = float(0.0);
513 float upper = float(10.0);
514 float range;
515
516 val = Internat::CompatibleToDouble(mFields[p]->GetValue());
517
520 lower = hint.LowerBound;
522 upper = hint.UpperBound;
524 lower *= mSampleRate;
525 upper *= mSampleRate;
526 }
527 range = upper - lower;
528 if (val < lower)
529 val = lower;
530 if (val > upper)
531 val = upper;
532
533 mSliders[p]->SetValue((int)(((val-lower)/range) * 1000.0 + 0.5));
534
536 ValidateUI();
537}
538
540{
541 if (!mParent)
542 return;
543
544 // Copy from the dialog
546
547 auto& controls = mSettings.controls;
548
549 const auto &data = *mInstance.mData;
550 for (unsigned long p = 0; p < data.PortCount; ++p) {
552 if (!(LADSPA_IS_PORT_CONTROL(d)))
553 continue;
554
555 wxString fieldText;
556 LADSPA_PortRangeHint hint = data.PortRangeHints[p];
557
558 bool forceint = false;
560 forceint = true;
561
563 continue;
564
566 mToggles[p]->SetValue(controls[p] > 0);
567 continue;
568 }
569
570 if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
571 fieldText.Printf(wxT("%d"), (int)(controls[p] + 0.5));
572 else
573 fieldText = Internat::ToDisplayString(controls[p]);
574
575 // Set the textctrl value. This will trigger an event so OnTextCtrl()
576 // can update the slider.
577 mFields[p]->SetValue(fieldText);
578 }
579}
580
581void LadspaEditor::UpdateControl(int index, float value, float epsilon)
582{
583 auto& controls = mSettings.controls;
584
585 assert(index < static_cast<int>(controls.size()));
586
587 if (std::abs(controls[index] - value) < epsilon)
588 return;
589
590 controls[index] = value;
591 Publish({ size_t(index), value });
592}
593
595{
596 const auto& data = *mInstance.mData;
597
598 for (size_t portIndex = 0, portsCount = src.controls.size();
599 portIndex < portsCount;
600 ++portIndex)
601 {
602 LADSPA_PortDescriptor d = data.PortDescriptors[portIndex];
603
605 continue;
606
608
609 const bool isIntValue = (LADSPA_IS_HINT_TOGGLED(hint.HintDescriptor)) ||
612
614 portIndex, src.controls[portIndex],
615 isIntValue ? 0.5f : ControlValueTolerance);
616 }
617}
wxT("CloseDown"))
END_EVENT_TABLE()
int min(int a, int b)
#define str(a)
EffectType
@ EffectTypeGenerate
XO("Cut/Copy/Paste")
#define LAT1CTOWX(X)
Definition: Internat.h:158
#define _(s)
Definition: Internat.h:73
@ ID_Texts
@ ID_Duration
@ ID_Sliders
@ ID_Toggles
constexpr float ControlValueTolerance
#define safenew
Definition: MemoryX.h:10
const NumericConverterType & NumericConverterType_TIME()
wxEVT_COMMAND_TEXT_UPDATED
Definition: Nyquist.cpp:73
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:51
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:59
EffectSettingsAccess & mAccess
Definition: EffectEditor.h:92
void BindTo(wxEvtHandler &src, const EventTag &eventType, void(Class::*pmf)(Event &))
Definition: EffectEditor.h:85
void ModifySettings(Function &&function)
Do a correct read-modify-write of settings.
virtual const EffectSettings & Get()=0
static FormatterContext SampleRateContext(double sampleRate)
static wxString ToDisplayString(double numberToConvert, int digitsAfterDecimalPoint=-1)
Convert a number to a string, uses the user's locale's decimal separator.
Definition: Internat.cpp:137
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
Definition: Internat.cpp:109
const float & mVal
void OnErase(wxEraseEvent &evt)
void OnSize(wxSizeEvent &evt)
LadspaEffectMeter(wxWindow *parent, const float &val, float min, float max)
void OnIdle(wxIdleEvent &evt)
virtual ~LadspaEffectMeter()
void OnPaint(wxPaintEvent &evt)
void SetName(const TranslatableString &name)
CallbackReturn Publish(const EffectSettingChanged &message)
Send a message to connected callbacks.
Definition: Observer.h:207
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
#define LADSPA_IS_HINT_BOUNDED_BELOW(x)
Definition: ladspa.h:310
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x)
Definition: ladspa.h:311
#define LADSPA_IS_HINT_INTEGER(x)
Definition: ladspa.h:315
#define LADSPA_IS_HINT_TOGGLED(x)
Definition: ladspa.h:312
int LADSPA_PortDescriptor
Definition: ladspa.h:152
#define LADSPA_IS_PORT_INPUT(x)
Definition: ladspa.h:168
#define LADSPA_IS_PORT_AUDIO(x)
Definition: ladspa.h:171
#define LADSPA_IS_PORT_CONTROL(x)
Definition: ladspa.h:170
#define LADSPA_IS_PORT_OUTPUT(x)
Definition: ladspa.h:169
#define LADSPA_IS_HINT_SAMPLE_RATE(x)
Definition: ladspa.h:313
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:202
DynamicRangeProcessorSettings GetSettings(EffectSettingsAccess &access)
const LADSPA_PortDescriptor * PortDescriptors
Definition: ladspa.h:410
const LADSPA_PortRangeHint * PortRangeHints
Definition: ladspa.h:419
_LADSPA_PortRangeHint is a structure that gives parameter validation information for a LADSPA (Linux ...
Definition: ladspa.h:337
LADSPA_PortRangeHintDescriptor HintDescriptor
Definition: ladspa.h:340
LADSPA_Data LowerBound
Definition: ladspa.h:345
LADSPA_Data UpperBound
Definition: ladspa.h:350
Externalized state of a plug-in.
EffectSettingsExtra extra
const unsigned mNumInputControls
Definition: LadspaEditor.h:65
wxWindow * mParent
Definition: LadspaEditor.h:75
const EffectType mType
Definition: LadspaEditor.h:69
void PopulateUI(ShuttleGui &S)
ArrayOf< wxSlider * > mSliders
Definition: LadspaEditor.h:76
const double mSampleRate
Definition: LadspaEditor.h:68
void Disconnect() override
On the first call only, may disconnect from further event handling.
ArrayOf< wxCheckBox * > mToggles
Definition: LadspaEditor.h:79
static LadspaEffectSettings & GetSettings(EffectSettings &settings)
Assume settings originated from MakeSettings() and copies thereof.
Definition: LadspaEditor.h:31
LadspaEffectSettings mSettings
Definition: LadspaEditor.h:70
NumericTextCtrl * mDuration
Definition: LadspaEditor.h:73
ArrayOf< wxStaticText * > mLabels
Definition: LadspaEditor.h:78
ArrayOf< wxTextCtrl * > mFields
Definition: LadspaEditor.h:77
LadspaEditor(const EffectUIServices &effect, const LadspaInstance &instance, unsigned numInputControls, unsigned numOutputControls, EffectSettingsAccess &access, double sampleRate, EffectType type, const LadspaEffectOutputs *pOutputs)
const LadspaEffectOutputs *const mpOutputs
Definition: LadspaEditor.h:71
void UpdateControls(const LadspaEffectSettings &src)
void RefreshControls()
void OnCheckBox(wxCommandEvent &evt)
void OnSlider(wxCommandEvent &evt)
void UpdateControl(int index, float value, float epsilon)
void OnTextCtrl(wxCommandEvent &evt)
bool ValidateUI() override
Get settings data from the panel; may make error dialogs and return false.
std::vector< LadspaEffectMeter * > mMeters
Definition: LadspaEditor.h:80
const unsigned mNumOutputControls
Definition: LadspaEditor.h:66
const LadspaInstance & mInstance
Definition: LadspaEditor.h:64
bool UpdateUI() override
Update appearance of the panel for changes in settings.
Carry output control port information back to main thread.
std::vector< float > controls
std::vector< float > controls
const LADSPA_Descriptor *const mData
Options & AutoPos(bool enable)