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