Audacity  3.0.3
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. See License.txt.
9 
10 **********************************************************************/
11 
12 
13 
14 #if defined(USE_LV2)
15 
16 #if defined(__GNUC__)
17 #pragma GCC diagnostic ignored "-Wparentheses"
18 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
19 #elif defined(__clang__)
20 #pragma clang diagnostic ignored "-Wparentheses"
21 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
22 #endif
23 
24 #include "LV2Effect.h"
25 
26 #include <cmath>
27 
28 #include <wx/button.h>
29 #include <wx/checkbox.h>
30 #include <wx/choice.h>
31 #include <wx/dcbuffer.h>
32 #include <wx/dialog.h>
33 #include <wx/crt.h>
34 #include <wx/log.h>
35 #include <wx/msgqueue.h>
36 
37 #ifdef __WXMAC__
38 #include <wx/evtloop.h>
39 #endif
40 
41 #include <wx/sizer.h>
42 #include <wx/slider.h>
43 #include <wx/statbox.h>
44 #include <wx/stattext.h>
45 #include <wx/tokenzr.h>
46 #include <wx/intl.h>
47 #include <wx/scrolwin.h>
48 
49 #include "../../ShuttleGui.h"
50 #include "../../widgets/valnum.h"
51 #include "../../widgets/AudacityMessageBox.h"
52 #include "../../widgets/wxPanelWrapper.h"
53 #include "../../widgets/NumericTextCtrl.h"
54 
55 #include "lilv/lilv.h"
56 #include "suil/suil.h"
57 #include "lv2/atom/atom.h"
58 #include "lv2/atom/forge.h"
59 #include "lv2/atom/util.h"
60 #include "lv2/instance-access/instance-access.h"
61 #include "lv2/port-groups/port-groups.h"
62 #include "lv2/parameters/parameters.h"
63 #include "lv2/state/state.h"
64 #include "lv2/ui/ui.h"
65 
66 #if defined(__WXGTK__)
67 #include <gtk/gtk.h>
68 #endif
69 
70 #if defined(__WXMSW__)
71 #include <wx/msw/wrapwin.h>
72 #endif
73 
74 // Define a maximum block size in number of samples (not bytes)
75 #define DEFAULT_BLOCKSIZE 1048576
76 
77 // Define a reasonable default sequence size in bytes
78 #define DEFAULT_SEQSIZE 8192
79 
80 // Define the static URI map
82 
83 // Define the static LILV URI nodes
84 #undef NODE
85 #define NODE(n, u) LilvNode *LV2Effect::node_##n = NULL;
87 
88 // Define the static URIDs
89 #undef URID
90 #define URID(n, u) LV2_URID LV2Effect::urid_##n = 0;
92 
94 //
95 // LV2EffectMeter
96 //
98 
99 class LV2EffectMeter final : public wxWindow
100 {
101 public:
102  LV2EffectMeter(wxWindow *parent, const LV2ControlPortPtr ctrl);
103  virtual ~LV2EffectMeter();
104 
105 private:
106  void OnErase(wxEraseEvent &evt);
107  void OnPaint(wxPaintEvent &evt);
108  void OnIdle(wxIdleEvent &evt);
109  void OnSize(wxSizeEvent &evt);
110 
111 private:
113  float mLastValue;
114 
115  DECLARE_EVENT_TABLE()
116 };
117 
118 BEGIN_EVENT_TABLE(LV2EffectMeter, wxWindow)
119  EVT_IDLE(LV2EffectMeter::OnIdle)
120  EVT_ERASE_BACKGROUND(LV2EffectMeter::OnErase)
121  EVT_PAINT(LV2EffectMeter::OnPaint)
122  EVT_SIZE(LV2EffectMeter::OnSize)
124 
125 LV2EffectMeter::LV2EffectMeter(wxWindow *parent, const LV2ControlPortPtr port)
126 : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDEFAULT_CONTROL_BORDER),
127  mControlPort(port)
128 {
129  mLastValue = -mControlPort->mVal;
130 
131  SetBackgroundColour(*wxWHITE);
132 }
133 
135 {
136 }
137 
138 void LV2EffectMeter::OnIdle(wxIdleEvent &evt)
139 {
140  evt.Skip();
141  if (mLastValue != mControlPort->mVal)
142  {
143  Refresh(false);
144  }
145 }
146 
147 void LV2EffectMeter::OnErase(wxEraseEvent &WXUNUSED(evt))
148 {
149  // Just ignore it to prevent flashing
150 }
151 
152 void LV2EffectMeter::OnPaint(wxPaintEvent &WXUNUSED(evt))
153 {
154  std::unique_ptr<wxDC> dc {wxAutoBufferedPaintDCFactory(this)};
155 
156  // Cache some metrics
157  wxRect r = GetClientRect();
158  wxCoord x = r.GetLeft();
159  wxCoord y = r.GetTop();
160  wxCoord w = r.GetWidth();
161  wxCoord h = r.GetHeight();
162 
163  // These use unscaled value, min, and max
164  float val = mControlPort->mVal;
165  if (val > mControlPort->mMax)
166  {
167  val = mControlPort->mMax;
168  }
169  if (val < mControlPort->mMin)
170  {
171  val = mControlPort->mMin;
172  }
173  val -= mControlPort->mMin;
174 
175  // Setup for erasing the background
176  dc->SetPen(*wxTRANSPARENT_PEN);
177  dc->SetBrush(wxColour(100, 100, 220));
178 
179  dc->Clear();
180  dc->DrawRectangle(x, y, (w * (val / fabs(mControlPort->mMax - mControlPort->mMin))), h);
181 
182  mLastValue = mControlPort->mVal;
183 }
184 
185 void LV2EffectMeter::OnSize(wxSizeEvent &WXUNUSED(evt))
186 {
187  Refresh(false);
188 }
189 
191 //
192 // LV2EffectSettingsDialog
193 //
195 
197 {
198 public:
199  LV2EffectSettingsDialog(wxWindow *parent, LV2Effect *effect);
200  virtual ~LV2EffectSettingsDialog();
201 
203 
204  void OnOk(wxCommandEvent &evt);
205 
206 private:
210  bool mUseGUI;
211 
212  DECLARE_EVENT_TABLE()
213 };
214 
215 BEGIN_EVENT_TABLE(LV2EffectSettingsDialog, wxDialogWrapper)
218 
220 : wxDialogWrapper(parent, wxID_ANY, XO("LV2 Effect Settings"))
221 {
222  mEffect = effect;
223 
224  mEffect->mHost->GetSharedConfig(wxT("Settings"), wxT("BufferSize"), mBufferSize, 8192);
225  mEffect->mHost->GetSharedConfig(wxT("Settings"), wxT("UseLatency"), mUseLatency, true);
226  mEffect->mHost->GetSharedConfig(wxT("Settings"), wxT("UseGUI"), mUseGUI, true);
227 
228  ShuttleGui S(this, eIsCreating);
229  PopulateOrExchange(S);
230 }
231 
233 {
234 }
235 
237 {
238  S.SetBorder(5);
239  S.StartHorizontalLay(wxEXPAND, 1);
240  {
241  S.StartVerticalLay(false);
242  {
243  // This really shouldn't be required for LV2 plugins because they have the ability
244  // to specify their exact requirements in the TTL file and/or to check the host
245  // supplied min/max values. However, I've run across one (Harrison Consoles XT-EQ)
246  // that crashed on sizes greater than 8192.
247  S.StartStatic(XO("Buffer Size"));
248  {
249  IntegerValidator<int> vld(&mBufferSize);
250  vld.SetRange(8, DEFAULT_BLOCKSIZE);
251 
252  S.AddVariableText( XO(
253 "The buffer size controls the number of samples sent to the effect "
254 "on each iteration. Smaller values will cause slower processing and "
255 "some effects require 8192 samples or less to work properly. However "
256 "most effects can accept large buffers and using them will greatly "
257 "reduce processing time."),
258  false, 0, 650);
259 
260  S.StartHorizontalLay(wxALIGN_LEFT);
261  {
262  wxTextCtrl *t;
263  t = S.TieNumericTextBox(
264  XXO("&Buffer Size (8 to %d) samples:")
266  mBufferSize,
267  12);
268  t->SetMinSize(wxSize(100, -1));
269  t->SetValidator(vld);
270  }
271  S.EndHorizontalLay();
272  }
273  S.EndStatic();
274 
275  S.StartStatic(XO("Latency Compensation"));
276  {
277  S.AddVariableText( XO(
278 "As part of their processing, some LV2 effects must delay returning "
279 "audio to Audacity. When not compensating for this delay, you will "
280 "notice that small silences have been inserted into the audio. "
281 "Enabling this setting will provide that compensation, but it may "
282 "not work for all LV2 effects."),
283  false, 0, 650);
284 
285  S.StartHorizontalLay(wxALIGN_LEFT);
286  {
287  S.TieCheckBox(XXO("Enable &compensation"),
288  mUseLatency);
289  }
290  S.EndHorizontalLay();
291  }
292  S.EndStatic();
293 
294  S.StartStatic(XO("Graphical Mode"));
295  {
296  S.AddVariableText( XO(
297 "LV2 effects can have a graphical interface for setting parameter values."
298 " A basic text-only method is also available. "
299 " Reopen the effect for this to take effect."),
300  false, 0, 650);
301  S.TieCheckBox(XXO("Enable &graphical interface"),
302  mUseGUI);
303  }
304  S.EndStatic();
305  }
306  S.EndVerticalLay();
307  }
308  S.EndHorizontalLay();
309 
310  S.AddStandardButtons();
311 
312  Layout();
313  Fit();
314  Center();
315 }
316 
317 void LV2EffectSettingsDialog::OnOk(wxCommandEvent &WXUNUSED(evt))
318 {
319  if (!Validate())
320  {
321  return;
322  }
323 
326 
327  mEffect->mHost->SetSharedConfig(wxT("Settings"), wxT("BufferSize"), mBufferSize);
328  mEffect->mHost->SetSharedConfig(wxT("Settings"), wxT("UseLatency"), mUseLatency);
329  mEffect->mHost->SetSharedConfig(wxT("Settings"), wxT("UseGUI"), mUseGUI);
330 
331  EndModal(wxID_OK);
332 }
333 
335 //
336 // LV2Effect
337 //
339 
340 enum
341 {
342  ID_Duration = 10000,
343  ID_Triggers = 11000,
344  ID_Toggles = 12000,
345  ID_Sliders = 13000,
346  ID_Choices = 14000,
347  ID_Texts = 15000,
348  ID_TIMER = 20000,
349 };
350 
351 BEGIN_EVENT_TABLE(LV2Effect, wxEvtHandler)
352  EVT_COMMAND_RANGE(ID_Triggers, ID_Triggers + 999, wxEVT_COMMAND_BUTTON_CLICKED, LV2Effect::OnTrigger)
353  EVT_COMMAND_RANGE(ID_Toggles, ID_Toggles + 999, wxEVT_COMMAND_CHECKBOX_CLICKED, LV2Effect::OnToggle)
354  EVT_COMMAND_RANGE(ID_Sliders, ID_Sliders + 999, wxEVT_COMMAND_SLIDER_UPDATED, LV2Effect::OnSlider)
355  EVT_COMMAND_RANGE(ID_Choices, ID_Choices + 999, wxEVT_COMMAND_CHOICE_SELECTED, LV2Effect::OnChoice)
357 
358  EVT_TIMER(ID_TIMER, LV2Effect::OnTimer)
359  EVT_IDLE(LV2Effect::OnIdle)
361 
362 LV2Effect::LV2Effect(const LilvPlugin *plug)
363 {
364  mPlug = plug;
365 
366  mHost = NULL;
367  mMaster = NULL;
368  mProcess = NULL;
369  mSuilInstance = NULL;
370 
371  mSampleRate = 44100;
372  mBlockSize = DEFAULT_BLOCKSIZE;
373  mSeqSize = DEFAULT_SEQSIZE;
374 
375  mMinBlockSize = 1;
376  mMaxBlockSize = mBlockSize;
377  mUserBlockSize = mBlockSize;
378 
379  mLatencyPort = -1;
380  mLatencyDone = false;
381  mRolling = false;
382  mActivated = false;
383 
384  mDialog = NULL;
385 
386  mUIIdleInterface = NULL;
387  mUIShowInterface = NULL;
388 
389  mAudioIn = 0;
390  mAudioOut = 0;
391  mMidiIn = 0;
392  mMidiOut = 0;
393 
394  mControlIn.reset();
395  mControlOut.reset();
396 
397  mPositionSpeed = 1.0;
398  mPositionFrame = 0.0;
399 
400  mNativeWin = NULL;
401  mNativeWinInitialSize = wxDefaultSize;
402  mNativeWinLastSize = wxDefaultSize;
403  mResizing = false;
404 #if defined(__WXGTK__)
405  mResized = false;
406 #endif
407 
408  mExternalUIHost.plugin_human_id = NULL;
409  mExternalWidget = NULL;
410  mExternalUIClosed = false;
411 
412  mNoResize = false;
413 
414  mSupportsNominalBlockLength = false;
415  mSupportsSampleRate = false;
416 
417  mFactoryPresetsLoaded = false;
418 }
419 
421 {
422 }
423 
424 // ============================================================================
425 // ComponentInterface Implementation
426 // ============================================================================
427 
429 {
430  return LilvString(lilv_plugin_get_uri(mPlug));
431 }
432 
434 {
435  return LilvString(lilv_plugin_get_name(mPlug), true);
436 }
437 
439 {
440  wxString vendor = LilvString(lilv_plugin_get_author_name(mPlug), true);
441 
442  if (vendor.empty())
443  {
444  return XO("n/a");
445  }
446 
447  return {vendor};
448 }
449 
451 {
452  return wxT("1.0");
453 }
454 
456 {
457  return XO("n/a");
458 }
459 
460 // ============================================================================
461 // EffectDefinitionInterface Implementation
462 // ============================================================================
463 
465 {
466  if (GetAudioInCount() == 0 && GetAudioOutCount() == 0)
467  {
468  return EffectTypeTool;
469  }
470 
471  if (GetAudioInCount() == 0)
472  {
473  return EffectTypeGenerate;
474  }
475 
476  if (GetAudioOutCount() == 0)
477  {
478  return EffectTypeAnalyze;
479  }
480 
481  return EffectTypeProcess;
482 }
483 
485 {
486  return LV2EFFECTS_FAMILY;
487 }
488 
490 {
491  return mControlPorts.size() != 0;
492 }
493 
495 {
496  return false;
497 }
498 
500 {
501  return false;
502 }
503 
505 {
506  return GetType() == EffectTypeProcess;
507 }
508 
510 {
511  return true;
512 }
513 
514 // ============================================================================
515 // EffectClientInterface Implementation
516 // ============================================================================
518 {
519  mHost = host;
520 
521  AddOption(urid_SequenceSize, sizeof(mSeqSize), urid_Int, &mSeqSize);
522  AddOption(urid_MinBlockLength, sizeof(mMinBlockSize), urid_Int, &mMinBlockSize);
523  AddOption(urid_MaxBlockLength, sizeof(mMaxBlockSize), urid_Int, &mMaxBlockSize);
524 
525  mBlockSizeOption = AddOption(urid_NominalBlockLength,
526  sizeof(mBlockSize),
527  urid_Int,
528  &mBlockSize);
529  mSampleRateOption = AddOption(urid_SampleRate,
530  sizeof(mSampleRate),
531  urid_Float,
532  &mSampleRate);
533  AddOption(0, 0, 0, NULL);
534 
535  if (!ValidateOptions(lilv_plugin_get_uri(mPlug)))
536  {
537  return false;
538  }
539 
540  mUriMapFeature.callback_data = this;
542 
543  mURIDMapFeature.handle = this;
545 
546  mURIDUnmapFeature.handle = this;
548 
549  mUIResizeFeature.handle = this;
551 
552  mLogFeature.handle = this;
555 
557 
558  LilvNode *pluginName = lilv_plugin_get_name(mPlug);
559  mExternalUIHost.plugin_human_id = lilv_node_as_string(pluginName);
560  lilv_node_free(pluginName);
561 
562  AddFeature(LV2_UI__noUserResize, NULL);
563  AddFeature(LV2_UI__fixedSize, NULL);
564  AddFeature(LV2_UI__idleInterface, NULL);
566  AddFeature(LV2_BUF_SIZE__boundedBlockLength, NULL);
567  AddFeature(LV2_BUF_SIZE__fixedBlockLength, NULL);
568  AddFeature(LV2_OPTIONS__options, mOptions.data());
569  AddFeature(LV2_URI_MAP_URI, &mUriMapFeature);
570  AddFeature(LV2_URID__map, &mURIDMapFeature);
571  AddFeature(LV2_URID__unmap, &mURIDUnmapFeature);
572  AddFeature(LV2_UI__resize, &mUIResizeFeature);
573  AddFeature(LV2_DATA_ACCESS_URI, &mExtensionDataFeature);
574  AddFeature(LV2_LOG__log, &mLogFeature);
577  // Some plugins specify this as a feature
579 
580  mInstanceAccessFeature = AddFeature(LV2_INSTANCE_ACCESS_URI, NULL);
581  mParentFeature = AddFeature(LV2_UI__parent, NULL);
582 
583  AddFeature(NULL, NULL);
584 
585  if (!ValidateFeatures(lilv_plugin_get_uri(mPlug)))
586  {
587  return false;
588  }
589 
590  auto minLength = lilv_world_get(gWorld, lilv_plugin_get_uri(mPlug), node_MinBlockLength, NULL);
591  if (minLength)
592  {
593  if (lilv_node_is_int(minLength))
594  {
595  int val = lilv_node_as_int(minLength);
596  if (mMinBlockSize < val)
597  {
598  mMinBlockSize = val;
599  }
600  }
601  lilv_node_free(minLength);
602  }
603 
604  auto maxLength = lilv_world_get(gWorld, lilv_plugin_get_uri(mPlug), node_MaxBlockLength, NULL);
605  if (maxLength)
606  {
607  if (lilv_node_is_int(maxLength))
608  {
609  int val = lilv_node_as_int(maxLength);
610  if (mMaxBlockSize > val)
611  {
612  mMaxBlockSize = val;
613  }
614  }
615  lilv_node_free(maxLength);
616  }
617 
619  {
621  }
622 
623  auto numPorts = lilv_plugin_get_num_ports(mPlug);
624 
625  // Allocate buffers for the port indices and the default control values
626  Floats minimumVals {numPorts};
627  Floats maximumVals {numPorts};
628  Floats defaultVals {numPorts};
629 
630  // Retrieve the port ranges for all ports (some values may be NaN)
631  lilv_plugin_get_port_ranges_float(mPlug,
632  minimumVals.get(),
633  maximumVals.get(),
634  defaultVals.get());
635 
636  // Get info about all ports
637  for (size_t i = 0; i < numPorts; i++)
638  {
639  const LilvPort *port = lilv_plugin_get_port_by_index(mPlug, i);
640  int index = lilv_port_get_index(mPlug, port);
641 
642  // It must be input or output, anything else is bogus
643  bool isInput;
644  if (lilv_port_is_a(mPlug, port, node_InputPort))
645  {
646  isInput = true;
647  }
648  else if (lilv_port_is_a(mPlug, port, node_OutputPort))
649  {
650  isInput = false;
651  }
652  else
653  {
654  assert(false);
655  return false;
656  }
657 
658  // Get the port name and symbol
659  wxString symbol = LilvString(lilv_port_get_symbol(mPlug, port));
660  wxString name = LilvString(lilv_port_get_name(mPlug, port), true);
661 
662  // Get the group to which this port belongs or default to the main group
663  wxString groupName = wxEmptyString;
664  LilvNode *group = lilv_port_get(mPlug, port, node_Group);
665  if (group)
666  {
667  groupName = LilvString(lilv_world_get(gWorld, group, node_Label, NULL), true);
668  if (groupName.empty())
669  {
670  groupName = LilvString(lilv_world_get(gWorld, group, node_Name, NULL), true);
671  }
672 
673  if (groupName.empty())
674  {
675  groupName = LilvString(group);
676  }
677 
678  lilv_node_free(group);
679  }
680  else
681  {
682  groupName = _("Effect Settings");
683  }
684 
685  // Get the latency port
686  uint32_t latencyIndex = lilv_plugin_get_latency_port_index(mPlug);
687 
688  // Get the ports designation (must be freed)
689  LilvNode *designation = lilv_port_get(mPlug, port, node_Designation);
690 
691  // Check for audio ports
692  if (lilv_port_is_a(mPlug, port, node_AudioPort))
693  {
694  mAudioPorts.push_back(std::make_shared<LV2AudioPort>(port, index, isInput, symbol, name, groupName));
695 
696  isInput ? mAudioIn++ : mAudioOut++;
697  }
698  // Check for Control ports
699  else if (lilv_port_is_a(mPlug, port, node_ControlPort))
700  {
701  // Add group if not previously done
702  if (mGroupMap.find(groupName) == mGroupMap.end())
703  {
704  mGroups.push_back(groupName);
705  }
706  mGroupMap[groupName].push_back(mControlPorts.size());
707 
708  mControlPorts.push_back(std::make_shared<LV2ControlPort>(port, index, isInput, symbol, name, groupName));
709  LV2ControlPortPtr controlPort = mControlPorts.back();
710 
711  // Get any unit descriptor
712  LilvNode *unit = lilv_port_get(mPlug, port, node_Unit);
713  if (unit)
714  {
715  // Really should use lilv_world_get_symbol()
716  LilvNode *symbol = lilv_world_get_symbol(gWorld, unit);
717  if (symbol)
718  {
719  controlPort->mUnits = LilvString(symbol);
720  lilv_node_free(symbol);
721  }
722  lilv_node_free(unit);
723  }
724 
725  // Get the scale points
726  LilvScalePoints *points = lilv_port_get_scale_points(mPlug, port);
727  LILV_FOREACH(scale_points, j, points)
728  {
729  const LilvScalePoint *point = lilv_scale_points_get(points, j);
730 
731  controlPort->mScaleValues.push_back(lilv_node_as_float(lilv_scale_point_get_value(point)));
732  controlPort->mScaleLabels.push_back(LilvString(lilv_scale_point_get_label(point)));
733  }
734  lilv_scale_points_free(points);
735 
736  // Collect the value and range info
737  controlPort->mHasLo = !std::isnan(minimumVals[i]);
738  controlPort->mHasHi = !std::isnan(maximumVals[i]);
739  controlPort->mMin = controlPort->mHasLo ? minimumVals[i] : 0.0;
740  controlPort->mMax = controlPort->mHasHi ? maximumVals[i] : 1.0;
741  controlPort->mLo = controlPort->mMin;
742  controlPort->mHi = controlPort->mMax;
743  controlPort->mDef = !std::isnan(defaultVals[i])
744  ? defaultVals[i]
745  : controlPort->mHasLo
746  ? controlPort->mLo
747  : controlPort->mHasHi
748  ? controlPort->mHi
749  : 0.0;
750  controlPort->mVal = controlPort->mDef;
751  controlPort->mLst = controlPort->mVal;
752 
753  // Figure out the type of port we have
754  if (isInput)
755  {
756  if (lilv_port_has_property(mPlug, port, node_Toggled))
757  {
758  controlPort->mToggle = true;
759  }
760  else if (lilv_port_has_property(mPlug, port, node_Enumeration))
761  {
762  controlPort->mEnumeration = true;
763  }
764  else if (lilv_port_has_property(mPlug, port, node_Integer))
765  {
766  controlPort->mInteger = true;
767  }
768  else if (lilv_port_has_property(mPlug, port, node_SampleRate))
769  {
770  controlPort->mSampleRate = true;
771  }
772 
773  // Trigger properties can be combined with other types, but it
774  // seems mostly to be combined with toggle. So, we turn the
775  // checkbox into a button.
776  if (lilv_port_has_property(mPlug, port, node_Trigger))
777  {
778  controlPort->mTrigger = true;
779  }
780 
781  // We'll make the slider logarithmic
782  if (lilv_port_has_property(mPlug, port, node_Logarithmic))
783  {
784  controlPort->mLogarithmic = true;
785  }
786 
787  if (lilv_port_has_property(mPlug, port, node_Enumeration))
788  {
789  controlPort->mEnumeration = true;
790  }
791 
792  mControlPortMap[controlPort->mIndex] = controlPort;
793  }
794  else
795  {
796  if (controlPort->mIndex == latencyIndex)
797  {
798  mLatencyPort = i;
799  }
800  }
801  }
802  // Check for atom ports
803  else if (lilv_port_is_a(mPlug, port, node_AtomPort))
804  {
805  mAtomPorts.push_back(std::make_shared<LV2AtomPort>(port, index, isInput, symbol, name, groupName));
806  std::shared_ptr<LV2AtomPort> atomPort = mAtomPorts.back();
807 
808  atomPort->mMinimumSize = 8192;
809  LilvNode *min = lilv_port_get(mPlug, port, node_MinimumSize);
810  if (min)
811  {
812  if (lilv_node_is_int(min))
813  {
814  uint32_t val = lilv_node_as_int(min);
815  if (atomPort->mMinimumSize < val)
816  {
817  atomPort->mMinimumSize = val;
818  }
819  }
820  lilv_node_free(min);
821  }
822 
823  atomPort->mBuffer.resize(atomPort->mMinimumSize);
824  atomPort->mRing = zix_ring_new(atomPort->mMinimumSize);
825  zix_ring_mlock(atomPort->mRing);
826 
827  if (lilv_port_supports_event(mPlug, port, node_Position))
828  {
829  atomPort->mWantsPosition = true;
830  }
831 
832  if (lilv_port_supports_event(mPlug, port, node_MidiEvent))
833  {
834  atomPort->mIsMidi = true;
835  (isInput ? mMidiIn : mMidiOut) += 1;
836  }
837 
838  bool isControl = lilv_node_equals(designation, node_Control);
839  if (isInput)
840  {
841  if (!mControlIn || isControl)
842  {
843  mControlIn = atomPort;
844  }
845  }
846  else
847  {
848  if (!mControlOut || isControl)
849  {
850  mControlOut = atomPort;
851  }
852  }
853  }
854  // Check for CV ports
855  else if (lilv_port_is_a(mPlug, port, node_CVPort))
856  {
857  mCVPorts.push_back(std::make_shared<LV2CVPort>(port, index, isInput, symbol, name, groupName));
858  std::shared_ptr<LV2CVPort> cvPort = mCVPorts.back();
859 
860  // Collect the value and range info
861  if (!std::isnan(minimumVals[i]))
862  {
863  cvPort->mHasLo = true;
864  cvPort->mMin = minimumVals[i];
865  }
866 
867  if (!std::isnan(maximumVals[i]))
868  {
869  cvPort->mHasHi = true;
870  cvPort->mMax = maximumVals[i];
871  }
872 
873  if (!std::isnan(defaultVals[i]))
874  {
875  cvPort->mDef = defaultVals[i];
876  }
877  else if (cvPort->mHasLo)
878  {
879  cvPort->mDef = cvPort->mMin;
880  }
881  else if (cvPort->mHasHi)
882  {
883  cvPort->mDef = cvPort->mMax;
884  }
885  }
886 
887  // Free the designation node
888  if (designation)
889  {
890  lilv_node_free(designation);
891  }
892  }
893 
894  // Ignore control designation if one of them is missing
895  if ((mControlIn && !mControlOut) || (!mControlIn && mControlOut))
896  {
897  mControlIn.reset();
898  mControlOut.reset();
899  }
900 
901  // Determine available extensions
902  mWantsOptionsInterface = false;
903  mWantsWorkerInterface = false;
904  mWantsStateInterface = false;
905 
906  LilvNodes *extdata = lilv_plugin_get_extension_data(mPlug);
907  if (extdata)
908  {
909  LILV_FOREACH(nodes, i, extdata)
910  {
911  const LilvNode *node = lilv_nodes_get(extdata, i);
912  const char *uri = lilv_node_as_string(node);
913 
914  if (strcmp(uri, LV2_OPTIONS__interface) == 0)
915  {
916  mWantsOptionsInterface = true;
917  }
918  else if (strcmp(uri, LV2_WORKER__interface) == 0)
919  {
920  mWantsWorkerInterface = true;
921  }
922  else if (strcmp(uri, LV2_STATE__interface) == 0)
923  {
924  mWantsStateInterface = true;
925  }
926  }
927  lilv_nodes_free(extdata);
928  }
929 
930  // mHost will be null during registration
931  if (mHost)
932  {
933  int userBlockSize;
934  mHost->GetSharedConfig(wxT("Settings"), wxT("BufferSize"), userBlockSize, 8192);
935  mUserBlockSize = std::max(1, userBlockSize);
936  mHost->GetSharedConfig(wxT("Settings"), wxT("UseLatency"), mUseLatency, true);
937  mHost->GetSharedConfig(wxT("Settings"), wxT("UseGUI"), mUseGUI, true);
938 
940 
941  bool haveDefaults;
942  mHost->GetPrivateConfig(mHost->GetFactoryDefaultsGroup(), wxT("Initialized"), haveDefaults, false);
943  if (!haveDefaults)
944  {
946  mHost->SetPrivateConfig(mHost->GetFactoryDefaultsGroup(), wxT("Initialized"), true);
947  }
948 
950  }
951 
952  lv2_atom_forge_init(&mForge, &mURIDMapFeature);
953 
954  return true;
955 }
956 
958 {
959  return mAudioIn;
960 }
961 
963 {
964  return mAudioOut;
965 }
966 
968 {
969  return mMidiIn;
970 }
971 
973 {
974  return mMidiOut;
975 }
976 
977 void LV2Effect::SetSampleRate(double rate)
978 {
979  mSampleRate = (float) rate;
980 
981  if (mMaster)
982  {
984  }
985 
986  for (size_t i = 0, cnt = mSlaves.size(); i < cnt; i++)
987  {
988  mSlaves[i]->SetSampleRate();
989  }
990 }
991 
992 size_t LV2Effect::SetBlockSize(size_t maxBlockSize)
993 {
994  mBlockSize = std::min(std::min((int)maxBlockSize, mUserBlockSize), mMaxBlockSize);
995 
997  {
999  }
1000  if (mBlockSize > mMaxBlockSize)
1001  {
1003  }
1004 
1005  if (mMaster)
1006  {
1007  mMaster->SetBlockSize();
1008  }
1009 
1010  for (size_t i = 0, cnt = mSlaves.size(); i < cnt; i++)
1011  {
1012  mSlaves[i]->SetBlockSize();
1013  }
1014 
1015  return mBlockSize;
1016 }
1017 
1019 {
1020  return mBlockSize;
1021 }
1022 
1024 {
1025  if (mUseLatency && mLatencyPort >= 0 && !mLatencyDone)
1026  {
1027  mLatencyDone = true;
1028  return sampleCount(mMaster->GetLatency());
1029  }
1030 
1031  return 0;
1032 }
1033 
1035 {
1036  return 0;
1037 }
1038 
1040 {
1041  return mMaster != NULL;
1042 }
1043 
1044 bool LV2Effect::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames WXUNUSED(chanMap))
1045 {
1047  if (!mProcess)
1048  {
1049  return false;
1050  }
1051 
1052  for (auto & port : mCVPorts)
1053  {
1054  port->mBuffer.reinit((unsigned) mBlockSize, port->mIsInput);
1055  }
1056 
1057  lilv_instance_activate(mProcess->GetInstance());
1058  mActivated = true;
1059 
1060  mLatencyDone = false;
1061 
1062  return true;
1063 }
1064 
1066 {
1067  if (mProcess)
1068  {
1070  mProcess = NULL;
1071  }
1072 
1073  return true;
1074 }
1075 
1076 size_t LV2Effect::ProcessBlock(float **inbuf, float **outbuf, size_t size)
1077 {
1078  wxASSERT(size <= ( size_t) mBlockSize);
1079 
1080  LilvInstance *instance = mProcess->GetInstance();
1081 
1082  int i = 0;
1083  int o = 0;
1084  for (auto & port : mAudioPorts)
1085  {
1086  lilv_instance_connect_port(instance,
1087  port->mIndex,
1088  (port->mIsInput ? inbuf[i++] : outbuf[o++]));
1089  }
1090 
1091  // Transfer incoming events from the ring buffer to the event buffer for each
1092  // atom input port. These will be made available to each slave in the chain and
1093  // to the master once all slaves have run.
1094  //
1095  // In addition, reset the output Atom ports.
1096  for (auto & port : mAtomPorts)
1097  {
1098  uint8_t *buf = port->mBuffer.data();
1099 
1100  if (port->mIsInput)
1101  {
1102  lv2_atom_forge_set_buffer(&mForge,
1103  buf,
1104  port->mBuffer.size());
1105 
1106  LV2_Atom_Forge_Frame seqFrame;
1107  LV2_Atom_Sequence *seq = ( LV2_Atom_Sequence *)
1108  lv2_atom_forge_sequence_head(&mForge, &seqFrame, 0);
1109 
1110  if (port->mWantsPosition)
1111  {
1112  lv2_atom_forge_frame_time(&mForge, mPositionFrame);
1113 
1114  LV2_Atom_Forge_Frame posFrame;
1115  lv2_atom_forge_object(&mForge, &posFrame, 0, urid_Position);
1116  lv2_atom_forge_key(&mForge, urid_Speed);
1117  lv2_atom_forge_float(&mForge, mPositionSpeed);
1118  lv2_atom_forge_key(&mForge, urid_Frame);
1119  lv2_atom_forge_long(&mForge, mPositionFrame);
1120  lv2_atom_forge_pop(&mForge, &posFrame);
1121  }
1122 
1123  ZixRing *ring = port->mRing;
1124  LV2_Atom atom;
1125  while (zix_ring_read(ring, &atom, sizeof(atom)))
1126  {
1127  if (mForge.offset + sizeof(LV2_Atom_Event) + atom.size < mForge.size)
1128  {
1129  lv2_atom_forge_frame_time(&mForge, mPositionFrame);
1130 
1131  lv2_atom_forge_write(&mForge, &atom, sizeof(atom));
1132  zix_ring_read(ring, &mForge.buf[mForge.offset], atom.size);
1133  mForge.offset += atom.size;
1134  seq->atom.size += atom.size;
1135  }
1136  else
1137  {
1138  zix_ring_skip(ring, atom.size);
1139  wxLogError(wxT("LV2 sequence buffer overflow"));
1140  }
1141  }
1142 
1143  lv2_atom_forge_pop(&mForge, &seqFrame);
1144  }
1145  else
1146  {
1147  port->mBuffer.resize(port->mMinimumSize);
1148  *(( LV2_Atom *) buf) =
1149  {
1150  port->mMinimumSize,
1151  urid_Chunk
1152  };
1153  }
1154  }
1155 
1156  lilv_instance_run(instance, size);
1157 
1159 
1160  for (auto & port : mAtomPorts)
1161  {
1162  if (!port->mIsInput)
1163  {
1164  port->mBuffer.resize(port->mMinimumSize);
1165 
1166  LV2_Atom *chunk = ( LV2_Atom *) port->mBuffer.data();
1167  chunk->size = port->mMinimumSize;
1168  chunk->type = urid_Chunk;
1169  }
1170  }
1171 
1172  return size;
1173 }
1174 
1176 {
1177  mMasterIn.reinit(mAudioIn, (unsigned int) mBlockSize);
1178  mMasterOut.reinit(mAudioOut, (unsigned int) mBlockSize);
1179 
1180  for (auto & port : mCVPorts)
1181  {
1182  port->mBuffer.reinit((unsigned) mBlockSize, port->mIsInput);
1183  }
1184 
1185  lilv_instance_activate(mMaster->GetInstance());
1186  mActivated = true;
1187 
1188  return true;
1189 }
1190 
1192 {
1193  for (auto & slave : mSlaves)
1194  {
1195  FreeInstance(slave);
1196  }
1197  mSlaves.clear();
1198 
1199  if (mActivated)
1200  {
1201  lilv_instance_deactivate(mMaster->GetInstance());
1202  mActivated = false;
1203  }
1204 
1205  for (auto & port : mCVPorts)
1206  {
1207  port->mBuffer.reset();
1208  }
1209 
1210  mMasterIn.reset();
1211  mMasterOut.reset();
1212 
1213  return true;
1214 }
1215 
1216 bool LV2Effect::RealtimeAddProcessor(unsigned WXUNUSED(numChannels), float sampleRate)
1217 {
1218  LV2Wrapper *slave = InitInstance(sampleRate);
1219  if (!slave)
1220  {
1221  return false;
1222  }
1223 
1224  mSlaves.push_back(slave);
1225 
1226  lilv_instance_activate(slave->GetInstance());
1227  mActivated = true;
1228 
1229  return true;
1230 }
1231 
1233 {
1234  mPositionSpeed = 0.0;
1235  mPositionFrame = 0.0;
1236  mRolling = false;
1237 
1238  return true;
1239 }
1240 
1242 {
1243  mPositionSpeed = 1.0;
1244  mPositionFrame = 0.0;
1245  mRolling = true;
1246 
1247  return true;
1248 }
1249 
1251 {
1252  int i = 0;
1253  for (auto & port : mAudioPorts)
1254  {
1255  if (port->mIsInput)
1256  {
1257  memset(mMasterIn[i++].get(), 0, mBlockSize * sizeof(float));
1258  }
1259  }
1260 
1261  mNumSamples = 0;
1262 
1263  // Transfer incoming events from the ring buffer to the event buffer for each
1264  // atom input port. These will be made available to each slave in the chain and
1265  // to the master once all slaves have run.
1266  //
1267  // In addition, reset the output Atom ports.
1268  for (auto & port : mAtomPorts)
1269  {
1270  uint8_t *buf = port->mBuffer.data();
1271 
1272  if (port->mIsInput)
1273  {
1274  lv2_atom_forge_set_buffer(&mForge,
1275  buf,
1276  port->mBuffer.size());
1277 
1278  LV2_Atom_Forge_Frame seqFrame;
1279  LV2_Atom_Sequence *seq = (LV2_Atom_Sequence *)
1280  lv2_atom_forge_sequence_head(&mForge, &seqFrame, 0);
1281 
1282  if (port->mWantsPosition)
1283  {
1284  lv2_atom_forge_frame_time(&mForge, mPositionFrame);
1285 
1286  LV2_Atom_Forge_Frame posFrame;
1287  lv2_atom_forge_object(&mForge, &posFrame, 0, urid_Position);
1288  lv2_atom_forge_key(&mForge, urid_Speed);
1289  lv2_atom_forge_float(&mForge, mPositionSpeed);
1290  lv2_atom_forge_key(&mForge, urid_Frame);
1291  lv2_atom_forge_long(&mForge, mPositionFrame);
1292  lv2_atom_forge_pop(&mForge, &posFrame);
1293  }
1294 
1295  ZixRing *ring = port->mRing;
1296  LV2_Atom atom;
1297  while (zix_ring_read(ring, &atom, sizeof(atom)))
1298  {
1299  if (mForge.offset + sizeof(LV2_Atom_Event) + atom.size < mForge.size)
1300  {
1301  lv2_atom_forge_frame_time(&mForge, mPositionFrame);
1302 
1303  lv2_atom_forge_write(&mForge, &atom, sizeof(atom));
1304  zix_ring_read(ring, &mForge.buf[mForge.offset], atom.size);
1305  mForge.offset += atom.size;
1306  seq->atom.size += atom.size;
1307  }
1308  else
1309  {
1310  zix_ring_skip(ring, atom.size);
1311  wxLogError(wxT("LV2 sequence buffer overflow"));
1312  }
1313  }
1314  lv2_atom_forge_pop(&mForge, &seqFrame);
1315 #if 0
1316  LV2_ATOM_SEQUENCE_FOREACH(seq, ev)
1317  {
1318  LV2_Atom_Object *o = (LV2_Atom_Object *) &ev->body;
1319  wxLogDebug(wxT("ev = %lld ev.size %d ev.type %d"), ev->time.frames, ev->body.size, ev->body.type);
1320  }
1321 #endif
1322  }
1323  else
1324  {
1325  port->mBuffer.resize(port->mMinimumSize);
1326  *((LV2_Atom *) buf) =
1327  {
1328  port->mMinimumSize,
1329  urid_Chunk
1330  };
1331  }
1332  }
1333 
1334  return true;
1335 }
1336 
1337 size_t LV2Effect::RealtimeProcess(int group, float **inbuf, float **outbuf, size_t numSamples)
1338 {
1339  wxASSERT(group >= 0 && group < (int) mSlaves.size());
1340  wxASSERT(numSamples <= (size_t) mBlockSize);
1341 
1342  if (group < 0 || group >= (int) mSlaves.size())
1343  {
1344  return 0;
1345  }
1346 
1347  LV2Wrapper *slave = mSlaves[group];
1348  LilvInstance *instance = slave->GetInstance();
1349 
1350  int i = 0;
1351  int o = 0;
1352  for (auto & port : mAudioPorts)
1353  {
1354  if (port->mIsInput)
1355  {
1356  for (decltype(numSamples) s = 0; s < numSamples; s++)
1357  {
1358  mMasterIn[i][s] += inbuf[i][s];
1359  }
1360  }
1361 
1362  lilv_instance_connect_port(instance,
1363  port->mIndex,
1364  (port->mIsInput ? inbuf[i++] : outbuf[o++]));
1365  }
1366 
1367  mNumSamples = wxMax(numSamples, mNumSamples);
1368 
1369  if (mRolling)
1370  {
1371  lilv_instance_run(instance, numSamples);
1372  }
1373  else
1374  {
1375  while (--i >= 0)
1376  {
1377  for (decltype(numSamples) s = 0; s < numSamples; s++)
1378  {
1379  outbuf[i][s] = inbuf[i][s];
1380  }
1381  }
1382  }
1383 
1384  slave->SendResponses();
1385 
1386  for (auto & port : mAtomPorts)
1387  {
1388  uint8_t *buf = port->mBuffer.data();
1389 
1390  if (!port->mIsInput)
1391  {
1392  port->mBuffer.resize(port->mMinimumSize);
1393 
1394  LV2_Atom *chunk = ( LV2_Atom *) buf;
1395  chunk->size = port->mMinimumSize;
1396  chunk->type = urid_Chunk;
1397  }
1398  }
1399 
1400  if (group == 0)
1401  {
1402  mPositionFrame += numSamples;
1403  }
1404 
1405  return numSamples;
1406 }
1407 
1409 {
1410  // Nothing to do if we did process any samples
1411  if (mNumSamples == 0)
1412  {
1413  return true;
1414  }
1415 
1416  int i = 0;
1417  int o = 0;
1418  for (auto & port : mAudioPorts)
1419  {
1420  lilv_instance_connect_port(mMaster->GetInstance(),
1421  port->mIndex,
1422  (port->mIsInput ? mMasterIn[i++].get() : mMasterOut[o++].get()));
1423  }
1424 
1425  if (mRolling)
1426  {
1427  lilv_instance_run(mMaster->GetInstance(), mNumSamples);
1428  }
1429 
1430  for (auto & port : mAtomPorts)
1431  {
1432  if (!port->mIsInput)
1433  {
1434  ZixRing *ring = port->mRing;
1435 
1436  LV2_ATOM_SEQUENCE_FOREACH((LV2_Atom_Sequence *) port->mBuffer.data(), ev)
1437  {
1438  zix_ring_write(ring, &ev->body, ev->body.size + sizeof(LV2_Atom));
1439  }
1440  }
1441  }
1442 
1443  mNumSamples = 0;
1444 
1445  return true;
1446 }
1447 
1449  wxWindow &parent, const EffectDialogFactory &factory, bool forceModal)
1450 {
1451  if (mDialog)
1452  {
1453  if (mDialog->Close(true))
1454  {
1455  mDialog = nullptr;
1456  }
1457  return false;
1458  }
1459 
1460  // mDialog is null
1461  auto cleanup = valueRestorer(mDialog);
1462 
1463  if ( factory )
1464  mDialog = factory(parent, mHost, this);
1465  if (!mDialog)
1466  {
1467  return false;
1468  }
1469 
1470  // Try to give the window a sensible default/minimum size
1471  mDialog->Layout();
1472  mDialog->Fit();
1473  mDialog->SetMinSize(mDialog->GetSize());
1474  if (mNoResize)
1475  {
1476  mDialog->SetMaxSize(mDialog->GetSize());
1477  }
1478 
1479  if ((SupportsRealtime() || GetType() == EffectTypeAnalyze) && !forceModal)
1480  {
1481  mDialog->Show();
1482  cleanup.release();
1483 
1484  return false;
1485  }
1486 
1487  bool res = mDialog->ShowModal() != 0;
1488 
1489  return res;
1490 }
1491 
1493 {
1494  for (auto & port : mControlPorts)
1495  {
1496  if (port->mIsInput)
1497  {
1498  if (!parms.Write(port->mName, port->mVal))
1499  {
1500  return false;
1501  }
1502  }
1503  }
1504 
1505  return true;
1506 }
1507 
1509 {
1510  // First pass validates values
1511  for (auto & port : mControlPorts)
1512  {
1513  if (port->mIsInput)
1514  {
1515  double d = 0.0;
1516  if (!parms.Read(port->mName, &d))
1517  {
1518  return false;
1519  }
1520 
1521  // Use unscaled range here
1522  if (d < port->mMin || d > port->mMax)
1523  {
1524  return false;
1525  }
1526  }
1527  }
1528 
1529  // Second pass actually sets the values
1530  for (auto & port : mControlPorts)
1531  {
1532  if (port->mIsInput)
1533  {
1534  double d = 0.0;
1535  if (!parms.Read(port->mName, &d))
1536  {
1537  return false;
1538  }
1539 
1540  port->mVal = d;
1541  port->mTmp = port->mVal * (port->mSampleRate ? mSampleRate : 1.0);
1542  }
1543  }
1544 
1545  return true;
1546 }
1547 
1548 // ============================================================================
1549 // EffectUIClientInterface Implementation
1550 // ============================================================================
1551 
1553 {
1554  mUIHost = host;
1555 }
1556 
1558 {
1559  auto parent = S.GetParent();
1560  mParent = parent;
1561 
1562  mParent->PushEventHandler(this);
1563 
1564  mSuilHost = NULL;
1565  mSuilInstance = NULL;
1566 
1568  if (mMaster == NULL)
1569  {
1570  AudacityMessageBox( XO("Couldn't instantiate effect") );
1571  return false;
1572  }
1573 
1574  // Determine if the GUI editor is supposed to be used or not
1575  mHost->GetSharedConfig(wxT("Settings"),
1576  wxT("UseGUI"),
1577  mUseGUI,
1578  true);
1579 
1580  // Until I figure out where to put the "Duration" control in the
1581  // graphical editor, force usage of plain editor.
1582  if (GetType() == EffectTypeGenerate)
1583  {
1584  mUseGUI = false;
1585  }
1586 
1587  if (mUseGUI)
1588  {
1589  mUseGUI = BuildFancy();
1590  }
1591 
1592  if (!mUseGUI)
1593  {
1594  return BuildPlain();
1595  }
1596 
1597  return true;
1598 }
1599 
1601 {
1602  return mUseGUI;
1603 }
1604 
1606 {
1607  if (!mParent->Validate() || !mParent->TransferDataFromWindow())
1608  {
1609  return false;
1610  }
1611 
1612  if (GetType() == EffectTypeGenerate)
1613  {
1615  }
1616 
1617  return true;
1618 }
1619 
1621 {
1622 #if 0
1623  // Nothing to do yet
1624 #endif
1625  return true;
1626 }
1627 
1629 {
1630 #ifdef __WXMAC__
1631 #ifdef __WX_EVTLOOP_BUSY_WAITING__
1632  wxEventLoop::SetBusyWaiting(false);
1633 #endif
1634 #endif
1635 
1636  mParent->RemoveEventHandler(this);
1637 
1638  if (mSuilInstance)
1639  {
1640  if (mNativeWin)
1641  {
1642  mNativeWin->Destroy();
1643  mNativeWin = NULL;
1644  }
1645 
1646  mUIIdleInterface = NULL;
1647  mUIShowInterface = NULL;
1648  mExternalWidget = NULL;
1649 
1650  suil_instance_free(mSuilInstance);
1651  mSuilInstance = NULL;
1652  }
1653 
1654  if (mSuilHost)
1655  {
1656  suil_host_free(mSuilHost);
1657  mSuilHost = NULL;
1658  }
1659 
1660  if (mMaster)
1661  {
1663  mMaster = NULL;
1664  }
1665 
1666  mUIHost = NULL;
1667  mParent = NULL;
1668  mDialog = NULL;
1669 
1670  return true;
1671 }
1672 
1674 {
1675  if (!LoadParameters(name))
1676  {
1677  return false;
1678  }
1679 
1680  return TransferDataToWindow();
1681 }
1682 
1684 {
1685  return SaveParameters(name);
1686 }
1687 
1689 {
1691  {
1692  return mFactoryPresetNames;
1693  }
1694 
1695  LilvNodes *presets = lilv_plugin_get_related(mPlug, node_Preset);
1696  if (presets)
1697  {
1698  LILV_FOREACH(nodes, i, presets)
1699  {
1700  const LilvNode *preset = lilv_nodes_get(presets, i);
1701 
1702  mFactoryPresetUris.push_back(LilvString(preset));
1703 
1704  lilv_world_load_resource(gWorld, preset);
1705 
1706  LilvNodes *labels = lilv_world_find_nodes(gWorld, preset, node_Label, NULL);
1707  if (labels)
1708  {
1709  const LilvNode *label = lilv_nodes_get_first(labels);
1710 
1711  mFactoryPresetNames.push_back(LilvString(label));
1712 
1713  lilv_nodes_free(labels);
1714  }
1715  else
1716  {
1717  mFactoryPresetNames.push_back(LilvString(preset).AfterLast(wxT('#')));
1718  }
1719  }
1720 
1721  lilv_nodes_free(presets);
1722  }
1723 
1724  mFactoryPresetsLoaded = true;
1725 
1726  return mFactoryPresetNames;
1727 }
1728 
1730 {
1731  if (id < 0 || id >= (int) mFactoryPresetUris.size())
1732  {
1733  return false;
1734  }
1735 
1736  LilvNode *preset = lilv_new_uri(gWorld, mFactoryPresetUris[id].ToUTF8());
1737  if (!preset)
1738  {
1739  return false;
1740  }
1741 
1742  LilvState *state = lilv_state_new_from_world(gWorld, &mURIDMapFeature, preset);
1743  if (state)
1744  {
1745  lilv_state_restore(state, mMaster->GetInstance(), set_value_func, this, 0, NULL);
1746 
1747  lilv_state_free(state);
1748 
1750  }
1751 
1752  lilv_node_free(preset);
1753 
1754  return state != NULL;
1755 }
1756 
1758 {
1760  {
1761  return false;
1762  }
1763 
1764  return TransferDataToWindow();
1765 }
1766 
1768 {
1769  return false;
1770 }
1771 
1773 {
1774 }
1775 
1777 {
1778 }
1779 
1781 {
1782  return true;
1783 }
1784 
1786 {
1787  LV2EffectSettingsDialog dlg(mParent, this);
1788  if (dlg.ShowModal() == wxID_OK)
1789  {
1790  // Reinitialize configuration settings
1791  int userBlockSize;
1792  mHost->GetSharedConfig(wxT("Settings"), wxT("BufferSize"), userBlockSize, DEFAULT_BLOCKSIZE);
1793  mUserBlockSize = std::max(1, userBlockSize);
1794  mHost->GetSharedConfig(wxT("Settings"), wxT("UseLatency"), mUseLatency, true);
1795  }
1796 }
1797 
1798 // ============================================================================
1799 // LV2Effect Implementation
1800 // ============================================================================
1801 
1803 {
1804  wxString parms;
1805  if (!mHost->GetPrivateConfig(group, wxT("Parameters"), parms, wxEmptyString))
1806  {
1807  return false;
1808  }
1809 
1810  CommandParameters eap;
1811  if (!eap.SetParameters(parms))
1812  {
1813  return false;
1814  }
1815 
1816  return SetAutomationParameters(eap);
1817 }
1818 
1820 {
1821  CommandParameters eap;
1822  if (!GetAutomationParameters(eap))
1823  {
1824  return false;
1825  }
1826 
1827  wxString parms;
1828  if (!eap.GetParameters(parms))
1829  {
1830  return false;
1831  }
1832 
1833  return mHost->SetPrivateConfig(group, wxT("Parameters"), parms);
1834 }
1835 
1836 size_t LV2Effect::AddOption(LV2_URID key, uint32_t size, LV2_URID type, const void *value)
1837 {
1838  int ndx = mOptions.size();
1839  mOptions.resize(1 + ndx);
1840 
1841  memset(&mOptions[ndx], 0, sizeof(mOptions[ndx]));
1842 
1843  if (key != 0)
1844  {
1845  mOptions[ndx].context = LV2_OPTIONS_INSTANCE;
1846  mOptions[ndx].subject = 0;
1847  mOptions[ndx].key = key;
1848  mOptions[ndx].size = size;
1849  mOptions[ndx].type = type;
1850  mOptions[ndx].value = value;
1851  }
1852 
1853  return ndx;
1854 }
1855 
1856 LV2_Feature *LV2Effect::AddFeature(const char *uri, void *data)
1857 {
1858  size_t ndx = mFeatures.size();
1859  mFeatures.resize(1 + ndx);
1860 
1861  if (uri)
1862  {
1863  mFeatures[ndx].reset(safenew LV2_Feature);
1864  mFeatures[ndx]->URI = uri;
1865  mFeatures[ndx]->data = data;
1866  }
1867 
1868  return mFeatures[ndx].get();
1869 }
1870 
1871 bool LV2Effect::ValidateFeatures(const LilvNode *subject)
1872 {
1873  if (CheckFeatures(subject, node_RequiredFeature, true))
1874  {
1875  return CheckFeatures(subject, node_OptionalFeature, false);
1876  }
1877 
1878  return false;
1879 }
1880 
1881 bool LV2Effect::CheckFeatures(const LilvNode *subject, const LilvNode *predicate, bool required)
1882 {
1883  bool supported = true;
1884 
1885  LilvNodes *nodes = lilv_world_find_nodes(gWorld, subject, predicate, NULL);
1886  if (nodes)
1887  {
1888  LILV_FOREACH(nodes, i, nodes)
1889  {
1890  const LilvNode *node = lilv_nodes_get(nodes, i);
1891  const char *uri = lilv_node_as_string(node);
1892 
1893  if ((strcmp(uri, LV2_UI__noUserResize) == 0) ||
1894  (strcmp(uri, LV2_UI__fixedSize) == 0))
1895  {
1896  mNoResize = true;
1897  }
1898  else if (strcmp(uri, LV2_WORKER__schedule) == 0)
1899  {
1900  /* Supported but handled in LV2Wrapper */
1901  }
1902  else
1903  {
1904  supported = false;
1905 
1906  for (auto & feature : mFeatures)
1907  {
1908  if (feature && strcmp(feature->URI, uri) == 0)
1909  {
1910  supported = true;
1911  break;
1912  }
1913  }
1914 
1915  if (!supported)
1916  {
1917  if (required)
1918  {
1919  wxLogError(wxT("%s requires unsupported feature %s"), lilv_node_as_string(lilv_plugin_get_uri(mPlug)), uri);
1920  printf(_("%s requires unsupported feature %s\n"), lilv_node_as_string(lilv_plugin_get_uri(mPlug)), uri);
1921  break;
1922  }
1923  supported = true;
1924  }
1925  }
1926  }
1927 
1928  lilv_nodes_free(nodes);
1929  }
1930 
1931 
1932  return supported;
1933 }
1934 
1935 bool LV2Effect::ValidateOptions(const LilvNode *subject)
1936 {
1937  if (CheckOptions(subject, node_RequiredOption, true))
1938  {
1939  return CheckOptions(subject, node_SupportedOption, false);
1940  }
1941 
1942  return false;
1943 }
1944 
1945 bool LV2Effect::CheckOptions(const LilvNode *subject, const LilvNode *predicate, bool required)
1946 {
1947  bool supported = true;
1948 
1949  LilvNodes *nodes = lilv_world_find_nodes(gWorld, subject, predicate, NULL);
1950  if (nodes)
1951  {
1952  LILV_FOREACH(nodes, i, nodes)
1953  {
1954  const LilvNode *node = lilv_nodes_get(nodes, i);
1955  const char *uri = lilv_node_as_string(node);
1956  LV2_URID urid = URID_Map(uri);
1957 
1958  if (urid == urid_NominalBlockLength)
1959  {
1961  }
1962  else if (urid == urid_SampleRate)
1963  {
1964  mSupportsSampleRate = true;
1965  }
1966  else
1967  {
1968  supported = false;
1969 
1970  for (auto & option : mOptions)
1971  {
1972  if (option.key == urid)
1973  {
1974  supported = true;
1975  break;
1976  }
1977  }
1978 
1979  if (!supported)
1980  {
1981  if (required)
1982  {
1983  wxLogError(wxT("%s requires unsupported option %s"), lilv_node_as_string(lilv_plugin_get_uri(mPlug)), uri);
1984  printf(_("%s requires unsupported option %s\n"), lilv_node_as_string(lilv_plugin_get_uri(mPlug)), uri);
1985  break;
1986  }
1987  supported = true;
1988  }
1989  }
1990  }
1991 
1992  lilv_nodes_free(nodes);
1993  }
1994 
1995  return supported;
1996 }
1997 
1999 {
2000  LV2Wrapper *wrapper = new LV2Wrapper(this);
2001  if (wrapper == NULL)
2002  {
2003  return NULL;
2004  }
2005 
2006  LilvInstance *instance = wrapper->Instantiate(mPlug, sampleRate, mFeatures);
2007  if (!instance)
2008  {
2009  delete wrapper;
2010  return NULL;
2011  }
2012 
2013  wrapper->SetBlockSize();
2014  wrapper->SetSampleRate();
2015 
2016  // Connect all control ports
2017  for (auto & port : mControlPorts)
2018  {
2019  // If it's not an input port and master has already been created
2020  // then connect the port to a dummy field since slave output port
2021  // values are unwanted as the master values will be used.
2022  //
2023  // Otherwise, connect it to the real value field.
2024  lilv_instance_connect_port(instance,
2025  port->mIndex,
2026  !port->mIsInput && mMaster
2027  ? &port->mDmy
2028  : &port->mVal);
2029  }
2030 
2031  // Connect all atom ports
2032  for (auto & port : mAtomPorts)
2033  {
2034  lilv_instance_connect_port(instance, port->mIndex, port->mBuffer.data());
2035  }
2036 
2037  // We don't fully support CV ports, so connect them to dummy buffers for now.
2038  for (auto & port : mCVPorts)
2039  {
2040  lilv_instance_connect_port(instance, port->mIndex, port->mBuffer.get());
2041  }
2042 
2043  // Give plugin a chance to initialize. The SWH plugins (like AllPass) need
2044  // this before it can be safely deleted.
2045  lilv_instance_activate(instance);
2046  lilv_instance_deactivate(instance);
2047 
2048  for (auto & port : mAtomPorts)
2049  {
2050  if (!port->mIsInput)
2051  {
2052  ZixRing *ring = port->mRing;
2053 
2054  LV2_ATOM_SEQUENCE_FOREACH(( LV2_Atom_Sequence *) port->mBuffer.data(), ev)
2055  {
2056  zix_ring_write(ring, &ev->body, ev->body.size + sizeof(LV2_Atom));
2057  }
2058  }
2059  }
2060 
2061  return wrapper;
2062 }
2063 
2065 {
2066  delete wrapper;
2067 }
2068 
2070 {
2071  // Set the native UI type
2072  const char *nativeType =
2073 #if defined(__WXGTK3__)
2074  LV2_UI__Gtk3UI;
2075 #elif defined(__WXGTK__)
2076  LV2_UI__GtkUI;
2077 #elif defined(__WXMSW__)
2078  LV2_UI__WindowsUI;
2079 #elif defined(__WXMAC__)
2080  LV2_UI__CocoaUI;
2081 #endif
2082 
2083  // Determine if the plugin has a supported UI
2084  const LilvUI *ui = NULL;
2085  const LilvNode *uiType = NULL;
2086  LilvUIs *uis = lilv_plugin_get_uis(mPlug);
2087  if (uis)
2088  {
2089  LilvNode *containerType = lilv_new_uri(gWorld, nativeType);
2090  if (containerType)
2091  {
2092  LILV_FOREACH(uis, iter, uis)
2093  {
2094  ui = lilv_uis_get(uis, iter);
2095  if (lilv_ui_is_supported(ui, suil_ui_supported, containerType, &uiType))
2096  {
2097  break;
2098  }
2099  if (lilv_ui_is_a(ui, node_Gtk) || lilv_ui_is_a(ui, node_Gtk3))
2100  {
2101  uiType = node_Gtk;
2102  break;
2103  }
2104 
2105  ui = NULL;
2106  }
2107 
2108  lilv_node_free(containerType);
2109  }
2110  }
2111 
2112  // Check for other supported UIs
2113  if (ui == NULL)
2114  {
2115  LILV_FOREACH(uis, iter, uis)
2116  {
2117  ui = lilv_uis_get(uis, iter);
2118  if (lilv_ui_is_a(ui, node_ExternalUI) || lilv_ui_is_a(ui, node_ExternalUIOld))
2119  {
2120  uiType = node_ExternalUI;
2121  break;
2122  }
2123  ui = NULL;
2124  }
2125  }
2126 
2127  // No usable UI found
2128  if (ui == NULL)
2129  {
2130  lilv_uis_free(uis);
2131  return false;
2132  }
2133 
2134  const LilvNode *uinode = lilv_ui_get_uri(ui);
2135  lilv_world_load_resource(gWorld, uinode);
2136  if (!ValidateFeatures(uinode))
2137  {
2138  lilv_uis_free(uis);
2139  return false;
2140  }
2141 
2142  const char *containerType;
2143 
2144  if (uiType == node_ExternalUI)
2145  {
2146  containerType = LV2_EXTERNAL_UI__Widget;
2147  }
2148  else
2149  {
2150  containerType = nativeType;
2151  mParentFeature->data = mParent->GetHandle();
2152 
2153 #if defined(__WXGTK__)
2154  // Make sure the parent has a window
2155  if (!gtk_widget_get_window(GTK_WIDGET(mParent->m_wxwindow)))
2156  {
2157  gtk_widget_realize(GTK_WIDGET(mParent->m_wxwindow));
2158  }
2159 #endif
2160  }
2161 
2162  LilvInstance *instance = mMaster->GetInstance();
2163  mInstanceAccessFeature->data = lilv_instance_get_handle(instance);
2164  mExtensionDataFeature.data_access = lilv_instance_get_descriptor(instance)->extension_data;
2165 
2166  // Set before creating the UI instance so the initial size (if any) can be captured
2167  mNativeWinInitialSize = wxDefaultSize;
2168  mNativeWinLastSize = wxDefaultSize;
2169 
2170  // Create the suil host
2173  NULL,
2174  NULL);
2175  if (!mSuilHost)
2176  {
2177  lilv_uis_free(uis);
2178  return false;
2179  }
2180 
2181 #if defined(__WXMSW__)
2182  // Plugins may have dependencies that need to be loaded from the same path
2183  // as the main DLL, so add this plugin's path to the DLL search order.
2184  char *libPath = lilv_file_uri_parse(lilv_node_as_uri(lilv_ui_get_binary_uri(ui)), NULL);
2185  wxString path = wxPathOnly(libPath);
2186  SetDllDirectory(path.c_str());
2187  lilv_free(libPath);
2188 #endif
2189 
2190  char *bundlePath = lilv_file_uri_parse(lilv_node_as_uri(lilv_ui_get_bundle_uri(ui)), NULL);
2191  char *binaryPath = lilv_file_uri_parse(lilv_node_as_uri(lilv_ui_get_binary_uri(ui)), NULL);
2192 
2193  mSuilInstance = suil_instance_new(mSuilHost,
2194  this,
2195  containerType,
2196  lilv_node_as_uri(lilv_plugin_get_uri(mPlug)),
2197  lilv_node_as_uri(lilv_ui_get_uri(ui)),
2198  lilv_node_as_uri(uiType),
2199  bundlePath,
2200  binaryPath,
2201  reinterpret_cast<const LV2_Feature * const *>(mFeatures.data()));
2202 
2203  lilv_free(binaryPath);
2204  lilv_free(bundlePath);
2205  lilv_uis_free(uis);
2206 
2207  // Bail if the instance (no compatible UI) couldn't be created
2208  if (!mSuilInstance)
2209  {
2210 #if defined(__WXMSW__)
2211  SetDllDirectory(NULL);
2212 #endif
2213 
2214  suil_host_free(mSuilHost);
2215  mSuilHost = NULL;
2216 
2217  return false;
2218  }
2219 
2220  if (uiType == node_ExternalUI)
2221  {
2222  mParent->SetMinSize(wxDefaultSize);
2223 
2224  mExternalWidget = (LV2_External_UI_Widget *) suil_instance_get_widget(mSuilInstance);
2225  mTimer.SetOwner(this, ID_TIMER);
2226  mTimer.Start(20);
2227 
2229  }
2230  else
2231  {
2232  WXWidget widget = (WXWidget) suil_instance_get_widget(mSuilInstance);
2233 
2234 #if defined(__WXGTK__)
2235  // Needed by some plugins (e.g., Invada) to ensure the display is fully
2236  // populated.
2237  gtk_widget_show_all(widget);
2238 
2239  // See note at size_request()
2240  g_signal_connect(widget, "size-request", G_CALLBACK(LV2Effect::size_request), this);
2241 #endif
2242 
2244  if ( !uNativeWin->Create(mParent, widget) )
2245  return false;
2246  mNativeWin = uNativeWin.release();
2247 
2248  mNativeWin->Bind(wxEVT_SIZE, &LV2Effect::OnSize, this);
2249 
2250  // The plugin called the LV2UI_Resize::ui_resize function to set the size before
2251  // the native window was created, so set the size now.
2252  if (mNativeWinInitialSize != wxDefaultSize)
2253  {
2254  mNativeWin->SetMinSize(mNativeWinInitialSize);
2255  }
2256 
2257  wxSizerItem *si = NULL;
2258  auto vs = std::make_unique<wxBoxSizer>(wxVERTICAL);
2259  if (vs)
2260  {
2261  auto hs = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
2262  if (hs)
2263  {
2264  if (mNoResize)
2265  {
2266  si = hs->Add(mNativeWin, 0, wxCENTER);
2267  vs->Add(hs.release(), 1, wxCENTER);
2268  }
2269  else
2270  {
2271  si = hs->Add(mNativeWin, 1, wxEXPAND);
2272  vs->Add(hs.release(), 1, wxEXPAND);
2273  }
2274  }
2275  }
2276 
2277  if (!si)
2278  {
2279  lilv_uis_free(uis);
2280  return false;
2281  }
2282 
2283  mParent->SetSizerAndFit(vs.release());
2284  }
2285 
2286  mUIIdleInterface = (LV2UI_Idle_Interface *)
2287  suil_instance_extension_data(mSuilInstance, LV2_UI__idleInterface);
2288 
2289  mUIShowInterface = (LV2UI_Show_Interface *)
2290  suil_instance_extension_data(mSuilInstance, LV2_UI__showInterface);
2291 
2292  if (mUIShowInterface)
2293  {
2294 // mUIShowInterface->show(suil_instance_get_handle(mSuilInstance));
2295  }
2296 
2298 
2299 #ifdef __WXMAC__
2300 #ifdef __WX_EVTLOOP_BUSY_WAITING__
2301  wxEventLoop::SetBusyWaiting(true);
2302 #endif
2303 #endif
2304 
2305 #if defined(__WXMSW__)
2306  SetDllDirectory(NULL);
2307 #endif
2308 
2309  return true;
2310 }
2311 
2313 {
2314  int numCols = 5;
2315  wxSizer *innerSizer;
2316 
2317  wxASSERT(mParent); // To justify safenew
2318  wxScrolledWindow *const w = safenew
2319  wxScrolledWindow(mParent,
2320  wxID_ANY,
2321  wxDefaultPosition,
2322  wxDefaultSize,
2323  wxVSCROLL | wxTAB_TRAVERSAL);
2324 
2325  {
2326  auto outerSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
2327  w->SetScrollRate(0, 20);
2328 
2329  // This fools NVDA into not saying "Panel" when the dialog gets focus
2330  w->SetName(wxT("\a"));
2331  w->SetLabel(wxT("\a"));
2332 
2333  outerSizer->Add(w, 1, wxEXPAND);
2334 
2335  {
2336  auto uInnerSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
2337  innerSizer = uInnerSizer.get();
2338 
2339  if (GetType() == EffectTypeGenerate)
2340  {
2341  // Add the length control
2342  auto groupSizer = std::make_unique<wxStaticBoxSizer>(wxVERTICAL, w, _("Generator"));
2343 
2344  auto sizer = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
2345 
2346  wxWindow *item = safenew wxStaticText(w, 0, _("&Duration:"));
2347  sizer->Add(item, 0, wxALIGN_CENTER | wxALL, 5);
2348  mDuration = safenew
2352  mHost->GetDuration(),
2353  mSampleRate,
2355  .AutoPos(true));
2356  mDuration->SetName( XO("Duration") );
2357  sizer->Add(mDuration, 0, wxALIGN_CENTER | wxALL, 5);
2358 
2359  groupSizer->Add(sizer.release(), 0, wxALIGN_CENTER | wxALL, 5);
2360  innerSizer->Add(groupSizer.release(), 0, wxEXPAND | wxALL, 5);
2361  }
2362 
2363  std::sort(mGroups.begin(), mGroups.end());
2364 
2365  for (size_t i = 0, groupCount = mGroups.size(); i < groupCount; i++)
2366  {
2367  wxString label = mGroups[i];
2368  auto groupSizer = std::make_unique<wxStaticBoxSizer>(wxVERTICAL, w, label);
2369 
2370  auto gridSizer = std::make_unique<wxFlexGridSizer>(numCols, 5, 5);
2371  gridSizer->AddGrowableCol(3);
2372 
2373  for (auto & p : mGroupMap[mGroups[i]])
2374  {
2375  auto & port = mControlPorts[p];
2376 
2377  if (port->mNotOnGui)
2378  {
2379  continue;
2380  }
2381 
2382  wxString labelText = port->mName;
2383  if (!port->mUnits.empty())
2384  {
2385  labelText += wxT(" (") + port->mUnits + wxT(")");
2386  }
2387 
2388  if (port->mTrigger)
2389  {
2390  gridSizer->Add(1, 1, 0);
2391 
2392  wxASSERT(w); // To justify safenew
2393  wxButton *b = safenew wxButton(w, ID_Triggers + p, labelText);
2394  gridSizer->Add(b, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
2395  port->mCtrl.button = b;
2396 
2397  gridSizer->Add(1, 1, 0);
2398  gridSizer->Add(1, 1, 0);
2399  gridSizer->Add(1, 1, 0);
2400  continue;
2401  }
2402 
2403  wxWindow *item = safenew wxStaticText(w, wxID_ANY, labelText + wxT(":"),
2404  wxDefaultPosition, wxDefaultSize,
2405  wxALIGN_RIGHT);
2406  gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
2407 
2408  if (port->mToggle)
2409  {
2410  wxCheckBox *c = safenew wxCheckBox(w, ID_Toggles + p, wxT(""));
2411  c->SetName(labelText);
2412  c->SetValue(port->mVal > 0);
2413  gridSizer->Add(c, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
2414  port->mCtrl.checkbox = c;
2415 
2416  gridSizer->Add(1, 1, 0);
2417  gridSizer->Add(1, 1, 0);
2418  gridSizer->Add(1, 1, 0);
2419  }
2420  else if (port->mEnumeration) // Check before integer
2421  {
2422  int s;
2423  for (s = (int) port->mScaleValues.size() - 1; s >= 0; s--)
2424  {
2425  if (port->mVal >= port->mScaleValues[s])
2426  {
2427  break;
2428  }
2429  }
2430 
2431  if (s < 0)
2432  {
2433  s = 0;
2434  }
2435 
2436  wxChoice *c = safenew wxChoice(w, ID_Choices + p);
2437  c->SetName(labelText);
2438  c->Append(port->mScaleLabels);
2439  c->SetSelection(s);
2440  gridSizer->Add(c, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
2441  port->mCtrl.choice = c;
2442 
2443  gridSizer->Add(1, 1, 0);
2444  gridSizer->Add(1, 1, 0);
2445  gridSizer->Add(1, 1, 0);
2446  }
2447  else if (!port->mIsInput)
2448  {
2449  gridSizer->Add(1, 1, 0);
2450  gridSizer->Add(1, 1, 0);
2451 
2452  LV2EffectMeter *m = safenew LV2EffectMeter(w, port);
2453  gridSizer->Add(m, 0, wxALIGN_CENTER_VERTICAL | wxEXPAND);
2454  port->mCtrl.meter = m;
2455 
2456  gridSizer->Add(1, 1, 0);
2457  }
2458  else
2459  {
2460  wxTextCtrl *t = safenew wxTextCtrl(w, ID_Texts + p, wxT(""));
2461  t->SetName(labelText);
2462  gridSizer->Add(t, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
2463  port->mText = t;
2464 
2465  float rate = port->mSampleRate ? mSampleRate : 1.0;
2466 
2467  port->mLo = port->mMin * rate;
2468  port->mHi = port->mMax * rate;
2469  port->mTmp = port->mVal * rate;
2470 
2471  if (port->mInteger)
2472  {
2473  IntegerValidator<float> vld(&port->mTmp);
2474  vld.SetRange(port->mLo, port->mHi);
2475  t->SetValidator(vld);
2476  }
2477  else
2478  {
2479  FloatingPointValidator<float> vld(6, &port->mTmp);
2480  vld.SetRange(port->mLo, port->mHi);
2481 
2482  // Set number of decimal places
2483  float range = port->mHi - port->mLo;
2484  auto style = range < 10
2485  ? NumValidatorStyle::THREE_TRAILING_ZEROES
2486  : range < 100
2487  ? NumValidatorStyle::TWO_TRAILING_ZEROES
2488  : NumValidatorStyle::ONE_TRAILING_ZERO;
2489  vld.SetStyle(style);
2490 
2491  t->SetValidator(vld);
2492  }
2493 
2494  if (port->mHasLo)
2495  {
2496  wxString str;
2497  if (port->mInteger || port->mSampleRate)
2498  {
2499  str.Printf(wxT("%d"), (int) lrintf(port->mLo));
2500  }
2501  else
2502  {
2503  str = Internat::ToDisplayString(port->mLo);
2504  }
2505  item = safenew wxStaticText(w, wxID_ANY, str);
2506  gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
2507  }
2508  else
2509  {
2510  gridSizer->Add(1, 1, 0);
2511  }
2512 
2513  wxSlider *s = safenew wxSliderWrapper(w, ID_Sliders + p,
2514  0, 0, 1000,
2515  wxDefaultPosition,
2516  wxSize(150, -1));
2517  s->SetName(labelText);
2518  gridSizer->Add(s, 0, wxALIGN_CENTER_VERTICAL | wxEXPAND);
2519  port->mCtrl.slider = s;
2520 
2521  if (port->mHasHi)
2522  {
2523  wxString str;
2524  if (port->mInteger || port->mSampleRate)
2525  {
2526  str.Printf(wxT("%d"), (int) lrintf(port->mHi));
2527  }
2528  else
2529  {
2530  str = Internat::ToDisplayString(port->mHi);
2531  }
2532  item = safenew wxStaticText(w, wxID_ANY, str);
2533  gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
2534  }
2535  else
2536  {
2537  gridSizer->Add(1, 1, 0);
2538  }
2539  }
2540  }
2541 
2542  groupSizer->Add(gridSizer.release(), 1, wxEXPAND | wxALL, 5);
2543  innerSizer->Add(groupSizer.release(), 0, wxEXPAND | wxALL, 5);
2544  }
2545 
2546  innerSizer->Layout();
2547 
2548  // Calculate the maximum width of all columns (bypass Generator sizer)
2549  std::vector<int> widths(numCols);
2550 
2551  size_t cnt = innerSizer->GetChildren().GetCount();
2552  for (size_t i = (GetType() == EffectTypeGenerate); i < cnt; i++)
2553  {
2554  wxSizer *groupSizer = innerSizer->GetItem(i)->GetSizer();
2555  wxFlexGridSizer *gridSizer = (wxFlexGridSizer *) groupSizer->GetItem((size_t) 0)->GetSizer();
2556 
2557  size_t items = gridSizer->GetChildren().GetCount();
2558  int cols = gridSizer->GetCols();
2559 
2560  for (size_t j = 0; j < items; j++)
2561  {
2562  wxSizerItem *item = gridSizer->GetItem(j);
2563  widths[j % cols] = wxMax(widths[j % cols], item->GetSize().GetWidth());
2564  }
2565  }
2566 
2567  // Set each column in all of the groups to the same width.
2568  for (size_t i = (GetType() == EffectTypeGenerate); i < cnt; i++)
2569  {
2570  wxSizer *groupSizer = innerSizer->GetItem(i)->GetSizer();
2571  wxFlexGridSizer *gridSizer = (wxFlexGridSizer *) groupSizer->GetItem((size_t) 0)->GetSizer();
2572 
2573  size_t items = gridSizer->GetChildren().GetCount();
2574  int cols = gridSizer->GetCols();
2575 
2576  for (size_t j = 0; j < items; j++)
2577  {
2578  wxSizerItem *item = gridSizer->GetItem(j);
2579 
2580  int flags = item->GetFlag();
2581  if (flags & wxEXPAND)
2582  {
2583  continue;
2584  }
2585 
2586  if (flags & wxALIGN_RIGHT)
2587  {
2588  flags = (flags & ~wxALL) | wxLEFT;
2589  }
2590  else
2591  {
2592  flags = (flags & ~wxALL) | wxRIGHT;
2593  }
2594  item->SetFlag(flags);
2595 
2596  item->SetBorder(widths[j % cols] - item->GetMinSize().GetWidth());
2597  }
2598  }
2599 
2600  w->SetSizer(uInnerSizer.release());
2601  }
2602 
2603  mParent->SetSizer(outerSizer.release());
2604  }
2605 
2606  // Try to give the window a sensible default/minimum size
2607  wxSize sz1 = innerSizer->GetMinSize();
2608  wxSize sz2 = mParent->GetMinSize();
2609  w->SetMinSize( { -1, std::min(sz1.y, sz2.y) } );
2610 
2611  // And let the parent reduce to the NEW minimum if possible
2612  mParent->SetMinSize(w->GetMinSize());
2613 
2615 
2616  return true;
2617 }
2618 
2620 {
2621  if (mUseGUI)
2622  {
2623  if (mSuilInstance)
2624  {
2625  for (auto & port : mControlPorts)
2626  {
2627  if (port->mIsInput)
2628  {
2629  suil_instance_port_event(mSuilInstance,
2630  port->mIndex,
2631  sizeof(float),
2632  0,
2633  &port->mVal);
2634  }
2635  }
2636  }
2637 
2638  return true;
2639  }
2640 
2641  for (auto & group : mGroups)
2642  {
2643  const auto & params = mGroupMap[group];
2644  for (auto & param : params)
2645  {
2646  auto & port = mControlPorts[param];
2647 
2648  if (port->mTrigger)
2649  {
2650  continue;
2651  }
2652 
2653  if (port->mToggle)
2654  {
2655  port->mCtrl.checkbox->SetValue(port->mVal > 0);
2656  }
2657  else if (port->mEnumeration) // Check before integer
2658  {
2659  int s;
2660  for (s = (int) port->mScaleValues.size() - 1; s >= 0; s--)
2661  {
2662  if (port->mVal >= port->mScaleValues[s])
2663  {
2664  break;
2665  }
2666  }
2667 
2668  if (s < 0)
2669  {
2670  s = 0;
2671  }
2672 
2673  port->mCtrl.choice->SetSelection(s);
2674  }
2675  else if (port->mIsInput)
2676  {
2677  port->mTmp = port->mVal * (port->mSampleRate ? mSampleRate : 1.0);
2678  SetSlider(port);
2679  }
2680  }
2681  }
2682 
2683  if (mParent && !mParent->TransferDataToWindow())
2684  {
2685  return false;
2686  }
2687 
2688  return true;
2689 }
2690 
2692 {
2693  if (!mParent->Validate() || !mParent->TransferDataFromWindow())
2694  {
2695  return false;
2696  }
2697 
2698  return true;
2699 }
2700 
2702 {
2703  float lo = port->mLo;
2704  float hi = port->mHi;
2705  float val = port->mTmp;
2706 
2707  if (port->mLogarithmic)
2708  {
2709  lo = logf(lo);
2710  hi = logf(hi);
2711  val = logf(val);
2712  }
2713 
2714  port->mCtrl.slider->SetValue(lrintf((val - lo) / (hi - lo) * 1000.0));
2715 }
2716 
2717 void LV2Effect::OnTrigger(wxCommandEvent &evt)
2718 {
2719  auto & port = mControlPorts[evt.GetId() - ID_Triggers];
2720 
2721  port->mVal = port->mDef;
2722 }
2723 
2724 void LV2Effect::OnToggle(wxCommandEvent &evt)
2725 {
2726  auto & port = mControlPorts[evt.GetId() - ID_Toggles];
2727 
2728  port->mVal = evt.GetInt() ? 1.0 : 0.0;
2729 }
2730 
2731 void LV2Effect::OnChoice(wxCommandEvent &evt)
2732 {
2733  auto & port = mControlPorts[evt.GetId() - ID_Choices];
2734 
2735  port->mVal = port->mScaleValues[evt.GetInt()];
2736 }
2737 
2738 void LV2Effect::OnText(wxCommandEvent &evt)
2739 {
2740  auto & port = mControlPorts[evt.GetId() - ID_Texts];
2741 
2742  if (port->mText->GetValidator()->TransferFromWindow())
2743  {
2744  port->mVal = port->mSampleRate ? port->mTmp / mSampleRate : port->mTmp;
2745 
2746  SetSlider(port);
2747  }
2748 }
2749 
2750 void LV2Effect::OnSlider(wxCommandEvent &evt)
2751 {
2752  auto & port = mControlPorts[evt.GetId() - ID_Sliders];
2753 
2754  float lo = port->mLo;
2755  float hi = port->mHi;
2756 
2757  if (port->mLogarithmic)
2758  {
2759  lo = logf(lo);
2760  hi = logf(hi);
2761  }
2762 
2763  port->mTmp = (((float) evt.GetInt()) / 1000.0) * (hi - lo) + lo;
2764  port->mTmp = port->mLogarithmic ? expf(port->mTmp) : port->mTmp;
2765 
2766  port->mTmp = port->mTmp < port->mLo ? port->mLo : port->mTmp;
2767  port->mTmp = port->mTmp > port->mHi ? port->mHi : port->mTmp;
2768 
2769  port->mVal = port->mSampleRate ? port->mTmp / mSampleRate : port->mTmp;
2770 
2771  port->mText->GetValidator()->TransferToWindow();
2772 }
2773 
2774 void LV2Effect::OnTimer(wxTimerEvent &evt)
2775 {
2776  evt.Skip();
2777 
2778  if (mExternalWidget)
2779  {
2781  }
2782 }
2783 
2784 void LV2Effect::OnIdle(wxIdleEvent &evt)
2785 {
2786  evt.Skip();
2787 
2788  if (!mSuilInstance)
2789  {
2790  return;
2791  }
2792 
2793  if (mExternalUIClosed)
2794  {
2795  mExternalUIClosed = false;
2796  mDialog->Close();
2797  return;
2798  }
2799 
2800  if (mUIIdleInterface)
2801  {
2802  SuilHandle handle = suil_instance_get_handle(mSuilInstance);
2803  if (mUIIdleInterface->idle(handle))
2804  {
2805  if (mUIShowInterface)
2806  {
2807  mUIShowInterface->hide(handle);
2808  }
2809  mDialog->Close();
2810  return;
2811  }
2812  }
2813 
2814  if (mControlOut)
2815  {
2816  ZixRing *ring = mControlOut->mRing;
2817 
2818  LV2_Atom *atom = (LV2_Atom *) malloc(mControlOut->mMinimumSize);
2819  if (atom)
2820  {
2821  while (zix_ring_read(ring, atom, sizeof(LV2_Atom)))
2822  {
2823  uint32_t size = lv2_atom_total_size(atom);
2824 
2825  if (size < mControlOut->mMinimumSize)
2826  {
2827  zix_ring_read(ring, LV2_ATOM_CONTENTS(LV2_Atom, atom), atom->size);
2828  suil_instance_port_event(mSuilInstance,
2829  mControlOut->mIndex,
2830  size,
2831  urid_EventTransfer,
2832  atom);
2833  }
2834  else
2835  {
2836  zix_ring_skip(ring, atom->size);
2837  wxLogError(wxT("LV2 sequence buffer overflow"));
2838  }
2839  }
2840  free(atom);
2841  }
2842  }
2843 
2844  for (auto & port : mControlPorts)
2845  {
2846  // Let UI know that a port's value has changed
2847  if (port->mVal != port->mLst)
2848  {
2849  suil_instance_port_event(mSuilInstance,
2850  port->mIndex,
2851  sizeof(port->mVal),
2852  0,
2853  &port->mVal);
2854  port->mLst = port->mVal;
2855  }
2856  }
2857 }
2858 
2859 void LV2Effect::OnSize(wxSizeEvent & evt)
2860 {
2861  evt.Skip();
2862 
2863  // Don't do anything here if we're recursing
2864  if (mResizing)
2865  {
2866  return;
2867  }
2868 
2869  // Indicate resizing is occurring
2870  mResizing = true;
2871 
2872  // Can only resize AFTER the dialog has been completely created and
2873  // there's no need to resize if we're already at the desired size.
2874  if (mDialog && evt.GetSize() != mNativeWinLastSize)
2875  {
2876  // Save the desired size and set the native window to match
2877  mNativeWinLastSize = evt.GetSize();
2878  mNativeWin->SetMinSize(mNativeWinLastSize);
2879 
2880  // Clear the minimum size of the parent window to allow the following
2881  // Fit() to make proper adjustments
2882  mParent->SetMinSize(wxDefaultSize);
2883 
2884 #if defined(__WXGTK__)
2885  // If the user resized the native window, then we need to also
2886  // clear the dialogs minimum size. If this isn't done, the dialog
2887  // will not resize properly when going from a larger size to a smaller
2888  // size (due to the minimum size constraint).
2889  //
2890  // In this case, mResized has been set by the "size_request()" function
2891  // to indicate that this is a plugin generated resize request.
2892  if (mResized)
2893  {
2894  mDialog->SetMinSize(wxDefaultSize);
2895  }
2896 
2897  // Resize dialog
2898  mDialog->Fit();
2899 
2900  // Reestablish the minimum (and maximum) now that the dialog
2901  // has is desired size.
2902  if (mResized)
2903  {
2904  mDialog->SetMinSize(mDialog->GetSize());
2905  if (mNoResize)
2906  {
2907  mDialog->SetMaxSize(mDialog->GetSize());
2908  }
2909  }
2910 
2911  // Tell size_request() that the native window was just resized.
2912  mResized = true;
2913 #else
2914  // Resize the dialog to fit its content.
2915  mDialog->Fit();
2916 #endif
2917  }
2918 
2919  // No longer resizing
2920  mResizing = false;
2921 }
2922 
2923 // ============================================================================
2924 // Feature handlers
2925 // ============================================================================
2926 
2927 // static callback
2928 uint32_t LV2Effect::uri_to_id(LV2_URI_Map_Callback_Data callback_data,
2929  const char *WXUNUSED(map),
2930  const char *uri)
2931 {
2932  return ((LV2Effect *) callback_data)->URID_Map(uri);
2933 }
2934 
2935 // static callback
2936 LV2_URID LV2Effect::urid_map(LV2_URID_Map_Handle handle, const char *uri)
2937 {
2938  return ((LV2Effect *) handle)->URID_Map(uri);
2939 }
2940 
2941 LV2_URID LV2Effect::URID_Map(const char *uri)
2942 {
2943  LV2_URID urid;
2944 
2945  urid = Lookup_URI(gURIDMap, uri, false);
2946  if (urid > 0)
2947  {
2948  return urid;
2949  }
2950 
2951  urid = Lookup_URI(mURIDMap, uri);
2952  if (urid > 0)
2953  {
2954  return urid + gURIDMap.size();
2955  }
2956 
2957  return 0;
2958 }
2959 
2960 LV2_URID LV2Effect::Lookup_URI(URIDMap & map, const char *uri, bool add)
2961 {
2962  size_t ndx = map.size();
2963  for (size_t i = 0; i < ndx; i++)
2964  {
2965  if (strcmp(map[i].get(), uri) == 0)
2966  {
2967  return i + 1;
2968  }
2969  }
2970 
2971  if (add)
2972  {
2973  // Almost all compilers have strdup(), but VC++ and MinGW call it _strdup().
2974  map.push_back(MallocString<>(wxCRT_StrdupA(uri)));
2975  return ndx + 1;
2976  }
2977 
2978  return 0;
2979 }
2980 
2981 // static callback
2982 const char *LV2Effect::urid_unmap(LV2_URID_Unmap_Handle handle, LV2_URID urid)
2983 {
2984  return ((LV2Effect *) handle)->URID_Unmap(urid);
2985 }
2986 
2987 const char *LV2Effect::URID_Unmap(LV2_URID urid)
2988 {
2989  if (urid > 0)
2990  {
2991  if (urid <= (LV2_URID) gURIDMap.size())
2992  {
2993  return mURIDMap[urid - 1].get();
2994  }
2995 
2996  urid -= gURIDMap.size();
2997 
2998  if (urid <= (LV2_URID) mURIDMap.size())
2999  {
3000  return mURIDMap[urid - 1].get();
3001  }
3002  }
3003 
3004  return NULL;
3005 }
3006 
3007 // static callback
3008 int LV2Effect::log_printf(LV2_Log_Handle handle, LV2_URID type, const char *fmt, ...)
3009 {
3010  va_list ap;
3011  int len;
3012 
3013  va_start(ap, fmt);
3014  len = ((LV2Effect *) handle)->LogVPrintf(type, fmt, ap);
3015  va_end(ap);
3016 
3017  return len;
3018 }
3019 
3020 // static callback
3021 int LV2Effect::log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char *fmt, va_list ap)
3022 {
3023  return ((LV2Effect *) handle)->LogVPrintf(type, fmt, ap);
3024 }
3025 
3026 int LV2Effect::LogVPrintf(LV2_URID type, const char *fmt, va_list ap)
3027 {
3028  long level = wxLOG_Error;
3029 
3030  if (type == urid_Error)
3031  {
3032  level = wxLOG_Error;
3033  }
3034  else if (type == urid_Note)
3035  {
3036  level = wxLOG_Info;
3037  }
3038  else if (type == urid_Trace)
3039  {
3040  level = wxLOG_Trace;
3041  }
3042  else if (type == urid_Warning)
3043  {
3044  level = wxLOG_Warning;
3045  }
3046  else
3047  {
3048  level = wxLOG_Message;
3049  }
3050 
3051  char *msg = NULL;
3052  int len = wxCRT_VsnprintfA(msg, 0, fmt, ap);
3053 
3054  msg = (char *) malloc(len + 1);
3055  if (msg)
3056  {
3057  wxCRT_VsnprintfA(msg, len, fmt, ap);
3058 
3059  wxString text(msg);
3060 
3061  wxLogGeneric(level, wxT("%s: %s"), GetSymbol().Msgid().Translation(), text);
3062 
3063  free(msg);
3064  }
3065 
3066  return len;
3067 }
3068 
3069 // static callback
3070 int LV2Effect::ui_resize(LV2UI_Feature_Handle handle, int width, int height)
3071 {
3072  return ((LV2Effect *) handle)->UIResize(width, height);
3073 }
3074 
3075 int LV2Effect::UIResize(int width, int height)
3076 {
3077  // Queue a wxSizeEvent to resize the plugins UI
3078  if (mNativeWin)
3079  {
3080  wxSizeEvent sw(wxSize(width, height));
3081  sw.SetEventObject(mNativeWin);
3082  mNativeWin->GetEventHandler()->AddPendingEvent(sw);
3083  }
3084  // The window hasn't been created yet, so record the desired size
3085  else
3086  {
3087  mNativeWinInitialSize = wxSize(width, height);
3088  }
3089 
3090  return 0;
3091 }
3092 
3093 // static callback
3094 void LV2Effect::ui_closed(LV2UI_Controller controller)
3095 {
3096  return ((LV2Effect *) controller)->UIClosed();
3097 }
3098 
3100 {
3101  mExternalUIClosed = true;
3102 
3103  return;
3104 }
3105 
3106 // static callback
3107 void LV2Effect::suil_port_write_func(SuilController controller,
3108  uint32_t port_index,
3109  uint32_t buffer_size,
3110  uint32_t protocol,
3111  const void *buffer)
3112 {
3113  ((LV2Effect *) controller)->SuilPortWrite(port_index, buffer_size, protocol, buffer);
3114 }
3115 
3116 void LV2Effect::SuilPortWrite(uint32_t port_index,
3117  uint32_t buffer_size,
3118  uint32_t protocol,
3119  const void *buffer)
3120 {
3121  // Handle implicit floats
3122  if (protocol == 0 && buffer_size == sizeof(float))
3123  {
3124  auto it = mControlPortMap.find(port_index);
3125  if (it != mControlPortMap.end())
3126  {
3127  it->second->mVal = *((const float *) buffer);
3128  }
3129  }
3130  // Handle event transfers
3131  else if (protocol == urid_EventTransfer)
3132  {
3133  if (mControlIn && port_index == mControlIn->mIndex)
3134  {
3135  zix_ring_write(mControlIn->mRing, buffer, buffer_size);
3136  }
3137  }
3138 
3139  return;
3140 }
3141 
3142 // static callback
3143 uint32_t LV2Effect::suil_port_index_func(SuilController controller,
3144  const char *port_symbol)
3145 {
3146  return ((LV2Effect *) controller)->SuilPortIndex(port_symbol);
3147 }
3148 
3149 uint32_t LV2Effect::SuilPortIndex(const char *port_symbol)
3150 {
3151  for (size_t i = 0, cnt = lilv_plugin_get_num_ports(mPlug); i < cnt; i++)
3152  {
3153  const LilvPort *port = lilv_plugin_get_port_by_index(mPlug, i);
3154  if (strcmp(port_symbol, lilv_node_as_string(lilv_port_get_symbol(mPlug, port))) == 0)
3155  {
3156  return lilv_port_get_index(mPlug, port);
3157  }
3158  }
3159 
3160  return LV2UI_INVALID_PORT_INDEX;
3161 }
3162 
3163 // static callback
3164 const void *LV2Effect::get_value_func(const char *port_symbol,
3165  void *user_data,
3166  uint32_t *size,
3167  uint32_t *type)
3168 {
3169  return ((LV2Effect *) user_data)->GetPortValue(port_symbol, size, type);
3170 }
3171 
3172 const void *LV2Effect::GetPortValue(const char *port_symbol,
3173  uint32_t *size,
3174  uint32_t *type)
3175 {
3176  wxString symbol = wxString::FromUTF8(port_symbol);
3177 
3178  for (auto & port : mControlPorts)
3179  {
3180  if (port->mSymbol == symbol)
3181  {
3182  *size = sizeof(float);
3183  *type = urid_Float;
3184  return (void *) &port->mVal;
3185  }
3186  }
3187 
3188  *size = 0;
3189  *type = 0;
3190 
3191  return NULL;
3192 }
3193 
3194 // static callback
3195 void LV2Effect::set_value_func(const char *port_symbol,
3196  void *user_data,
3197  const void *value,
3198  uint32_t size,
3199  uint32_t type)
3200 {
3201  ((LV2Effect *) user_data)->SetPortValue(port_symbol, value, size, type);
3202 }
3203 
3204 void LV2Effect::SetPortValue(const char *port_symbol,
3205  const void *value,
3206  uint32_t size,
3207  uint32_t type)
3208 {
3209  wxString symbol = wxString::FromUTF8(port_symbol);
3210 
3211  for (auto & port : mControlPorts)
3212  {
3213  if (port->mSymbol == symbol)
3214  {
3215  if (type == urid_Bool && size == sizeof(bool))
3216  {
3217  port->mVal = (float) (*((const bool *) value)) ? 1.0f : 0.0f;
3218  }
3219  else if (type == urid_Double && size == sizeof(double))
3220  {
3221  port->mVal = (float) (*((const double *) value));
3222  }
3223  else if (type == urid_Float && size == sizeof(float))
3224  {
3225  port->mVal = (float) (*((const float *) value));
3226  }
3227  else if (type == urid_Int && size == sizeof(int32_t))
3228  {
3229  port->mVal = (float) (*((const int32_t *) value));
3230  }
3231  else if (type == urid_Long && size == sizeof(int64_t))
3232  {
3233  port->mVal = (float) (*((const int64_t *) value));
3234  }
3235 
3236  break;
3237  }
3238  }
3239 }
3240 
3241 #if defined(__WXGTK__)
3242 // static callback
3243 //
3244 // Need to queue a wxSizeEvent when the native window gets resized outside of
3245 // WX control. Many of the x42 LV2 plugins can resize themselves when changing
3246 // the scale factor. (e.g., open "x42-dpl" effect and right click to change scaling)
3247 void LV2Effect::size_request(GtkWidget *widget, GtkRequisition *requisition, LV2Effect *effect)
3248 {
3249  effect->SizeRequest(widget, requisition);
3250 }
3251 
3252 void LV2Effect::SizeRequest(GtkWidget *widget, GtkRequisition *requisition)
3253 {
3254  // Don't do anything if the OnSize() method is active
3255  if (!mResizing)
3256  {
3257  // If the OnSize() routine has processed an event, mResized will be true,
3258  // so just set the widgets size.
3259  if (mResized)
3260  {
3261  gtk_widget_set_size_request(widget, mNativeWinLastSize.x, mNativeWinLastSize.y);
3262  mResized = false;
3263  }
3264  // Otherwise, the plugin has resized the widget and we need to let WX know
3265  // about it.
3266  else if (mNativeWin)
3267  {
3268  mResized = true;
3269  wxSizeEvent se(wxSize(requisition->width, requisition->height));
3270  se.SetEventObject(mNativeWin);
3271  mNativeWin->GetEventHandler()->AddPendingEvent(se);
3272  }
3273  }
3274 }
3275 #endif
3276 
3278 : mEffect(effect)
3279 {
3280  mInstance = NULL;
3281  mHandle = NULL;
3282  mOptionsInterface = NULL;
3283  mStateInterface = NULL;
3284  mWorkerInterface = NULL;
3285  mWorkerSchedule = {};
3286  mFreeWheeling = false;
3287  mLatency = 0.0;
3288  mStopWorker = false;
3289 }
3290 
3292 {
3293  if (mInstance)
3294  {
3295  wxThread *thread = GetThread();
3296  if (thread && thread->IsAlive())
3297  {
3298  mStopWorker = true;
3299 
3300  LV2Work work = {0, NULL};
3301  mRequests.Post(work);
3302 
3303  thread->Wait();
3304  }
3305 
3306  if (mEffect->mActivated)
3307  {
3308  lilv_instance_deactivate(mInstance);
3309  mEffect->mActivated = false;
3310  }
3311 
3312  lilv_instance_free(mInstance);
3313  mInstance = NULL;
3314  }
3315 }
3316 
3317 LilvInstance *LV2Wrapper::Instantiate(const LilvPlugin *plugin,
3318  double sampleRate,
3319  std::vector<std::unique_ptr<LV2_Feature>> & features)
3320 {
3322  {
3323  // Remove terminator
3324  features.pop_back();
3325 
3326  mWorkerSchedule.handle = this;
3328  mEffect->AddFeature(LV2_WORKER__schedule, &mWorkerSchedule);
3329 
3330  mEffect->AddFeature(NULL, NULL);
3331  }
3332 
3333 #if defined(__WXMSW__)
3334  // Plugins may have dependencies that need to be loaded from the same path
3335  // as the main DLL, so add this plugin's path to the DLL search order.
3336  const LilvNode *const libNode = lilv_plugin_get_library_uri(plugin);
3337  const char *const libUri = lilv_node_as_uri(libNode);
3338  char *libPath = lilv_file_uri_parse(libUri, NULL);
3339  wxString path = wxPathOnly(libPath);
3340  SetDllDirectory(path.c_str());
3341  lilv_free(libPath);
3342 #endif
3343 
3344  mInstance = lilv_plugin_instantiate(plugin,
3345  sampleRate,
3346  reinterpret_cast<LV2_Feature **>(features.data()));
3347 
3348 #if defined(__WXMSW__)
3349  SetDllDirectory(NULL);
3350 #endif
3351 
3353  {
3354  // Remove terminator
3355  features.pop_back();
3356 
3357  // Remove the worker interface feature
3358  features.pop_back();
3359 
3360  // Re-add terminator
3361  mEffect->AddFeature(NULL, NULL);
3362  }
3363 
3364  if (!mInstance)
3365  {
3366  return NULL;
3367  }
3368 
3369  mHandle = lilv_instance_get_handle(mInstance);
3370 
3371  mOptionsInterface = (LV2_Options_Interface *)
3372  lilv_instance_get_extension_data(mInstance, LV2_OPTIONS__interface);
3373 
3374  mStateInterface = (LV2_State_Interface *)
3375  lilv_instance_get_extension_data(mInstance, LV2_STATE__interface);
3376 
3377  mWorkerInterface = (LV2_Worker_Interface *)
3378  lilv_instance_get_extension_data(mInstance, LV2_WORKER__interface);
3379 
3380  if (mEffect->mLatencyPort >= 0)
3381  {
3382  lilv_instance_connect_port(mInstance, mEffect->mLatencyPort, &mLatency);
3383  }
3384 
3385  if (mWorkerInterface)
3386  {
3387  if (CreateThread() == wxTHREAD_NO_ERROR)
3388  {
3389  GetThread()->Run();
3390  }
3391 
3392  }
3393 
3394  return mInstance;
3395 }
3396 
3398 {
3399  return mInstance;
3400 }
3401 
3403 {
3404  return mHandle;
3405 }
3406 
3408 {
3409  return mLatency;
3410 }
3411 
3413 {
3414  mFreeWheeling = enable;
3415 }
3416 
3418 {
3420  {
3421  LV2_Options_Option options[2] = {};
3422 
3423  memcpy(&options,
3425  sizeof(mEffect->mOptions[0]));
3426 
3427  mOptionsInterface->set(mHandle, options);
3428  }
3429 }
3430 
3432 {
3434  {
3435  LV2_Options_Option options[2] = {};
3436  memcpy(&options,
3438  sizeof(mEffect->mOptions[0]));
3439 
3440  mOptionsInterface->set(mHandle, options);
3441  }
3442 }
3443 
3444 void LV2Wrapper::ConnectPorts(float **inbuf, float **outbuf)
3445 {
3446 }
3447 
3449 {
3450  LV2Work work;
3451 
3452  while (mRequests.Receive(work) == wxMSGQUEUE_NO_ERROR)
3453  {
3454  if (mStopWorker)
3455  {
3456  break;
3457  }
3458 
3459  mWorkerInterface->work(mHandle,
3460  respond,
3461  this,
3462  work.size,
3463  work.data);
3464  }
3465 
3466  return (void *) 0;
3467 }
3468 
3470 {
3471  if (mWorkerInterface)
3472  {
3473  LV2Work work;
3474 
3475  while (mResponses.ReceiveTimeout(0, work) == wxMSGQUEUE_NO_ERROR)
3476  {
3477  mWorkerInterface->work_response(mHandle, work.size, work.data);
3478  }
3479 
3480  if (mWorkerInterface->end_run)
3481  {
3482  mWorkerInterface->end_run(mHandle);
3483  }
3484  }
3485 }
3486 
3487 // static callback
3488 LV2_Worker_Status LV2Wrapper::schedule_work(LV2_Worker_Schedule_Handle handle,
3489  uint32_t size,
3490  const void *data)
3491 {
3492  return ((LV2Wrapper *) handle)->ScheduleWork(size, data);
3493 }
3494 
3495 LV2_Worker_Status LV2Wrapper::ScheduleWork(uint32_t size, const void *data)
3496 {
3497  if (mFreeWheeling)
3498  {
3499  return mWorkerInterface->work(mHandle,
3500  respond,
3501  this,
3502  size,
3503  data);
3504  }
3505 
3506  LV2Work work = {size, data};
3507 
3508  mRequests.Post(work);
3509 
3510  return LV2_WORKER_SUCCESS;
3511 }
3512 
3513 // static callback
3514 LV2_Worker_Status LV2Wrapper::respond(LV2_Worker_Respond_Handle handle,
3515  uint32_t size,
3516  const void *data)
3517 {
3518  return ((LV2Wrapper *) handle)->Respond(size, data);
3519 }
3520 
3521 LV2_Worker_Status LV2Wrapper::Respond(uint32_t size, const void *data)
3522 {
3523  LV2Work work = {size, data};
3524 
3525  mResponses.Post(work);
3526 
3527  return LV2_WORKER_SUCCESS;
3528 }
3529 
3530 #endif
3531 
LV2Effect::GetFactoryPresets
RegistryPaths GetFactoryPresets() override
Definition: LV2Effect.cpp:1688
LV2Effect::RealtimeProcess
size_t RealtimeProcess(int group, float **inbuf, float **outbuf, size_t numSamples) override
Definition: LV2Effect.cpp:1337
LV2Effect::mPositionFrame
float mPositionFrame
Definition: LV2Effect.h:505
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
RegistryPaths
std::vector< RegistryPath > RegistryPaths
Definition: Types.h:262
LV2Effect::mURIDMap
URIDMap mURIDMap
Definition: LV2Effect.h:437
LV2Effect::mOptions
std::vector< LV2_Options_Option > mOptions
Definition: LV2Effect.h:531
LV2_EXTERNAL_UI_RUN
#define LV2_EXTERNAL_UI_RUN(ptr)
Definition: lv2_external_ui.h:66
TranslatableString
Definition: Types.h:290
LV2_EXTERNAL_UI__Widget
#define LV2_EXTERNAL_UI__Widget
Definition: lv2_external_ui.h:27
LV2Effect::OnToggle
void OnToggle(wxCommandEvent &evt)
Definition: LV2Effect.cpp:2724
CommandParameters
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the Shuttle cla...
Definition: EffectAutomationParameters.h:67
LV2Effect::ExportPresets
void ExportPresets() override
Definition: LV2Effect.cpp:1772
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:36
CommandParameters::SetParameters
bool SetParameters(const wxString &parms)
Definition: EffectAutomationParameters.h:287
LV2Wrapper::GetLatency
float GetLatency()
Definition: LV2Effect.cpp:3407
LV2EffectSettingsDialog
Definition: LV2Effect.cpp:197
LV2Wrapper::Respond
LV2_Worker_Status Respond(uint32_t size, const void *data)
Definition: LV2Effect.cpp:3521
valueRestorer
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
Definition: MemoryX.h:430
LV2EFFECTS_FAMILY
#define LV2EFFECTS_FAMILY
Definition: LV2Effect.h:62
LV2Effect::mUIShowInterface
LV2UI_Show_Interface * mUIShowInterface
Definition: LV2Effect.h:557
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1177
LV2CVPort::mHasHi
bool mHasHi
Definition: LV2Effect.h:169
LV2Effect::mMaster
LV2Wrapper * mMaster
Definition: LV2Effect.h:492
EffectTypeProcess
@ EffectTypeProcess
Definition: EffectInterface.h:59
wxSliderWrapper
wxSlider wxSliderWrapper
Definition: ShuttleGui.h:103
LV2Wrapper::ConnectPorts
void ConnectPorts(float **inbuf, float **outbuf)
Definition: LV2Effect.cpp:3444
LV2Effect::mUserBlockSize
int mUserBlockSize
Definition: LV2Effect.h:459
LV2Effect::mExternalUIHost
LV2_External_UI_Host mExternalUIHost
Definition: LV2Effect.h:525
LV2Effect::mControlOut
LV2AtomPortPtr mControlOut
Definition: LV2Effect.h:470
LV2Effect::mNativeWin
NativeWindow * mNativeWin
Definition: LV2Effect.h:548
LV2Effect::GetDescription
TranslatableString GetDescription() override
Definition: LV2Effect.cpp:455
LV2Effect::mExtensionDataFeature
LV2_Extension_Data_Feature mExtensionDataFeature
Definition: LV2Effect.h:523
LV2Effect::mFeatures
std::vector< std::unique_ptr< LV2_Feature > > mFeatures
Definition: LV2Effect.h:537
LV2Effect::suil_port_index_func
static uint32_t suil_port_index_func(SuilController controller, const char *port_symbol)
Definition: LV2Effect.cpp:3143
LV2Effect::LoadParameters
bool LoadParameters(const RegistryPath &group)
Definition: LV2Effect.cpp:1802
LV2Wrapper::SetFreeWheeling
void SetFreeWheeling(bool enable)
Definition: LV2Effect.cpp:3412
LV2Effect::SetHost
bool SetHost(EffectHostInterface *host) override
Definition: LV2Effect.cpp:517
NumericTextCtrl::Options::AutoPos
Options & AutoPos(bool enable)
Definition: NumericTextCtrl.h:187
eIsGettingFromDialog
@ eIsGettingFromDialog
Definition: ShuttleGui.h:37
LV2Effect::mProcess
LV2Wrapper * mProcess
Definition: LV2Effect.h:493
EffectHostInterface
EffectHostInterface is a decorator of a EffectUIClientInterface. It adds virtual (abstract) functions...
Definition: EffectInterface.h:119
LV2Effect::mExternalUIClosed
bool mExternalUIClosed
Definition: LV2Effect.h:527
LV2Effect::log_vprintf
static int log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char *fmt, va_list ap)
Definition: LV2Effect.cpp:3021
LV2Effect::mAudioIn
unsigned mAudioIn
Definition: LV2Effect.h:465
ID_Toggles
@ ID_Toggles
Definition: LV2Effect.cpp:344
LV2Effect::mControlPorts
LV2ControlPortArray mControlPorts
Definition: LV2Effect.h:462
LV2Wrapper::schedule_work
static LV2_Worker_Status schedule_work(LV2_Worker_Schedule_Handle handle, uint32_t size, const void *data)
Definition: LV2Effect.cpp:3488
URIDLIST
#define URIDLIST
Definition: LoadLV2.h:111
LV2Effect::GetType
EffectType GetType() override
Definition: LV2Effect.cpp:464
zix_ring_mlock
void zix_ring_mlock(ZixRing *ring)
Definition: ring.cpp:93
LV2Wrapper::LV2Work::size
uint32_t size
Definition: LV2Effect.h:593
LV2_UI__makeResident
#define LV2_UI__makeResident
Definition: LoadLV2.h:49
LV2Wrapper::mWorkerSchedule
LV2_Worker_Schedule mWorkerSchedule
Definition: LV2Effect.h:650
LV2Effect::BuildFancy
bool BuildFancy()
Definition: LV2Effect.cpp:2069
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: AudacityMessageBox.h:20
LV2Effect::set_value_func
static void set_value_func(const char *port_symbol, void *user_data, const void *value, uint32_t size, uint32_t type)
Definition: LV2Effect.cpp:3195
Settings
Definition: TrackInfo.cpp:48
LV2Effect::mControlIn
LV2AtomPortPtr mControlIn
Definition: LV2Effect.h:469
Effect
Base class for many of the effects in Audacity.
Definition: Effect.h:71
LV2Effect::mGroups
wxArrayString mGroups
Definition: LV2Effect.h:479
LV2Effect::HideUI
bool HideUI() override
Definition: LV2Effect.cpp:1620
EffectTypeGenerate
@ EffectTypeGenerate
Definition: EffectInterface.h:58
LV2Effect::mWantsOptionsInterface
bool mWantsOptionsInterface
Definition: LV2Effect.h:481
LV2Effect::gURIDMap
static URIDMap gURIDMap
Definition: LV2Effect.h:436
ShuttleGuiBase::TieCheckBox
wxCheckBox * TieCheckBox(const TranslatableString &Prompt, bool &Var)
Definition: ShuttleGui.cpp:1603
LV2Wrapper::mStateInterface
LV2_State_Interface * mStateInterface
Definition: LV2Effect.h:646
Format
Abstract base class used in importing a file.
DEFAULT_BLOCKSIZE
#define DEFAULT_BLOCKSIZE
Definition: LV2Effect.cpp:75
LV2Effect::Lookup_URI
static LV2_URID Lookup_URI(URIDMap &map, const char *uri, bool add=true)
Definition: LV2Effect.cpp:2960
LV2Effect::CheckOptions
bool CheckOptions(const LilvNode *subject, const LilvNode *predicate, bool required)
Definition: LV2Effect.cpp:1945
_LV2_External_UI_Host::ui_closed
void(* ui_closed)(LV2UI_Controller controller)
Definition: lv2_external_ui.h:90
LV2Effect::mUseGUI
bool mUseGUI
Definition: LV2Effect.h:515
gWorld
LilvWorld * gWorld
Definition: LoadLV2.cpp:77
LV2Effect::UIResize
int UIResize(int width, int height)
Definition: LV2Effect.cpp:3075
LV2Effect.h
LV2Effect::GetAudioInCount
unsigned GetAudioInCount() override
Definition: LV2Effect.cpp:957
ID_Choices
@ ID_Choices
Definition: LV2Effect.cpp:346
ID_Triggers
@ ID_Triggers
Definition: LV2Effect.cpp:343
LV2Wrapper::respond
static LV2_Worker_Status respond(LV2_Worker_Respond_Handle handle, uint32_t size, const void *data)
Definition: LV2Effect.cpp:3514
URIDMap
std::vector< MallocString<> > URIDMap
Definition: LV2Effect.h:253
NumericTextCtrl::SetName
void SetName(const TranslatableString &name)
Definition: NumericTextCtrl.cpp:1418
LV2Wrapper::mInstance
LilvInstance * mInstance
Definition: LV2Effect.h:636
LV2Effect::mNativeWinLastSize
wxSize mNativeWinLastSize
Definition: LV2Effect.h:550
MallocString
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:349
XO
#define XO(s)
Definition: Internat.h:32
LV2Effect::ProcessFinalize
bool ProcessFinalize() override
Definition: LV2Effect.cpp:1065
LV2Effect::mDialog
wxDialog * mDialog
Definition: LV2Effect.h:511
LV2Effect::mPositionSpeed
float mPositionSpeed
Definition: LV2Effect.h:504
LV2Effect::IsLegacy
bool IsLegacy() override
Definition: LV2Effect.cpp:499
EffectHostInterface::GetCurrentSettingsGroup
virtual RegistryPath GetCurrentSettingsGroup()=0
LV2Effect::mLatencyPort
int mLatencyPort
Definition: LV2Effect.h:487
LV2Effect::mUriMapFeature
LV2_URI_Map_Feature mUriMapFeature
Definition: LV2Effect.h:518
CommandParameters::GetParameters
bool GetParameters(wxString &parms)
Definition: EffectAutomationParameters.h:259
LV2Wrapper::SetBlockSize
void SetBlockSize()
Definition: LV2Effect.cpp:3431
LV2Effect::GetPortValue
const void * GetPortValue(const char *port_symbol, uint32_t *size, uint32_t *type)
Definition: LV2Effect.cpp:3172
LV2AtomPort::mMinimumSize
uint32_t mMinimumSize
Definition: LV2Effect.h:137
lrintf
#define lrintf(flt)
Definition: float_cast.h:149
LV2Wrapper::ScheduleWork
LV2_Worker_Status ScheduleWork(uint32_t size, const void *data)
Definition: LV2Effect.cpp:3495
NumericTextCtrl
Definition: NumericTextCtrl.h:169
LV2CVPort::mMin
float mMin
Definition: LV2Effect.h:163
ID_Texts
@ ID_Texts
Definition: LV2Effect.cpp:347
LV2Effect::mSlaves
std::vector< LV2Wrapper * > mSlaves
Definition: LV2Effect.h:494
LV2Wrapper::mStopWorker
bool mStopWorker
Definition: LV2Effect.h:654
LV2EffectSettingsDialog::mUseGUI
bool mUseGUI
Definition: LV2Effect.cpp:210
wxEVT_COMMAND_TEXT_UPDATED
wxEVT_COMMAND_TEXT_UPDATED
Definition: Nyquist.cpp:126
LV2Effect::LoadUserPreset
bool LoadUserPreset(const RegistryPath &name) override
Definition: LV2Effect.cpp:1673
ComponentInterfaceSymbol
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Definition: ComponentInterface.h:60
LV2Effect::mControlPortMap
std::unordered_map< uint32_t, LV2ControlPortPtr > mControlPortMap
Definition: LV2Effect.h:461
LV2Effect::RealtimeInitialize
bool RealtimeInitialize() override
Definition: LV2Effect.cpp:1175
LV2Effect::mSupportsNominalBlockLength
bool mSupportsNominalBlockLength
Definition: LV2Effect.h:534
LV2Wrapper::GetHandle
LV2_Handle GetHandle()
Definition: LV2Effect.cpp:3402
LV2Effect::~LV2Effect
virtual ~LV2Effect()
Definition: LV2Effect.cpp:420
LV2Effect::RealtimeAddProcessor
bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) override
Definition: LV2Effect.cpp:1216
NumericTextCtrl::Options
Definition: NumericTextCtrl.h:175
LV2Effect::SetSampleRate
void SetSampleRate(double rate) override
Definition: LV2Effect.cpp:977
LV2Effect::ImportPresets
void ImportPresets() override
Definition: LV2Effect.cpp:1776
LV2EffectMeter::LV2EffectMeter
LV2EffectMeter(wxWindow *parent, const LV2ControlPortPtr ctrl)
Definition: LV2Effect.cpp:125
LV2Effect::mNumSamples
size_t mNumSamples
Definition: LV2Effect.h:497
LV2Effect::mMaxBlockSize
int mMaxBlockSize
Definition: LV2Effect.h:458
LV2Effect::GetFamily
EffectFamilySymbol GetFamily() override
Definition: LV2Effect.cpp:484
LV2Effect::ValidateFeatures
bool ValidateFeatures(const LilvNode *subject)
Definition: LV2Effect.cpp:1871
LV2Effect::OnText
void OnText(wxCommandEvent &evt)
Definition: LV2Effect.cpp:2738
LV2Effect::ui_closed
static void ui_closed(LV2UI_Controller controller)
Definition: LV2Effect.cpp:3094
LV2Effect::ShowInterface
bool ShowInterface(wxWindow &parent, const EffectDialogFactory &factory, bool forceModal=false) override
Definition: LV2Effect.cpp:1448
LV2EffectMeter::OnErase
void OnErase(wxEraseEvent &evt)
Definition: LV2Effect.cpp:147
LV2Effect::mGroupMap
std::unordered_map< wxString, std::vector< int > > mGroupMap
Definition: LV2Effect.h:478
LV2CVPort::mHasLo
bool mHasLo
Definition: LV2Effect.h:168
LV2Effect::SetHostUI
void SetHostUI(EffectUIHostInterface *host) override
Definition: LV2Effect.cpp:1552
LV2Effect::LV2Wrapper
friend class LV2Wrapper
Definition: LV2Effect.h:567
ArraysOf::reinit
void reinit(Integral count)
Definition: MemoryX.h:164
LV2Effect::ValidateOptions
bool ValidateOptions(const LilvNode *subject)
Definition: LV2Effect.cpp:1935
LV2Effect::mURIDMapFeature
LV2_URID_Map mURIDMapFeature
Definition: LV2Effect.h:519
LV2Effect::ui_resize
static int ui_resize(LV2UI_Feature_Handle handle, int width, int height)
Definition: LV2Effect.cpp:3070
LV2Effect::OnIdle
void OnIdle(wxIdleEvent &evt)
Definition: LV2Effect.cpp:2784
LV2Effect::mForge
LV2_Atom_Forge mForge
Definition: LV2Effect.h:529
LV2Effect::GetPath
PluginPath GetPath() override
Definition: LV2Effect.cpp:428
LV2Effect::mSampleRate
float mSampleRate
Definition: LV2Effect.h:453
LV2Effect::PopulateUI
bool PopulateUI(ShuttleGui &S) override
Definition: LV2Effect.cpp:1557
LV2Effect::RealtimeResume
bool RealtimeResume() override
Definition: LV2Effect.cpp:1241
LV2Effect::uri_to_id
static uint32_t uri_to_id(LV2_URI_Map_Callback_Data callback_data, const char *map, const char *uri)
Definition: LV2Effect.cpp:2928
LV2Effect::mBlockSize
int mBlockSize
Definition: LV2Effect.h:454
XXO
#define XXO(s)
Definition: Internat.h:45
LV2Effect::IsReady
bool IsReady() override
Definition: LV2Effect.cpp:1039
LV2Effect::CanExportPresets
bool CanExportPresets() override
Definition: LV2Effect.cpp:1767
LV2Wrapper::~LV2Wrapper
virtual ~LV2Wrapper()
Definition: LV2Effect.cpp:3291
LV2Effect::GetVersion
wxString GetVersion() override
Definition: LV2Effect.cpp:450
EffectHostInterface::GetDuration
virtual double GetDuration()=0
LV2AtomPort::mIsMidi
bool mIsMidi
Definition: LV2Effect.h:138
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1170
LV2Effect::mSupportsSampleRate
bool mSupportsSampleRate
Definition: LV2Effect.h:535
LV2EffectMeter::mLastValue
float mLastValue
Definition: LV2Effect.cpp:113
factory
static RegisteredToolbarFactory factory
Definition: ControlToolBar.cpp:804
LV2Effect::mSuilHost
SuilHost * mSuilHost
Definition: LV2Effect.h:545
LV2Effect::mLatencyDone
bool mLatencyDone
Definition: LV2Effect.h:488
LV2Effect::AddFeature
LV2_Feature * AddFeature(const char *uri, void *data)
Definition: LV2Effect.cpp:1856
ZixRingImpl
Definition: ring.cpp:51
LV2EffectMeter::OnPaint
void OnPaint(wxPaintEvent &evt)
Definition: LV2Effect.cpp:152
LV2Effect::ValidateUI
bool ValidateUI() override
Definition: LV2Effect.cpp:1605
label
TranslatableString label
Definition: Tags.cpp:755
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1160
LV2Wrapper::mLatency
float mLatency
Definition: LV2Effect.h:652
LV2Effect::BuildPlain
bool BuildPlain()
Definition: LV2Effect.cpp:2312
LV2Effect::mMasterIn
FloatBuffers mMasterIn
Definition: LV2Effect.h:496
LV2CVPort::mMax
float mMax
Definition: LV2Effect.h:166
LV2Effect::RealtimeProcessStart
bool RealtimeProcessStart() override
Definition: LV2Effect.cpp:1250
LV2Effect::OnSize
void OnSize(wxSizeEvent &evt)
Definition: LV2Effect.cpp:2859
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1196
LV2EffectMeter::OnIdle
void OnIdle(wxIdleEvent &evt)
Definition: LV2Effect.cpp:138
LV2Effect::GetAutomationParameters
bool GetAutomationParameters(CommandParameters &parms) override
Definition: LV2Effect.cpp:1492
LV2Effect::mCVPorts
LV2CVPortArray mCVPorts
Definition: LV2Effect.h:474
LV2Wrapper
Definition: LV2Effect.h:589
ChannelNames
enum ChannelName * ChannelNames
LV2Effect::urid_map
static LV2_URID urid_map(LV2_URID_Map_Handle handle, const char *uri)
Definition: LV2Effect.cpp:2936
NODELIST
#define NODELIST
Definition: LoadLV2.h:67
LV2Effect::mUIHost
EffectUIHostInterface * mUIHost
Definition: LV2Effect.h:513
LV2Effect::mInstanceAccessFeature
LV2_Feature * mInstanceAccessFeature
Definition: LV2Effect.h:539
name
const TranslatableString name
Definition: Distortion.cpp:98
NumericConverter::TIME
@ TIME
Definition: NumericTextCtrl.h:51
PluginPath
wxString PluginPath
type alias for identifying a Plugin supplied by a module, each module defining its own interpretation...
Definition: Types.h:257
LV2Effect::mMidiOut
unsigned mMidiOut
Definition: LV2Effect.h:472
LV2Effect::InitInstance
LV2Wrapper * InitInstance(float sampleRate)
Definition: LV2Effect.cpp:1998
EffectTypeTool
@ EffectTypeTool
Definition: EffectInterface.h:61
LV2Effect::suil_port_write_func
static void suil_port_write_func(SuilController controller, uint32_t port_index, uint32_t buffer_size, uint32_t protocol, const void *buffer)
Definition: LV2Effect.cpp:3107
LV2Effect::CloseUI
bool CloseUI() override
Definition: LV2Effect.cpp:1628
LV2Effect::mResizing
bool mResizing
Definition: LV2Effect.h:551
LV2Effect::GetTailSize
size_t GetTailSize() override
Definition: LV2Effect.cpp:1034
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:503
LV2Effect::mHost
EffectHostInterface * mHost
Definition: LV2Effect.h:451
LV2Effect::mSuilInstance
SuilInstance * mSuilInstance
Definition: LV2Effect.h:546
LV2Wrapper::LV2Wrapper
LV2Wrapper(LV2Effect *effect)
Definition: LV2Effect.cpp:3277
NativeWindow
Definition: NativeWindow.h:27
LV2Effect::SaveParameters
bool SaveParameters(const RegistryPath &group)
Definition: LV2Effect.cpp:1819
LV2Wrapper::LV2Work
Definition: LV2Effect.h:592
LV2Wrapper::SendResponses
void SendResponses()
Definition: LV2Effect.cpp:3469
LV2Effect::TransferDataToWindow
bool TransferDataToWindow()
Definition: LV2Effect.cpp:2619
LV2Wrapper::Instantiate
LilvInstance * Instantiate(const LilvPlugin *plugin, double sampleRrate, std::vector< std::unique_ptr< LV2_Feature >> &features)
Definition: LV2Effect.cpp:3317
EffectClientInterface::EffectDialogFactory
std::function< wxDialog *(wxWindow &parent, EffectHostInterface *, EffectUIClientInterface *) > EffectDialogFactory
Definition: EffectInterface.h:149
EffectHostInterface::GetDurationFormat
virtual NumericFormatSymbol GetDurationFormat()=0
LV2EffectSettingsDialog::mEffect
LV2Effect * mEffect
Definition: LV2Effect.cpp:207
ShuttleGuiBase::TieNumericTextBox
wxTextCtrl * TieNumericTextBox(const TranslatableString &Prompt, int &Value, const int nChars=0)
Definition: ShuttleGui.cpp:1647
LV2Effect::mFactoryPresetUris
wxArrayString mFactoryPresetUris
Definition: LV2Effect.h:563
LV2Wrapper::mOptionsInterface
LV2_Options_Interface * mOptionsInterface
Definition: LV2Effect.h:643
LV2Effect::mAtomPorts
LV2AtomPortArray mAtomPorts
Definition: LV2Effect.h:468
LV2EffectSettingsDialog::mUseLatency
bool mUseLatency
Definition: LV2Effect.cpp:209
ConfigClientInterface::GetSharedConfig
virtual bool GetSharedConfig(const RegistryPath &group, const RegistryPath &key, wxString &value, const wxString &defval)=0
LV2Effect::GetMidiInCount
int GetMidiInCount() override
Definition: LV2Effect.cpp:967
LV2ControlPortPtr
std::shared_ptr< LV2ControlPort > LV2ControlPortPtr
Definition: LV2Effect.h:247
LV2CVPort::mDef
float mDef
Definition: LV2Effect.h:167
LV2AtomPort::mWantsPosition
bool mWantsPosition
Definition: LV2Effect.h:139
LV2Wrapper::LV2Work::data
const void * data
Definition: LV2Effect.h:594
EffectUIHostInterface
EffectUIHostInterface has nothing in it. It is provided so that an Effect can call SetHostUI passing ...
Definition: EffectInterface.h:216
_LV2_External_UI_Widget
Definition: lv2_external_ui.h:41
LV2Wrapper::mWorkerInterface
LV2_Worker_Interface * mWorkerInterface
Definition: LV2Effect.h:649
LV2Effect::OnTrigger
void OnTrigger(wxCommandEvent &evt)
Definition: LV2Effect.cpp:2717
LV2Effect::log_printf
static int log_printf(LV2_Log_Handle handle, LV2_URID type, const char *fmt,...)
Definition: LV2Effect.cpp:3008
LV2Effect::UIClosed
void UIClosed()
Definition: LV2Effect.cpp:3099
LV2Effect::mLogFeature
LV2_Log_Log mLogFeature
Definition: LV2Effect.h:522
LV2Effect::mMidiIn
unsigned mMidiIn
Definition: LV2Effect.h:471
LV2_EXTERNAL_UI_DEPRECATED_URI
#define LV2_EXTERNAL_UI_DEPRECATED_URI
Definition: lv2_external_ui.h:30
LV2Effect::LoadFactoryPreset
bool LoadFactoryPreset(int id) override
Definition: LV2Effect.cpp:1729
LV2Effect::IsGraphicalUI
bool IsGraphicalUI() override
Definition: LV2Effect.cpp:1600
LV2EffectSettingsDialog::OnOk
void OnOk(wxCommandEvent &evt)
Definition: LV2Effect.cpp:317
LV2Effect::mAudioPorts
LV2AudioPortArray mAudioPorts
Definition: LV2Effect.h:464
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:886
LV2Wrapper::mRequests
wxMessageQueue< LV2Work > mRequests
Definition: LV2Effect.h:639
LV2Effect::SetAutomationParameters
bool SetAutomationParameters(CommandParameters &parms) override
Definition: LV2Effect.cpp:1508
LV2EffectSettingsDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: LV2Effect.cpp:236
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
LV2Effect::mParent
wxWindow * mParent
Definition: LV2Effect.h:512
LV2Effect::URID_Unmap
const char * URID_Unmap(LV2_URID urid)
Definition: LV2Effect.cpp:2987
wxDialogWrapper
Definition: wxPanelWrapper.h:81
LV2Wrapper::Entry
void * Entry()
Definition: LV2Effect.cpp:3448
LV2Effect::SuilPortIndex
uint32_t SuilPortIndex(const char *port_symbol)
Definition: LV2Effect.cpp:3149
LV2Wrapper::GetInstance
LilvInstance * GetInstance()
Definition: LV2Effect.cpp:3397
LV2AtomPort::mRing
ZixRing * mRing
Definition: LV2Effect.h:142
zix_ring_new
ZixRing * zix_ring_new(uint32_t size)
Definition: ring.cpp:74
LV2Effect::mSampleRateOption
size_t mSampleRateOption
Definition: LV2Effect.h:533
LV2Effect
Definition: LV2Effect.h:258
key
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: CommandManager.cpp:196
LV2Effect::SupportsRealtime
bool SupportsRealtime() override
Definition: LV2Effect.cpp:504
ConfigClientInterface::SetPrivateConfig
virtual bool SetPrivateConfig(const RegistryPath &group, const RegistryPath &key, const wxString &value)=0
LV2Effect::mFactoryPresetNames
RegistryPaths mFactoryPresetNames
Definition: LV2Effect.h:562
LV2Effect::SetBlockSize
size_t SetBlockSize(size_t maxBlockSize) override
Definition: LV2Effect.cpp:992
LV2_EXTERNAL_UI_SHOW
#define LV2_EXTERNAL_UI_SHOW(ptr)
Definition: lv2_external_ui.h:67
LV2Effect::mParentFeature
LV2_Feature * mParentFeature
Definition: LV2Effect.h:540
_
#define _(s)
Definition: Internat.h:76
sampleCount
Definition: Types.h:581
LV2Effect::mPlug
URIDLIST const LilvPlugin * mPlug
Definition: LV2Effect.h:449
EffectTypeAnalyze
@ EffectTypeAnalyze
Definition: EffectInterface.h:60
LV2Effect::mWantsWorkerInterface
bool mWantsWorkerInterface
Definition: LV2Effect.h:483
LV2Effect::RealtimeProcessEnd
bool RealtimeProcessEnd() override
Definition: LV2Effect.cpp:1408
ConfigClientInterface::SetSharedConfig
virtual bool SetSharedConfig(const RegistryPath &group, const RegistryPath &key, const wxString &value)=0
LV2Effect::mUIResizeFeature
LV2UI_Resize mUIResizeFeature
Definition: LV2Effect.h:521
LV2Effect::GetLatency
sampleCount GetLatency() override
Definition: LV2Effect.cpp:1023
LV2Effect::mDuration
NumericTextCtrl * mDuration
Definition: LV2Effect.h:559
LV2Wrapper::SetSampleRate
void SetSampleRate()
Definition: LV2Effect.cpp:3417
LV2Effect::ProcessInitialize
bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap=NULL) override
Definition: LV2Effect.cpp:1044
LV2Effect::GetSymbol
ComponentInterfaceSymbol GetSymbol() override
Definition: LV2Effect.cpp:433
LV2Effect::mRolling
bool mRolling
Definition: LV2Effect.h:489
LV2Effect::mMasterOut
FloatBuffers mMasterOut
Definition: LV2Effect.h:496
LV2Effect::mTimer
wxTimer mTimer
Definition: LV2Effect.h:509
LV2Effect::OnTimer
void OnTimer(wxTimerEvent &evt)
Definition: LV2Effect.cpp:2774
LV2Effect::FreeInstance
void FreeInstance(LV2Wrapper *wrapper)
Definition: LV2Effect.cpp:2064
LV2Wrapper::mResponses
wxMessageQueue< LV2Work > mResponses
Definition: LV2Effect.h:640
LV2Effect::mUIIdleInterface
LV2UI_Idle_Interface * mUIIdleInterface
Definition: LV2Effect.h:556
LV2Effect::mExternalWidget
LV2_External_UI_Widget * mExternalWidget
Definition: LV2Effect.h:526
LV2EffectSettingsDialog::LV2EffectSettingsDialog
LV2EffectSettingsDialog(wxWindow *parent, LV2Effect *effect)
Definition: LV2Effect.cpp:219
LV2EffectSettingsDialog::mBufferSize
int mBufferSize
Definition: LV2Effect.cpp:208
LV2Effect::ProcessBlock
size_t ProcessBlock(float **inbuf, float **outbuf, size_t size) override
Definition: LV2Effect.cpp:1076
LV2Wrapper::mEffect
LV2Effect * mEffect
Definition: LV2Effect.h:635
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2406
LV2Effect::mUseLatency
bool mUseLatency
Definition: LV2Effect.h:486
ID_Duration
@ ID_Duration
Definition: LV2Effect.cpp:342
LV2Effect::IsDefault
bool IsDefault() override
Definition: LV2Effect.cpp:494
LV2Effect::SaveUserPreset
bool SaveUserPreset(const RegistryPath &name) override
Definition: LV2Effect.cpp:1683
LV2Effect::get_value_func
static const void * get_value_func(const char *port_symbol, void *user_data, uint32_t *size, uint32_t *type)
Definition: LV2Effect.cpp:3164
ID_TIMER
@ ID_TIMER
Definition: LV2Effect.cpp:348
LV2Effect::RealtimeFinalize
bool RealtimeFinalize() override
Definition: LV2Effect.cpp:1191
zix_ring_write
uint32_t zix_ring_write(ZixRing *ring, const void *src, uint32_t size)
Definition: ring.cpp:201
LV2Effect::OnSlider
void OnSlider(wxCommandEvent &evt)
Definition: LV2Effect.cpp:2750
LV2Wrapper::mHandle
LV2_Handle mHandle
Definition: LV2Effect.h:637
LV2Effect::mWantsStateInterface
bool mWantsStateInterface
Definition: LV2Effect.h:482
LV2Effect::CheckFeatures
bool CheckFeatures(const LilvNode *subject, const LilvNode *predicate, bool required)
Definition: LV2Effect.cpp:1881
zix_ring_skip
uint32_t zix_ring_skip(ZixRing *ring, uint32_t size)
Definition: ring.cpp:187
params
EffectDistortion::Params params
Definition: Distortion.cpp:99
LV2AtomPort::mBuffer
std::vector< uint8_t > mBuffer
Definition: LV2Effect.h:141
LV2Effect::mSeqSize
int mSeqSize
Definition: LV2Effect.h:455
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:497
ID_Sliders
@ ID_Sliders
Definition: LV2Effect.cpp:345
LV2Effect::AddOption
size_t AddOption(LV2_URID, uint32_t size, LV2_URID, const void *value)
Definition: LV2Effect.cpp:1836
Internat::ToDisplayString
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:166
LV2Effect::mActivated
bool mActivated
Definition: LV2Effect.h:490
LV2EffectMeter::mControlPort
const LV2ControlPortPtr mControlPort
Definition: LV2Effect.cpp:112
LV2EffectMeter
Definition: LV2Effect.cpp:100
RegistryPath
wxString RegistryPath
Definition: Types.h:261
LV2Effect::GetAudioOutCount
unsigned GetAudioOutCount() override
Definition: LV2Effect.cpp:962
ShuttleGuiBase::AddVariableText
wxStaticText * AddVariableText(const TranslatableString &Str, bool bCenter=false, int PositionFlags=0, int wrapWidth=0)
Definition: ShuttleGui.cpp:456
LV2Effect::RealtimeSuspend
bool RealtimeSuspend() override
Definition: LV2Effect.cpp:1232
LV2Effect::mURIDUnmapFeature
LV2_URID_Unmap mURIDUnmapFeature
Definition: LV2Effect.h:520
LV2EffectSettingsDialog::~LV2EffectSettingsDialog
virtual ~LV2EffectSettingsDialog()
Definition: LV2Effect.cpp:232
ConfigClientInterface::GetPrivateConfig
virtual bool GetPrivateConfig(const RegistryPath &group, const RegistryPath &key, wxString &value, const wxString &defval)=0
LV2Effect::mAudioOut
unsigned mAudioOut
Definition: LV2Effect.h:466
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:915
Destroy_ptr
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:365
EffectType
EffectType
Definition: EffectInterface.h:55
LV2EffectMeter::~LV2EffectMeter
virtual ~LV2EffectMeter()
Definition: LV2Effect.cpp:134
safenew
#define safenew
Definition: MemoryX.h:8
LV2Effect::SuilPortWrite
void SuilPortWrite(uint32_t port_index, uint32_t buffer_size, uint32_t protocol, const void *buffer)
Definition: LV2Effect.cpp:3116
DEFAULT_SEQSIZE
#define DEFAULT_SEQSIZE
Definition: LV2Effect.cpp:78
LV2Effect::SetSlider
void SetSlider(const LV2ControlPortPtr &port)
Definition: LV2Effect.cpp:2701
NumericConverter::GetValue
double GetValue()
Definition: NumericTextCtrl.cpp:1170
LV2Effect::LogVPrintf
int LogVPrintf(LV2_URID type, const char *fmt, va_list ap)
Definition: LV2Effect.cpp:3026
LV2Effect::mBlockSizeOption
size_t mBlockSizeOption
Definition: LV2Effect.h:532
LV2Effect::LoadFactoryDefaults
bool LoadFactoryDefaults() override
Definition: LV2Effect.cpp:1757
LV2Wrapper::mFreeWheeling
bool mFreeWheeling
Definition: LV2Effect.h:653
END_EVENT_TABLE
END_EVENT_TABLE()
LV2Effect::HasOptions
bool HasOptions() override
Definition: LV2Effect.cpp:1780
LV2Effect::mFactoryPresetsLoaded
bool mFactoryPresetsLoaded
Definition: LV2Effect.h:561
ArrayOf< float >
LV2Effect::GetVendor
VendorSymbol GetVendor() override
Definition: LV2Effect.cpp:438
LilvString
wxString LilvString(const LilvNode *node)
Definition: LV2Effect.h:572
LV2Effect::mNativeWinInitialSize
wxSize mNativeWinInitialSize
Definition: LV2Effect.h:549
LV2Effect::GetMidiOutCount
int GetMidiOutCount() override
Definition: LV2Effect.cpp:972
EVT_COMMAND_RANGE
EVT_COMMAND_RANGE(ID_Slider, ID_Slider+NUMBER_OF_BANDS - 1, wxEVT_COMMAND_SLIDER_UPDATED, EffectEqualization::OnSlider) EffectEqualization
Definition: Equalization.cpp:217
LV2Effect::TransferDataFromWindow
bool TransferDataFromWindow()
Definition: LV2Effect.cpp:2691
LV2Effect::mNoResize
bool mNoResize
Definition: LV2Effect.h:484
_LV2_External_UI_Host::plugin_human_id
const char * plugin_human_id
Definition: lv2_external_ui.h:101
EffectHostInterface::SetDuration
virtual void SetDuration(double seconds)=0
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:638
EffectHostInterface::GetFactoryDefaultsGroup
virtual RegistryPath GetFactoryDefaultsGroup()=0
LV2Effect::GetBlockSize
size_t GetBlockSize() const override
Definition: LV2Effect.cpp:1018
LV2Effect::urid_unmap
static const char * urid_unmap(LV2_URID_Unmap_Handle handle, LV2_URID urid)
Definition: LV2Effect.cpp:2982
LV2Effect::SupportsAutomation
bool SupportsAutomation() override
Definition: LV2Effect.cpp:509
LV2_EXTERNAL_UI__Host
#define LV2_EXTERNAL_UI__Host
Definition: lv2_external_ui.h:26
LV2Effect::OnChoice
void OnChoice(wxCommandEvent &evt)
Definition: LV2Effect.cpp:2731
LV2Effect::mMinBlockSize
int mMinBlockSize
Definition: LV2Effect.h:457
LV2Effect::SetPortValue
void SetPortValue(const char *port_symbol, const void *value, uint32_t size, uint32_t type)
Definition: LV2Effect.cpp:3204
ZixRingImpl::size
uint32_t size
Size (capacity) in bytes.
Definition: ring.cpp:54
LV2Effect::URID_Map
LV2_URID URID_Map(const char *uri)
Definition: LV2Effect.cpp:2941
LV2EffectMeter::OnSize
void OnSize(wxSizeEvent &evt)
Definition: LV2Effect.cpp:185
zix_ring_read
uint32_t zix_ring_read(ZixRing *ring, void *dst, uint32_t size)
Definition: ring.cpp:172
LV2Effect::ShowOptions
void ShowOptions() override
Definition: LV2Effect.cpp:1785
LV2Effect::IsInteractive
bool IsInteractive() override
Definition: LV2Effect.cpp:489