Audacity  2.2.2
LadspaEffect.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  LadspaEffect.cpp
6 
7  Dominic Mazzoni
8 
9  This class implements a LADSPA Plug-in effect.
10 
11 *******************************************************************//****************************************************************//*******************************************************************/
23 
24 
25 #include "../../Audacity.h"
26 
27 #include "ladspa.h"
28 
29 #include <float.h>
30 
31 #include <wx/wxprec.h>
32 #include <wx/button.h>
33 #include <wx/checkbox.h>
34 #include <wx/dcbuffer.h>
35 #include <wx/dcclient.h>
36 #include <wx/dynlib.h>
37 #include <wx/filename.h>
38 #include <wx/log.h>
39 #include <wx/menu.h>
40 #include <wx/sizer.h>
41 #include <wx/slider.h>
42 #include <wx/statbox.h>
43 #include <wx/stattext.h>
44 #include <wx/textctrl.h>
45 #include <wx/tokenzr.h>
46 #include <wx/intl.h>
47 #include <wx/scrolwin.h>
48 #include <wx/version.h>
49 
50 #include "LadspaEffect.h" // This class's header file
51 #include "../../FileNames.h"
52 #include "../../Internat.h"
53 #include "../../ShuttleGui.h"
54 #include "../../widgets/valnum.h"
55 #include "../../widgets/wxPanelWrapper.h"
56 
57 #if wxUSE_ACCESSIBILITY
58 #include "../../widgets/WindowAccessible.h"
59 #endif
60 
61 // ============================================================================
62 // List of effects that ship with Audacity. These will be autoregistered.
63 // ============================================================================
64 const static wxChar *kShippedEffects[] =
65 {
66  wxT("sc4_1882.dll"),
67 };
68 
69 // ============================================================================
70 // Module registration entry point
71 //
72 // This is the symbol that Audacity looks for when the module is built as a
73 // dynamic library.
74 //
75 // When the module is builtin to Audacity, we use the same function, but it is
76 // declared static so as not to clash with other builtin modules.
77 // ============================================================================
78 DECLARE_MODULE_ENTRY(AudacityModule)
79 {
80  // Create and register the importer
81  // Trust the module manager not to leak this
82  return safenew LadspaEffectsModule(moduleManager, path);
83 }
84 
85 // ============================================================================
86 // Register this as a builtin module
87 // ============================================================================
88 DECLARE_BUILTIN_MODULE(LadspaBuiltin);
89 
91 //
92 // LadspaEffectsModule
93 //
95 
97  const wxString *path)
98 {
99  mModMan = moduleManager;
100  if (path)
101  {
102  mPath = *path;
103  }
104 }
105 
107 {
108 }
109 
110 // ============================================================================
111 // IdentInterface implementation
112 // ============================================================================
113 
115 {
116  return mPath;
117 }
118 
120 {
121  /* i8n-hint: abbreviates "Linux Audio Developer's Simple Plugin API"
122  (Application programming interface)
123  */
124  return XO("LADSPA Effects");
125 }
126 
128 {
129  return XO("The Audacity Team");
130 }
131 
133 {
134  // This "may" be different if this were to be maintained as a separate DLL
135  return LADSPAEFFECTS_VERSION;
136 }
137 
139 {
140  return _("Provides LADSPA Effects");
141 }
142 
143 // ============================================================================
144 // ModuleInterface implementation
145 // ============================================================================
146 
148 {
149  // Nothing to do here
150  return true;
151 }
152 
154 {
155  // Nothing to do here
156  return;
157 }
158 
160 {
161  static const wxString ext[] = {
162 
163 #ifdef __WXMSW__
164 
165  { _T("dll") }
166 
167 #else
168 
169  { _T("so") }
170 
171  #ifdef __WXMAC__
172  // Is it correct that these are candidate plug-in files too for macOs?
173  , { _T("dylib") }
174  #endif
175 
176 #endif
177 
178  };
179  static const wxArrayString result{ sizeof(ext)/sizeof(*ext), ext };
180  return result;
181 }
182 
184 {
185  // To do: better choice
186  return FileNames::PlugInDir();
187 }
188 
190 {
191  // Autoregister effects that we "think" are ones that have been shipped with
192  // Audacity. A little simplistic, but it should suffice for now.
193  wxArrayString pathList = GetSearchPaths();
194  wxArrayString files;
195  wxString ignoredErrMsg;
196 
197  for (int i = 0; i < (int)WXSIZEOF(kShippedEffects); i++)
198  {
199  files.Clear();
200  pm.FindFilesInPathList(kShippedEffects[i], pathList, files);
201  for (size_t j = 0, cnt = files.GetCount(); j < cnt; j++)
202  {
203  if (!pm.IsPluginRegistered(files[j]))
204  {
205  // No checking for error ?
206  DiscoverPluginsAtPath(files[j], ignoredErrMsg,
208  }
209  }
210  }
211 
212  // We still want to be called during the normal registration process
213  return false;
214 }
215 
217 {
218  wxArrayString pathList = GetSearchPaths();
219  wxArrayString files;
220 
221 #if defined(__WXMAC__)
222 
223  // Recursively scan for all shared objects
224  pm.FindFilesInPathList(wxT("*.so"), pathList, files, true);
225 
226 #elif defined(__WXMSW__)
227 
228  // Recursively scan for all DLLs
229  pm.FindFilesInPathList(wxT("*.dll"), pathList, files, true);
230 
231 #else
232 
233  // Recursively scan for all shared objects
234  pm.FindFilesInPathList(wxT("*.so"), pathList, files, true);
235 
236 #endif
237 
238  return files;
239 }
240 
242  const wxString & path, wxString &errMsg,
243  const RegistrationCallback &callback)
244 {
245  errMsg.clear();
246  // Since we now have builtin VST support, ignore the VST bridge as it
247  // causes duplicate menu entries to appear.
248  wxFileName ff(path);
249  if (ff.GetName().CmpNoCase(wxT("vst-bridge")) == 0) {
250  errMsg = _("Audacity no longer uses vst-bridge");
251  return 0;
252  }
253 
254  // As a courtesy to some plug-ins that might be bridges to
255  // open other plug-ins, we set the current working
256  // directory to be the plug-in's directory.
257  wxString envpath;
258  bool hadpath = wxGetEnv(wxT("PATH"), &envpath);
259  wxSetEnv(wxT("PATH"), ff.GetPath() + wxFILE_SEP_PATH + envpath);
260  wxString saveOldCWD = ff.GetCwd();
261  ff.SetCwd();
262 
263  int index = 0;
264  int nLoaded = 0;
265  LADSPA_Descriptor_Function mainFn = NULL;
266  wxDynamicLibrary lib;
267  if (lib.Load(path, wxDL_NOW)) {
268  wxLogNull logNo;
269 
270  mainFn = (LADSPA_Descriptor_Function) lib.GetSymbol(wxT("ladspa_descriptor"));
271  if (mainFn) {
272  const LADSPA_Descriptor *data;
273 
274  for (data = mainFn(index); data; data = mainFn(++index)) {
275  LadspaEffect effect(path, index);
276  if (effect.SetHost(NULL)) {
277  ++nLoaded;
278  if (callback)
279  callback( this, &effect );
280  }
281  else
282  errMsg = _("Could not load the library");
283  }
284  }
285  }
286  else
287  errMsg = _("Could not load the library");
288 
289  if (lib.IsLoaded()) {
290  // PRL: I suspect Bug1257 -- Crash when enabling Amplio2 -- is the fault of a timing-
291  // dependent multi-threading bug in the Amplio2 library itself, in case the unload of the .dll
292  // comes too soon after the load. I saw the bug in Release builds but not Debug.
293  // A sleep of even 1 ms was enough to fix the problem for me, but let's be even more generous.
294  ::wxMilliSleep(10);
295  lib.Unload();
296  }
297 
298  wxSetWorkingDirectory(saveOldCWD);
299  hadpath ? wxSetEnv(wxT("PATH"), envpath) : wxUnsetEnv(wxT("PATH"));
300 
301  return nLoaded;
302 }
303 
304 bool LadspaEffectsModule::IsPluginValid(const wxString & path, bool bFast)
305 {
306  if( bFast )
307  return true;
308  wxString realPath = path.BeforeFirst(wxT(';'));
309  return wxFileName::FileExists(realPath);
310 }
311 
313 {
314  // Acquires a resource for the application.
315  // For us, the path is two words.
316  // 1) The library's path
317  // 2) The LADSPA descriptor index
318  long index;
319  wxString realPath = path.BeforeFirst(wxT(';'));
320  path.AfterFirst(wxT(';')).ToLong(&index);
321 
322  // Safety of this depends on complementary calls to DeleteInstance on the module manager side.
323  return safenew LadspaEffect(realPath, (int)index);
324 }
325 
327 {
328  std::unique_ptr < LadspaEffect > {
329  dynamic_cast<LadspaEffect *>(instance)
330  };
331 }
332 
334 {
335  wxArrayString pathList;
336  wxArrayString files;
337  wxString pathVar;
338 
339  // Check for the LADSPA_PATH environment variable
340  pathVar = wxString::FromUTF8(getenv("LADSPA_PATH"));
341  if (!pathVar.empty())
342  {
343  wxStringTokenizer tok(pathVar);
344  while (tok.HasMoreTokens())
345  {
346  pathList.Add(tok.GetNextToken());
347  }
348  }
349 
350 #if defined(__WXMAC__)
351 #define LADSPAPATH wxT("/Library/Audio/Plug-Ins/LADSPA")
352 
353  // Look in ~/Library/Audio/Plug-Ins/LADSPA and /Library/Audio/Plug-Ins/LADSPA
354  pathList.Add(wxGetHomeDir() + wxFILE_SEP_PATH + LADSPAPATH);
355  pathList.Add(LADSPAPATH);
356 
357 #elif defined(__WXMSW__)
358 
359  // No special paths...probably should look in %CommonProgramFiles%\LADSPA
360 
361 #else
362 
363  pathList.Add(wxGetHomeDir() + wxFILE_SEP_PATH + wxT(".ladspa"));
364  pathList.Add(wxT("/usr/local/lib/ladspa"));
365  pathList.Add(wxT("/usr/lib/ladspa"));
366  pathList.Add(wxT(LIBDIR) wxT("/ladspa"));
367 
368 #endif
369 
370  return pathList;
371 }
372 
374 //
375 // LadspaEffectOptionsDialog
376 //
378 
380 {
381 public:
382  LadspaEffectOptionsDialog(wxWindow * parent, EffectHostInterface *host);
383  virtual ~LadspaEffectOptionsDialog();
384 
385  void PopulateOrExchange(ShuttleGui & S);
386 
387  void OnOk(wxCommandEvent & evt);
388 
389 private:
392 
393  DECLARE_EVENT_TABLE()
394 };
395 
396 BEGIN_EVENT_TABLE(LadspaEffectOptionsDialog, wxDialogWrapper)
397  EVT_BUTTON(wxID_OK, LadspaEffectOptionsDialog::OnOk)
399 
401 : wxDialogWrapper(parent, wxID_ANY, wxString(_("LADSPA Effect Options")))
402 {
403  mHost = host;
404 
405  mHost->GetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency, true);
406 
407  ShuttleGui S(this, eIsCreating);
408  PopulateOrExchange(S);
409 }
410 
412 {
413 }
414 
416 {
417  S.SetBorder(5);
418  S.StartHorizontalLay(wxEXPAND, 1);
419  {
420  S.StartVerticalLay(false);
421  {
422  S.StartStatic(_("Latency Compensation"));
423  {
424  S.AddVariableText(wxString() +
425  _("As part of their processing, some LADSPA effects must delay returning ") +
426  _("audio to Audacity. When not compensating for this delay, you will ") +
427  _("notice that small silences have been inserted into the audio. ") +
428  _("Enabling this option will provide that compensation, but it may ") +
429  _("not work for all LADSPA effects."))->Wrap(650);
430 
431  S.StartHorizontalLay(wxALIGN_LEFT);
432  {
433  S.TieCheckBox(_("Enable &compensation"),
434  mUseLatency);
435  }
436  S.EndHorizontalLay();
437  }
438  S.EndStatic();
439  }
440  S.EndVerticalLay();
441  }
442  S.EndHorizontalLay();
443 
444  S.AddStandardButtons();
445 
446  Layout();
447  Fit();
448  Center();
449 }
450 
451 void LadspaEffectOptionsDialog::OnOk(wxCommandEvent & WXUNUSED(evt))
452 {
453  if (!Validate())
454  {
455  return;
456  }
457 
459  PopulateOrExchange(S);
460 
461  mHost->SetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency);
462 
463  EndModal(wxID_OK);
464 }
465 
466 enum
467 {
468  ID_Duration = 20000,
469  ID_Toggles = 21000,
470  ID_Sliders = 22000,
471  ID_Texts = 23000,
472 };
473 
475 //
476 // LadspaEffectMeter
477 //
479 
480 class LadspaEffectMeter final : public wxWindow
481 {
482 public:
483  LadspaEffectMeter(wxWindow *parent, const float & val, float min, float max);
484  virtual ~LadspaEffectMeter();
485 
486 private:
487  void OnErase(wxEraseEvent & evt);
488  void OnPaint(wxPaintEvent & evt);
489  void OnIdle(wxIdleEvent & evt);
490  void OnSize(wxSizeEvent & evt);
491 
492 private:
493  const float & mVal;
494  float mMin;
495  float mMax;
496  float mLastValue;
497 
498  DECLARE_EVENT_TABLE()
499 };
500 
501 BEGIN_EVENT_TABLE(LadspaEffectMeter, wxWindow)
502  EVT_IDLE(LadspaEffectMeter::OnIdle)
503  EVT_ERASE_BACKGROUND(LadspaEffectMeter::OnErase)
504  EVT_PAINT(LadspaEffectMeter::OnPaint)
505  EVT_SIZE(LadspaEffectMeter::OnSize)
507 
508 LadspaEffectMeter::LadspaEffectMeter(wxWindow *parent, const float & val, float min, float max)
509 : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDEFAULT_CONTROL_BORDER),
510  mVal(val)
511 {
512  mMin = min;
513  mMax = max;
514  mLastValue = -mVal;
515 
516  SetBackgroundColour(*wxWHITE);
517 }
518 
520 {
521 }
522 
523 void LadspaEffectMeter::OnIdle(wxIdleEvent & WXUNUSED(evt))
524 {
525  if (mLastValue != mVal)
526  {
527  Refresh(false);
528  }
529 }
530 
531 void LadspaEffectMeter::OnErase(wxEraseEvent & WXUNUSED(evt))
532 {
533  // Just ignore it to prevent flashing
534 }
535 
536 void LadspaEffectMeter::OnPaint(wxPaintEvent & WXUNUSED(evt))
537 {
538  wxPaintDC dc(this);
539 
540  // Cache some metrics
541  wxRect r = GetClientRect();
542  wxCoord x = r.GetLeft();
543  wxCoord y = r.GetTop();
544  wxCoord w = r.GetWidth();
545  wxCoord h = r.GetHeight();
546 
547  // These use unscaled value, min, and max
548  float val = mVal;
549  if (val > mMax)
550  {
551  val = mMax;
552  }
553  if (val < mMin)
554  {
555  val = mMin;
556  }
557  val -= mMin;
558 
559  // Setup for erasing the background
560  dc.SetPen(*wxTRANSPARENT_PEN);
561  dc.SetBrush(wxColour(100, 100, 220));
562 
563  dc.Clear();
564  dc.DrawRectangle(x, y, (w * (val / fabs(mMax - mMin))), h);
565 
566  mLastValue = mVal;
567 }
568 
569 void LadspaEffectMeter::OnSize(wxSizeEvent & WXUNUSED(evt))
570 {
571  Refresh(false);
572 }
573 
575 //
576 // LadspaEffect
577 //
579 
580 BEGIN_EVENT_TABLE(LadspaEffect, wxEvtHandler)
581  EVT_COMMAND_RANGE(ID_Toggles, ID_Toggles + 999, wxEVT_COMMAND_CHECKBOX_CLICKED, LadspaEffect::OnCheckBox)
582  EVT_COMMAND_RANGE(ID_Sliders, ID_Sliders + 999, wxEVT_COMMAND_SLIDER_UPDATED, LadspaEffect::OnSlider)
585 
586 LadspaEffect::LadspaEffect(const wxString & path, int index)
587 {
588  mPath = path;
589  mIndex = index;
590  mData = NULL;
591 
592  mHost = NULL;
593  mMaster = NULL;
594  mReady = false;
595 
596  mInteractive = false;
597 
598  mAudioIns = 0;
599  mAudioOuts = 0;
600  mNumInputControls = 0;
601  mNumOutputControls = 0;
602  mSampleRate = 44100;
603  mBlockSize = 0;
604 
605  mLatencyPort = -1;
606 
607  mDialog = NULL;
608  mParent = NULL;
609 }
610 
612 {
613 }
614 
615 // ============================================================================
616 // IdentInterface implementation
617 // ============================================================================
618 
620 {
621  return wxString::Format(wxT("%s;%d"), mPath, mIndex);
622 }
623 
625 {
626  return LAT1CTOWX(mData->Name);
627 }
628 
630 {
631  return { LAT1CTOWX(mData->Maker) };
632 }
633 
635 {
636  return _("n/a");
637 }
638 
640 {
641  return LAT1CTOWX(mData->Copyright);
642 }
643 
644 // ============================================================================
645 // EffectDefinitionInterface implementation
646 // ============================================================================
647 
649 {
650  if (mAudioIns == 0 && mAudioOuts == 0)
651  {
652  return EffectTypeTool;
653  }
654 
655  if (mAudioIns == 0)
656  {
657  return EffectTypeGenerate;
658  }
659 
660  if (mAudioOuts == 0)
661  {
662  return EffectTypeAnalyze;
663  }
664 
665  return EffectTypeProcess;
666 }
667 
669 {
670  return LADSPAEFFECTS_FAMILY;
671 }
672 
674 {
675  return mInteractive;
676 }
677 
679 {
680  return false;
681 }
682 
684 {
685  return false;
686 }
687 
689 {
690  return GetType() != EffectTypeGenerate;
691 }
692 
694 {
695  return mNumInputControls > 0;
696 }
697 
698 // ============================================================================
699 // EffectClientInterface Implementation
700 // ============================================================================
701 
703 {
704  mHost = host;
705 
706  if (!Load())
707  {
708  return false;
709  }
710 
711  mInputPorts.reinit( mData->PortCount );
712  mOutputPorts.reinit( mData->PortCount );
713  mInputControls.reinit( mData->PortCount );
714  mOutputControls.reinit( mData->PortCount );
715 
716  for (unsigned long p = 0; p < mData->PortCount; p++)
717  {
718  LADSPA_PortDescriptor d = mData->PortDescriptors[p];
719 
720  // Collect the audio ports
721  if (LADSPA_IS_PORT_AUDIO(d))
722  {
723  if (LADSPA_IS_PORT_INPUT(d))
724  {
725  mInputPorts[mAudioIns++] = p;
726  }
727  else if (LADSPA_IS_PORT_OUTPUT(d))
728  {
729  mOutputPorts[mAudioOuts++] = p;
730  }
731  }
732  // Determine the port's default value
734  {
735  mInteractive = true;
736 
737  LADSPA_PortRangeHint hint = mData->PortRangeHints[p];
738  float val = float(1.0);
739  float lower = hint.LowerBound;
740  float upper = hint.UpperBound;
741 
743  {
744  lower *= mSampleRate;
745  upper *= mSampleRate;
746  }
747 
748  if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) && val < lower)
749  {
750  val = lower;
751  }
752 
753  if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) && val > upper)
754  {
755  val = upper;
756  }
757 
759  {
760  val = lower;
761  }
762 
764  {
765  val = upper;
766  }
767 
769  {
771  {
772  val = exp(log(lower) * 0.75f + log(upper) * 0.25f);
773  }
774  else
775  {
776  val = lower * 0.75f + upper * 0.25f;
777  }
778  }
779 
781  {
783  {
784  val = exp(log(lower) * 0.5f + log(upper) * 0.5f);
785  }
786  else
787  {
788  val = lower * 0.5f + upper * 0.5f;
789  }
790  }
791 
793  {
795  {
796  val = exp(log(lower) * 0.25f + log(upper) * 0.75f);
797  }
798  else
799  {
800  val = lower * 0.25f + upper * 0.75f;
801  }
802  }
803 
805  {
806  val = 0.0f;
807  }
808 
810  {
811  val = 1.0f;
812  }
813 
815  {
816  val = 100.0f;
817  }
818 
820  {
821  val = 440.0f;
822  }
823 
824  mNumInputControls++;
825  mInputControls[p] = val;
826  }
828  {
829  mOutputControls[p] = 0.0;
830 
831  // LADSPA effects have a convention of providing latency on an output
832  // control port whose name is "latency".
833  if (strcmp(mData->PortNames[p], "latency") == 0)
834  {
835  mLatencyPort = p;
836  }
837  else
838  {
839  mInteractive = true;
840  mNumOutputControls++;
841  }
842  }
843  }
844 
845  // mHost will be null during registration
846  if (mHost)
847  {
848  mHost->GetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency, true);
849 
850  bool haveDefaults;
851  mHost->GetPrivateConfig(mHost->GetFactoryDefaultsGroup(), wxT("Initialized"), haveDefaults, false);
852  if (!haveDefaults)
853  {
854  SaveParameters(mHost->GetFactoryDefaultsGroup());
855  mHost->SetPrivateConfig(mHost->GetFactoryDefaultsGroup(), wxT("Initialized"), true);
856  }
857 
858  LoadParameters(mHost->GetCurrentSettingsGroup());
859  }
860 
861  return true;
862 }
863 
865 {
866  return mAudioIns;
867 }
868 
870 {
871  return mAudioOuts;
872 }
873 
875 {
876  return 0;
877 }
878 
880 {
881  return 0;
882 }
883 
885 {
886  mSampleRate = rate;
887 }
888 
889 size_t LadspaEffect::SetBlockSize(size_t maxBlockSize)
890 {
891  mBlockSize = maxBlockSize;
892 
893  return mBlockSize;
894 }
895 
897 {
898  if (mUseLatency && mLatencyPort >= 0 && !mLatencyDone)
899  {
900  mLatencyDone = true;
901  return sampleCount ( mOutputControls[mLatencyPort] );
902  }
903 
904  return 0;
905 }
906 
908 {
909  return 0;
910 }
911 
913 {
914  return mReady;
915 }
916 
917 bool LadspaEffect::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames WXUNUSED(chanMap))
918 {
919  /* Instantiate the plugin */
920  if (!mReady)
921  {
922  mMaster = InitInstance(mSampleRate);
923  if (!mMaster)
924  {
925  return false;
926  }
927  mReady = true;
928  }
929 
930  mLatencyDone = false;
931 
932  return true;
933 }
934 
936 {
937  if (mReady)
938  {
939  mReady = false;
940 
941  FreeInstance(mMaster);
942  mMaster = NULL;
943  }
944 
945  return true;
946 }
947 
948 size_t LadspaEffect::ProcessBlock(float **inBlock, float **outBlock, size_t blockLen)
949 {
950  for (int i = 0; i < (int)mAudioIns; i++)
951  {
952  mData->connect_port(mMaster, mInputPorts[i], inBlock[i]);
953  }
954 
955  for (int i = 0; i < (int)mAudioOuts; i++)
956  {
957  mData->connect_port(mMaster, mOutputPorts[i], outBlock[i]);
958  }
959 
960  mData->run(mMaster, blockLen);
961 
962  RefreshControls(true);
963 
964  return blockLen;
965 }
966 
968 {
969  return true;
970 }
971 
972 bool LadspaEffect::RealtimeAddProcessor(unsigned WXUNUSED(numChannels), float sampleRate)
973 {
974  LADSPA_Handle slave = InitInstance(sampleRate);
975  if (!slave)
976  {
977  return false;
978  }
979 
980  mSlaves.push_back(slave);
981 
982  return true;
983 }
984 
986 {
987  for (size_t i = 0, cnt = mSlaves.size(); i < cnt; i++)
988  {
989  FreeInstance(mSlaves[i]);
990  }
991  mSlaves.clear();
992 
993  return true;
994 }
995 
997 {
998  return true;
999 }
1000 
1002 {
1003  return true;
1004 }
1005 
1007 {
1008  return true;
1009 }
1010 
1012  float **inbuf,
1013  float **outbuf,
1014  size_t numSamples)
1015 {
1016  for (int i = 0; i < (int)mAudioIns; i++)
1017  {
1018  mData->connect_port(mSlaves[group], mInputPorts[i], inbuf[i]);
1019  }
1020 
1021  for (int i = 0; i < (int)mAudioOuts; i++)
1022  {
1023  mData->connect_port(mSlaves[group], mOutputPorts[i], outbuf[i]);
1024  }
1025 
1026  mData->run(mSlaves[group], numSamples);
1027 
1028  return numSamples;
1029 }
1030 
1032 {
1033  return true;
1034 }
1035 
1036 bool LadspaEffect::ShowInterface(wxWindow *parent, bool forceModal)
1037 {
1038  if (mDialog)
1039  {
1040  if ( mDialog->Close(true) )
1041  mDialog = nullptr;
1042  return false;
1043  }
1044 
1045  // mDialog is null
1046  auto cleanup = valueRestorer( mDialog );
1047 
1048  mDialog = mHost->CreateUI(parent, this);
1049  if (!mDialog)
1050  {
1051  return false;
1052  }
1053 
1054  mDialog->Layout();
1055  mDialog->Fit();
1056  mDialog->SetMinSize(mDialog->GetSize());
1057 
1058  if ((SupportsRealtime() || GetType() == EffectTypeAnalyze) && !forceModal)
1059  {
1060  mDialog->Show();
1061  cleanup.release();
1062 
1063  return false;
1064  }
1065 
1066  bool res = mDialog->ShowModal() != 0;
1067 
1068  return res;
1069 }
1070 
1072 {
1073  for (unsigned long p = 0; p < mData->PortCount; p++)
1074  {
1075  LADSPA_PortDescriptor d = mData->PortDescriptors[p];
1076 
1078  {
1079  if (!parms.Write(LAT1CTOWX(mData->PortNames[p]), mInputControls[p]))
1080  {
1081  return false;
1082  }
1083  }
1084  }
1085 
1086  return true;
1087 }
1088 
1090 {
1091  for (unsigned long p = 0; p < mData->PortCount; p++)
1092  {
1093  LADSPA_PortDescriptor d = mData->PortDescriptors[p];
1094 
1096  {
1097  wxString labelText = LAT1CTOWX(mData->PortNames[p]);
1098  double d = 0.0;
1099  if (!parms.Read(labelText, &d))
1100  {
1101  return false;
1102  }
1103 
1104  mInputControls[p] = d;
1105  }
1106  }
1107 
1108  return true;
1109 }
1110 
1111 bool LadspaEffect::LoadUserPreset(const wxString & name)
1112 {
1113  if (!LoadParameters(name))
1114  {
1115  return false;
1116  }
1117 
1118  RefreshControls();
1119 
1120  return true;
1121 }
1122 
1123 bool LadspaEffect::SaveUserPreset(const wxString & name)
1124 {
1125  return SaveParameters(name);
1126 }
1127 
1129 {
1130  return wxArrayString();
1131 }
1132 
1133 bool LadspaEffect::LoadFactoryPreset(int WXUNUSED(id))
1134 {
1135  return true;
1136 }
1137 
1139 {
1140  if (!LoadParameters(mHost->GetFactoryDefaultsGroup()))
1141  {
1142  return false;
1143  }
1144 
1145  RefreshControls();
1146 
1147  return true;
1148 }
1149 
1150 // ============================================================================
1151 // EffectUIClientInterface Implementation
1152 // ============================================================================
1153 
1155 {
1156  mUIHost = host;
1157 }
1158 
1159 bool LadspaEffect::PopulateUI(wxWindow *parent)
1160 {
1161  mParent = parent;
1162 
1163  mParent->PushEventHandler(this);
1164 
1165  mToggles.reinit( mData->PortCount );
1166  mSliders.reinit( mData->PortCount );
1167  mFields.reinit( mData->PortCount, true);
1168  mLabels.reinit( mData->PortCount );
1169  mMeters.reinit( mData->PortCount );
1170 
1171  wxASSERT(mParent); // To justify safenew
1172  wxScrolledWindow *const w = safenew wxScrolledWindow(mParent,
1173  wxID_ANY,
1174  wxDefaultPosition,
1175  wxDefaultSize,
1176  wxVSCROLL | wxTAB_TRAVERSAL);
1177 
1178  {
1179  auto mainSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
1180  w->SetScrollRate(0, 20);
1181 
1182  // This fools NVDA into not saying "Panel" when the dialog gets focus
1183  w->SetName(wxT("\a"));
1184  w->SetLabel(wxT("\a"));
1185 
1186  mainSizer->Add(w, 1, wxEXPAND);
1187  mParent->SetSizer(mainSizer.release());
1188  }
1189 
1190  wxSizer *marginSizer;
1191  {
1192  auto uMarginSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
1193  marginSizer = uMarginSizer.get();
1194 
1195  if (mNumInputControls)
1196  {
1197  auto paramSizer = std::make_unique<wxStaticBoxSizer>(wxVERTICAL, w, _("Effect Settings"));
1198 
1199  auto gridSizer = std::make_unique<wxFlexGridSizer>(5, 0, 0);
1200  gridSizer->AddGrowableCol(3);
1201 
1202  wxControl *item;
1203 
1204  // Add the duration control for generators
1205  if (GetType() == EffectTypeGenerate)
1206  {
1207  item = safenew wxStaticText(w, 0, _("Duration:"));
1208  gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
1209  mDuration = safenew
1212  mHost->GetDurationFormat(),
1213  mHost->GetDuration(),
1214  mSampleRate,
1216  .AutoPos(true));
1217  mDuration->SetName(_("Duration"));
1218  gridSizer->Add(mDuration, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1219  gridSizer->Add(1, 1, 0);
1220  gridSizer->Add(1, 1, 0);
1221  gridSizer->Add(1, 1, 0);
1222  }
1223 
1224  for (unsigned long p = 0; p < mData->PortCount; p++)
1225  {
1226  LADSPA_PortDescriptor d = mData->PortDescriptors[p];
1228  {
1229  continue;
1230  }
1231 
1232  wxString labelText = LAT1CTOWX(mData->PortNames[p]);
1233  item = safenew wxStaticText(w, 0, labelText + wxT(":"));
1234  gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
1235 
1236  wxString fieldText;
1237  LADSPA_PortRangeHint hint = mData->PortRangeHints[p];
1238 
1240  {
1241  mToggles[p] = safenew wxCheckBox(w, ID_Toggles + p, wxT(""));
1242  mToggles[p]->SetName(labelText);
1243  mToggles[p]->SetValue(mInputControls[p] > 0);
1244  gridSizer->Add(mToggles[p], 0, wxALL, 5);
1245 
1246  gridSizer->Add(1, 1, 0);
1247  gridSizer->Add(1, 1, 0);
1248  gridSizer->Add(1, 1, 0);
1249  continue;
1250  }
1251 
1252  wxString bound;
1253  float lower = -FLT_MAX;
1254  float upper = FLT_MAX;
1255  bool haslo = false;
1256  bool hashi = false;
1257  bool forceint = false;
1258 
1260  {
1261  lower = hint.LowerBound;
1262  haslo = true;
1263  }
1264 
1266  {
1267  upper = hint.UpperBound;
1268  hashi = true;
1269  }
1270 
1272  {
1273  lower *= mSampleRate;
1274  upper *= mSampleRate;
1275  forceint = true;
1276  }
1277 
1278  // Limit to the UI precision
1279  lower = ceilf(lower * 1000000.0) / 1000000.0;
1280  upper = floorf(upper * 1000000.0) / 1000000.0;
1281  mInputControls[p] = roundf(mInputControls[p] * 1000000.0) / 1000000.0;
1282 
1283  if (haslo && mInputControls[p] < lower)
1284  {
1285  mInputControls[p] = lower;
1286  }
1287 
1288  if (hashi && mInputControls[p] > upper)
1289  {
1290  mInputControls[p] = lower;
1291  }
1292 
1293  // Don't specify a value at creation time. This prevents unwanted events
1294  // being sent to the OnTextCtrl() handler before the associated slider
1295  // has been created.
1296  mFields[p] = safenew wxTextCtrl(w, ID_Texts + p);
1297  mFields[p]->SetName(labelText);
1298  gridSizer->Add(mFields[p], 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1299 
1300  wxString str;
1301  if (haslo)
1302  {
1303  if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
1304  {
1305  str.Printf(wxT("%d"), (int)(lower + 0.5));
1306  }
1307  else
1308  {
1309  str = Internat::ToDisplayString(lower);
1310  }
1311  item = safenew wxStaticText(w, 0, str);
1312  gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
1313  }
1314  else
1315  {
1316  gridSizer->Add(1, 1, 0);
1317  }
1318 
1319  mSliders[p] = safenew wxSlider(w, ID_Sliders + p,
1320  0, 0, 1000,
1321  wxDefaultPosition,
1322  wxSize(200, -1));
1323 #if wxUSE_ACCESSIBILITY
1324  // so that name can be set on a standard control
1325  mSliders[p]->SetAccessible(safenew WindowAccessible(mSliders[p]));
1326 #endif
1327  mSliders[p]->SetName(labelText);
1328  gridSizer->Add(mSliders[p], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5);
1329 
1330  if (hashi)
1331  {
1332  if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
1333  {
1334  str.Printf(wxT("%d"), (int)(upper + 0.5));
1335  }
1336  else
1337  {
1338  str = Internat::ToDisplayString(upper);
1339  }
1340  item = safenew wxStaticText(w, 0, str);
1341  gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 5);
1342  }
1343  else
1344  {
1345  gridSizer->Add(1, 1, 0);
1346  }
1347 
1348  if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
1349  {
1350  fieldText.Printf(wxT("%d"), (int)(mInputControls[p] + 0.5));
1351 
1352  IntegerValidator<float> vld(&mInputControls[p]);
1353  vld.SetRange(haslo ? lower : INT_MIN,
1354  hashi ? upper : INT_MAX);
1355  mFields[p]->SetValidator(vld);
1356  }
1357  else
1358  {
1359  fieldText = Internat::ToDisplayString(mInputControls[p]);
1360 
1361  // > 12 decimal places can cause rounding errors in display.
1362  FloatingPointValidator<float> vld(6, &mInputControls[p]);
1363  vld.SetRange(lower, upper);
1364 
1365  // Set number of decimal places
1366  if (upper - lower < 10.0)
1367  {
1368  vld.SetStyle(NumValidatorStyle::THREE_TRAILING_ZEROES);
1369  }
1370  else if (upper - lower < 100.0)
1371  {
1372  vld.SetStyle(NumValidatorStyle::TWO_TRAILING_ZEROES);
1373  }
1374  else
1375  {
1376  vld.SetStyle(NumValidatorStyle::ONE_TRAILING_ZERO);
1377  }
1378 
1379  mFields[p]->SetValidator(vld);
1380  }
1381 
1382  // Set the textctrl value. This will trigger an event so OnTextCtrl()
1383  // can update the slider.
1384  mFields[p]->SetValue(fieldText);
1385  }
1386 
1387  paramSizer->Add(gridSizer.release(), 0, wxEXPAND | wxALL, 5);
1388  marginSizer->Add(paramSizer.release(), 0, wxEXPAND | wxALL, 5);
1389  }
1390 
1391  if (mNumOutputControls > 0)
1392  {
1393  auto paramSizer = std::make_unique<wxStaticBoxSizer>(wxVERTICAL, w, _("Effect Output"));
1394 
1395  auto gridSizer = std::make_unique<wxFlexGridSizer>(2, 0, 0);
1396  gridSizer->AddGrowableCol(1);
1397 
1398  wxControl *item;
1399 
1400  for (unsigned long p = 0; p < mData->PortCount; p++)
1401  {
1402  LADSPA_PortDescriptor d = mData->PortDescriptors[p];
1404  {
1405  continue;
1406  }
1407 
1408  wxString labelText = LAT1CTOWX(mData->PortNames[p]);
1409  item = safenew wxStaticText(w, 0, labelText + wxT(":"));
1410  gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
1411 
1412  //LADSPA_PortRangeHint hint = mData->PortRangeHints[p];
1413 
1414  wxString bound;
1415  float lower = 0.0;
1416  float upper = 1.0;
1417 
1418  /*
1419  bool haslo = false;
1420  bool hashi = false;
1421  bool forceint = false;
1422 
1423  if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor))
1424  {
1425  lower = hint.LowerBound;
1426  haslo = true;
1427  }
1428 
1429  if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor))
1430  {
1431  upper = hint.UpperBound;
1432  hashi = true;
1433  }
1434 
1435  if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor))
1436  {
1437  lower *= mSampleRate;
1438  upper *= mSampleRate;
1439  forceint = true;
1440  }
1441  */
1442 
1443  // Limit to the UI precision
1444  lower = ceilf(lower * 1000000.0) / 1000000.0;
1445  upper = floorf(upper * 1000000.0) / 1000000.0;
1446  mInputControls[p] = roundf(mInputControls[p] * 1000000.0) / 1000000.0;
1447 
1448  mMeters[p] = safenew LadspaEffectMeter(w, mOutputControls[p], lower, upper);
1449  mMeters[p]->SetLabel(labelText); // for screen readers
1450  gridSizer->Add(mMeters[p], 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 5);
1451  }
1452 
1453  paramSizer->Add(gridSizer.release(), 0, wxEXPAND | wxALL, 5);
1454  marginSizer->Add(paramSizer.release(), 0, wxEXPAND | wxALL, 5);
1455 
1456  RefreshControls(true);
1457  }
1458 
1459  w->SetSizer(uMarginSizer.release());
1460  }
1461 
1462  w->Layout();
1463 
1464  // Try to give the window a sensible default/minimum size
1465  wxSize sz1 = marginSizer->GetMinSize();
1466  wxSize sz2 = mParent->GetMinSize();
1467  w->SetSizeHints(wxSize(wxMin(sz1.x, sz2.x), wxMin(sz1.y, sz2.y)));
1468 
1469  // And let the parent reduce to the NEW minimum if possible
1470  mParent->SetSizeHints(-1, -1);
1471 
1472  return true;
1473 }
1474 
1476 {
1477  return false;
1478 }
1479 
1481 {
1482  if (!mParent->Validate())
1483  {
1484  return false;
1485  }
1486 
1487  if (GetType() == EffectTypeGenerate)
1488  {
1489  mHost->SetDuration(mDuration->GetValue());
1490  }
1491 
1492  return true;
1493 }
1494 
1496 {
1497  return true;
1498 }
1499 
1501 {
1502  mParent->RemoveEventHandler(this);
1503 
1504  mToggles.reset();
1505  mSliders.reset();
1506  mFields.reset();
1507  mLabels.reset();
1508 
1509  mUIHost = NULL;
1510  mParent = NULL;
1511  mDialog = NULL;
1512 
1513  return true;
1514 }
1515 
1517 {
1518  return false;
1519 }
1520 
1522 {
1523 }
1524 
1526 {
1527 }
1528 
1530 {
1531  return true;
1532 }
1533 
1535 {
1536  LadspaEffectOptionsDialog dlg(mParent, mHost);
1537  if (dlg.ShowModal())
1538  {
1539  // Reinitialize configuration options
1540  mHost->GetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency, true);
1541  }
1542 }
1543 
1544 // ============================================================================
1545 // LadspaEffect Implementation
1546 // ============================================================================
1547 
1549 {
1550  if (mLib.IsLoaded())
1551  {
1552  return true;
1553  }
1554 
1555  wxFileName ff = mPath;
1556  wxString envpath;
1557  bool hadpath = wxGetEnv(wxT("PATH"), &envpath);
1558  wxSetEnv(wxT("PATH"), ff.GetPath() + wxFILE_SEP_PATH + envpath);
1559  wxString saveOldCWD = ff.GetCwd();
1560  ff.SetCwd();
1561 
1562  LADSPA_Descriptor_Function mainFn = NULL;
1563 
1564  if (mLib.Load(mPath, wxDL_NOW))
1565  {
1566  wxLogNull logNo;
1567 
1568  mainFn = (LADSPA_Descriptor_Function) mLib.GetSymbol(wxT("ladspa_descriptor"));
1569  if (mainFn)
1570  {
1571  mData = mainFn(mIndex);
1572  return true;
1573  }
1574  }
1575 
1576  if (mLib.IsLoaded())
1577  {
1578  mLib.Unload();
1579  }
1580 
1581  wxSetWorkingDirectory(saveOldCWD);
1582  hadpath ? wxSetEnv(wxT("PATH"), envpath) : wxUnsetEnv(wxT("PATH"));
1583 
1584  return false;
1585 }
1586 
1588 {
1589  if (mLib.IsLoaded())
1590  {
1591  mLib.Unload();
1592  }
1593 }
1594 
1595 bool LadspaEffect::LoadParameters(const wxString & group)
1596 {
1597  wxString parms;
1598  if (!mHost->GetPrivateConfig(group, wxT("Parameters"), parms, wxEmptyString))
1599  {
1600  return false;
1601  }
1602 
1603  CommandParameters eap;
1604  if (!eap.SetParameters(parms))
1605  {
1606  return false;
1607  }
1608 
1609  return SetAutomationParameters(eap);
1610 }
1611 
1612 bool LadspaEffect::SaveParameters(const wxString & group)
1613 {
1614  CommandParameters eap;
1615  if (!GetAutomationParameters(eap))
1616  {
1617  return false;
1618  }
1619 
1620  wxString parms;
1621  if (!eap.GetParameters(parms))
1622  {
1623  return false;
1624  }
1625 
1626  return mHost->SetPrivateConfig(group, wxT("Parameters"), parms);
1627 }
1628 
1630 {
1631  /* Instantiate the plugin */
1632  LADSPA_Handle handle = mData->instantiate(mData, sampleRate);
1633  if (!handle)
1634  {
1635  return NULL;
1636  }
1637 
1638  for (unsigned long p = 0; p < mData->PortCount; p++)
1639  {
1640  LADSPA_PortDescriptor d = mData->PortDescriptors[p];
1641  if (LADSPA_IS_PORT_CONTROL(d))
1642  {
1643  if (LADSPA_IS_PORT_INPUT(d))
1644  {
1645  mData->connect_port(handle, p, &mInputControls[p]);
1646  }
1647  else
1648  {
1649  mData->connect_port(handle, p, &mOutputControls[p]);
1650  }
1651  }
1652  }
1653 
1654  if (mData->activate)
1655  {
1656  mData->activate(handle);
1657  }
1658 
1659  return handle;
1660 }
1661 
1663 {
1664  if (mData->deactivate)
1665  {
1666  mData->deactivate(handle);
1667  }
1668 
1669  mData->cleanup(handle);
1670 }
1671 
1672 void LadspaEffect::OnCheckBox(wxCommandEvent & evt)
1673 {
1674  int p = evt.GetId() - ID_Toggles;
1675 
1676  mInputControls[p] = mToggles[p]->GetValue();
1677 }
1678 
1679 void LadspaEffect::OnSlider(wxCommandEvent & evt)
1680 {
1681  int p = evt.GetId() - ID_Sliders;
1682 
1683  float val;
1684  float lower = float(0.0);
1685  float upper = float(10.0);
1686  float range;
1687  bool forceint = false;
1688 
1689  LADSPA_PortRangeHint hint = mData->PortRangeHints[p];
1691  lower = hint.LowerBound;
1693  upper = hint.UpperBound;
1695  lower *= mSampleRate;
1696  upper *= mSampleRate;
1697  forceint = true;
1698  }
1699 
1700  range = upper - lower;
1701 
1702  val = (mSliders[p]->GetValue() / 1000.0) * range + lower;
1703 
1704  wxString str;
1705  if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
1706  str.Printf(wxT("%d"), (int)(val + 0.5));
1707  else
1708  str = Internat::ToDisplayString(val);
1709 
1710  mFields[p]->SetValue(str);
1711 
1712  mInputControls[p] = val;
1713 }
1714 
1715 void LadspaEffect::OnTextCtrl(wxCommandEvent & evt)
1716 {
1717  LadspaEffect *that = reinterpret_cast<LadspaEffect *>(this);
1718  int p = evt.GetId() - ID_Texts;
1719 
1720  float val;
1721  float lower = float(0.0);
1722  float upper = float(10.0);
1723  float range;
1724 
1725  val = Internat::CompatibleToDouble(that->mFields[p]->GetValue());
1726 
1727  LADSPA_PortRangeHint hint = that->mData->PortRangeHints[p];
1728  if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor))
1729  lower = hint.LowerBound;
1730  if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor))
1731  upper = hint.UpperBound;
1732  if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor)) {
1733  lower *= mSampleRate;
1734  upper *= mSampleRate;
1735  }
1736  range = upper - lower;
1737 
1738  if (val < lower)
1739  val = lower;
1740  if (val > upper)
1741  val = upper;
1742 
1743  mInputControls[p] = val;
1744 
1745  that->mSliders[p]->SetValue((int)(((val-lower)/range) * 1000.0 + 0.5));
1746 }
1747 
1748 void LadspaEffect::RefreshControls(bool outputOnly)
1749 {
1750  if (!mParent)
1751  {
1752  return;
1753  }
1754 
1755  for (unsigned long p = 0; p < mData->PortCount; p++)
1756  {
1757  LADSPA_PortDescriptor d = mData->PortDescriptors[p];
1758  if (!(LADSPA_IS_PORT_CONTROL(d)))
1759  {
1760  continue;
1761  }
1762 
1763  wxString fieldText;
1764  LADSPA_PortRangeHint hint = mData->PortRangeHints[p];
1765 
1766  bool forceint = false;
1768  {
1769  forceint = true;
1770  }
1771 
1772  if (LADSPA_IS_PORT_OUTPUT(d))
1773  {
1774  continue;
1775  }
1776 
1777  if (outputOnly)
1778  {
1779  continue;
1780  }
1781 
1783  {
1784  mToggles[p]->SetValue(mInputControls[p] > 0);
1785  continue;
1786  }
1787 
1788  if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
1789  {
1790  fieldText.Printf(wxT("%d"), (int)(mInputControls[p] + 0.5));
1791  }
1792  else
1793  {
1794  fieldText = Internat::ToDisplayString(mInputControls[p]);
1795  }
1796 
1797  // Set the textctrl value. This will trigger an event so OnTextCtrl()
1798  // can update the slider.
1799  mFields[p]->SetValue(fieldText);
1800  }
1801 }
bool RealtimeProcessEnd() override
EVT_COMMAND_RANGE(ID_Slider, ID_Slider+NUMBER_OF_BANDS-1, wxEVT_COMMAND_SLIDER_UPDATED, EffectEqualization::OnSlider) EffectEqualization
virtual ~LadspaEffectMeter()
IdentInterfaceSymbol GetVendor() override
const LADSPA_Descriptor *(* LADSPA_Descriptor_Function)(unsigned long Index)
Definition: ladspa.h:593
bool LoadFactoryPreset(int id) override
void * LADSPA_Handle
Definition: ladspa.h:363
#define LADSPA_IS_HINT_DEFAULT_LOW(x)
Definition: ladspa.h:320
IdentInterfaceSymbol GetSymbol() override
bool HasOptions() override
void ShowOptions() override
An Effect that calls up a LADSPA plug in, i.e. many possible effects from this one class...
Definition: LadspaEffect.h:42
bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) override
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
bool AutoRegisterPlugins(PluginManagerInterface &pm) override
void DeleteInstance(IdentInterface *instance) override
void OnPaint(wxPaintEvent &evt)
EffectType GetType() override
size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen) override
bool CanExportPresets() override
virtual void FindFilesInPathList(const wxString &pattern, const wxArrayString &pathList, wxArrayString &files, bool directories=false)=0
bool SaveParameters(const wxString &group)
EffectHostInterface * mHost
size_t SetBlockSize(size_t maxBlockSize) override
#define LADSPA_IS_HINT_TOGGLED(x)
Definition: ladspa.h:312
#define LADSPA_IS_HINT_INTEGER(x)
Definition: ladspa.h:315
static const PluginID & DefaultRegistrationCallback(ModuleInterface *provider, IdentInterface *ident)
wxString GetPath() override
bool ProcessFinalize() override
void OnTextCtrl(wxCommandEvent &evt)
wxString GetDescription() override
const LADSPA_PortRangeHint * PortRangeHints
Definition: ladspa.h:419
bool IsGraphicalUI() override
int LADSPA_PortDescriptor
Definition: ladspa.h:152
bool GetAutomationParameters(CommandParameters &parms) override
void ImportPresets() override
#define LADSPA_IS_HINT_DEFAULT_100(x)
Definition: ladspa.h:332
wxString GetVersion() override
DECLARE_BUILTIN_MODULE(LadspaBuiltin)
#define LADSPA_IS_HINT_BOUNDED_BELOW(x)
Definition: ladspa.h:310
IdentInterfaceSymbol GetSymbol() override
Base class for many of the effects in Audacity.
Definition: Effect.h:62
#define XO(s)
Definition: Internat.h:33
void OnOk(wxCommandEvent &evt)
bool HideUI() override
wxArrayString GetFactoryPresets() override
#define LADSPA_IS_HINT_DEFAULT_HIGH(x)
Definition: ladspa.h:324
#define LADSPA_IS_HINT_SAMPLE_RATE(x)
Definition: ladspa.h:313
int GetMidiInCount() override
void SetSampleRate(double rate) override
wxString GetDescription() override
#define safenew
Definition: Audacity.h:230
ArrayOf< wxSlider * > mSliders
Definition: LadspaEffect.h:189
void EndHorizontalLay()
bool RealtimeSuspend() override
ArrayOf< wxTextCtrl * > mFields
Definition: LadspaEffect.h:190
wxArrayString FindPluginPaths(PluginManagerInterface &pm) override
IdentInterfaceSymbol GetFamilyId() override
virtual bool IsPluginRegistered(const wxString &path)=0
void SetHostUI(EffectUIHostInterface *host) override
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
LADSPA_PortRangeHintDescriptor HintDescriptor
Definition: ladspa.h:340
void EndVerticalLay()
const LADSPA_Descriptor * mData
Definition: LadspaEffect.h:153
wxString InstallPath() override
unsigned GetAudioInCount() override
LADSPA_Handle InitInstance(float sampleRate)
size_t GetTailSize() override
sampleCount GetLatency() override
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
Definition: Internat.cpp:122
LadspaEffectsModule(ModuleManagerInterface *moduleManager, const wxString *path)
#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x)
Definition: ladspa.h:322
bool RealtimeFinalize() override
#define LADSPA_IS_HINT_DEFAULT_0(x)
Definition: ladspa.h:328
void FreeInstance(LADSPA_Handle handle)
void RefreshControls(bool outputOnly=false)
#define LADSPA_IS_PORT_CONTROL(x)
Definition: ladspa.h:170
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
int GetMidiOutCount() override
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the Shuttle cla...
#define LADSPA_IS_HINT_DEFAULT_440(x)
Definition: ladspa.h:334
wxArrayString GetSearchPaths()
bool RealtimeResume() override
virtual ~LadspaEffect()
const float & mVal
void OnIdle(wxIdleEvent &evt)
_LADSPA_PortRangeHint is a structure that gives parameter validation information for a LADSPA (Linux ...
Definition: ladspa.h:337
if(pTrack &&pTrack->GetDisplay()!=WaveTrack::Spectrum)
bool GetParameters(wxString &parms)
unsigned GetAudioOutCount() override
int min(int a, int b)
bool SupportsAutomation() override
#define LAT1CTOWX(X)
Definition: Internat.h:180
bool RealtimeProcessStart() override
DECLARE_MODULE_ENTRY(AudacityModule)
bool LoadUserPreset(const wxString &name) override
IdentInterfaceSymbol pairs a persistent string identifier used internally with an optional...
enum ChannelName * ChannelNames
static const wxChar * kShippedEffects[]
void PopulateOrExchange(ShuttleGui &S)
IdentInterfaceSymbol GetVendor() override
size_t RealtimeProcess(int group, float **inbuf, float **outbuf, size_t numSamples) override
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x)
Definition: ladspa.h:318
wxEVT_COMMAND_TEXT_UPDATED
Definition: Nyquist.cpp:111
wxString GetPath() override
#define LADSPA_IS_PORT_AUDIO(x)
Definition: ladspa.h:171
bool SetParameters(const wxString &parms)
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
ValueRestorer< T > valueRestorer(T &var)
Definition: MemoryX.h:494
_LADSPA_Descriptor is a structure that provides the API to a LADSPA (Linux Audio Plugin Architecture)...
Definition: ladspa.h:373
bool LoadParameters(const wxString &group)
#define LADSPAEFFECTS_FAMILY
Definition: LadspaEffect.h:32
ModuleManagerInterface * mModMan
Definition: LadspaEffect.h:245
EffectHostInterface is a decorator of a EffectUIClientInterface. It adds virtual (abstract) functions...
void OnErase(wxEraseEvent &evt)
EffectType
bool Initialize() override
#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x)
Definition: ladspa.h:326
wxCheckBox * TieCheckBox(const wxString &Prompt, WrappedType &WrappedRef)
unsigned DiscoverPluginsAtPath(const wxString &path, wxString &errMsg, const RegistrationCallback &callback) override
#define LADSPA_IS_PORT_INPUT(x)
Definition: ladspa.h:168
const wxChar * name
Definition: Distortion.cpp:94
std::function< const PluginID &(ModuleInterface *, IdentInterface *) > RegistrationCallback
LADSPA_Data LowerBound
Definition: ladspa.h:345
bool IsReady() override
bool RealtimeInitialize() override
wxStaticText * AddVariableText(const wxString &Str, bool bCenter=false, int PositionFlags=0)
Definition: ShuttleGui.cpp:414
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x)
Definition: ladspa.h:311
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:149
void OnSize(wxSizeEvent &evt)
wxStaticBox * StartStatic(const wxString &Str, int iProp=0)
Definition: ShuttleGui.cpp:763
bool IsPluginValid(const wxString &path, bool bFast) override
wxString GetVersion() override
#define LADSPA_IS_HINT_LOGARITHMIC(x)
Definition: ladspa.h:314
bool SetAutomationParameters(CommandParameters &parms) override
bool SaveUserPreset(const wxString &name) override
void OnCheckBox(wxCommandEvent &evt)
void ExportPresets() override
bool SetHost(EffectHostInterface *host) override
Options & AutoPos(bool value)
#define LADSPAEFFECTS_VERSION
Definition: LadspaEffect.h:28
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxButton *extra=NULL)
bool IsInteractive() override
END_EVENT_TABLE()
#define LADSPA_IS_PORT_OUTPUT(x)
Definition: ladspa.h:169
bool IsDefault() override
bool ShowInterface(wxWindow *parent, bool forceModal=false) override
void Terminate() override
bool SupportsRealtime() override
void SetBorder(int Border)
Definition: ShuttleGui.h:286
IdentInterface provides name / vendor / version functions to identify plugins. It is what makes a cla...
LADSPA_Data UpperBound
Definition: ladspa.h:350
bool CloseUI() override
static wxString PlugInDir()
The user plug-in directory (not a system one)
Definition: FileNames.cpp:214
bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap=NULL) override
bool ValidateUI() override
bool PopulateUI(wxWindow *parent) override
bool IsLegacy() override
IdentInterface * CreateInstance(const wxString &path) override
#define LADSPA_IS_HINT_DEFAULT_1(x)
Definition: ladspa.h:330
bool LoadFactoryDefaults() override
EffectUIHostInterface has nothing in it. It is provided so that an Effect can call SetHostUI passing ...
void OnSlider(wxCommandEvent &evt)
wxArrayString FileExtensions() override
virtual ~LadspaEffectsModule()
void StartVerticalLay(int iProp=1)