Audacity  2.3.1
Effect.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Effect.cpp
6 
7  Dominic Mazzoni
8  Vaughan Johnson
9  Martyn Shaw
10 
11 *******************************************************************//****************************************************************//*******************************************************************/
23 
24 #include "../Audacity.h"
25 #include "Effect.h"
26 
27 #include <algorithm>
28 
29 #include <wx/defs.h>
30 #include <wx/hashmap.h>
31 #include <wx/sizer.h>
32 #include <wx/stockitem.h>
33 #include <wx/string.h>
34 #include <wx/tglbtn.h>
35 #include <wx/timer.h>
36 #include <wx/utils.h>
37 #include <wx/log.h>
38 
40 
41 #include "../AudacityException.h"
42 #include "../AudioIO.h"
43 #include "../LabelTrack.h"
44 #include "../Menus.h"
45 #include "../Mix.h"
46 #include "../Prefs.h"
47 #include "../Project.h"
48 #include "../ShuttleGui.h"
49 #include "../Shuttle.h"
50 #include "../WaveTrack.h"
51 #include "../toolbars/ControlToolBar.h"
52 #include "../widgets/AButton.h"
53 #include "../widgets/ProgressDialog.h"
54 #include "../ondemand/ODManager.h"
55 #include "TimeWarper.h"
56 #include "nyquist/Nyquist.h"
57 #include "../widgets/HelpSystem.h"
58 #include "../widgets/LinkingHtmlWindow.h"
59 #include "../widgets/NumericTextCtrl.h"
60 #include "../widgets/ErrorDialog.h"
61 #include "../FileNames.h"
62 #include "../commands/AudacityCommand.h"
63 #include "../commands/CommandContext.h"
64 
65 #if defined(__WXMAC__)
66 #include <Cocoa/Cocoa.h>
67 #endif
68 
69 #include "../Experimental.h"
70 #include "../commands/ScreenshotCommand.h"
71 
72 #include <unordered_map>
73 
74 // Effect application counter
76 
77 static const int kDummyID = 20000;
78 static const int kSaveAsID = 20001;
79 static const int kImportID = 20002;
80 static const int kExportID = 20003;
81 static const int kDefaultsID = 20004;
82 static const int kOptionsID = 20005;
83 static const int kUserPresetsDummyID = 20006;
84 static const int kDeletePresetDummyID = 20007;
85 static const int kMenuID = 20100;
86 static const int kEnableID = 20101;
87 static const int kPlayID = 20102;
88 static const int kRewindID = 20103;
89 static const int kFFwdID = 20104;
90 static const int kPlaybackID = 20105;
91 static const int kCaptureID = 20106;
92 static const int kUserPresetsID = 21000;
93 static const int kDeletePresetID = 22000;
94 static const int kFactoryPresetsID = 23000;
95 
96 const wxString Effect::kUserPresetIdent = wxT("User Preset:");
97 const wxString Effect::kFactoryPresetIdent = wxT("Factory Preset:");
98 const wxString Effect::kCurrentSettingsIdent = wxT("<Current Settings>");
99 const wxString Effect::kFactoryDefaultsIdent = wxT("<Factory Defaults>");
100 
101 using t2bHash = std::unordered_map< void*, bool >;
102 
104 {
105  mClient = NULL;
106 
107  mTracks = NULL;
108  mT0 = 0.0;
109  mT1 = 0.0;
110  mDuration = 0.0;
111  mIsPreview = false;
112  mIsLinearEffect = false;
113  mPreviewWithNotSelected = false;
114  mPreviewFullSelection = false;
115  mNumTracks = 0;
116  mNumGroups = 0;
117  mProgress = NULL;
118 
119  mRealtimeSuspendLock.Enter();
120  mRealtimeSuspendCount = 1; // Effects are initially suspended
121  mRealtimeSuspendLock.Leave();
122 
123  mUIParent = NULL;
124  mUIDialog = NULL;
125 
126  mNumAudioIn = 0;
127  mNumAudioOut = 0;
128 
129  mBufferSize = 0;
130  mBlockSize = 0;
131  mNumChannels = 0;
132 
133  mUIDebug = false;
134 
136  mProjectRate = p ? p->GetRate() : 44100;
137 
138  mIsBatch = false;
139 }
140 
142 {
143  if (mUIDialog)
144  {
145  mUIDialog->Close();
146  }
147 }
148 
149 // EffectDefinitionInterface implementation
150 
152 {
153  if (mClient)
154  {
155  return mClient->GetType();
156  }
157 
158  return EffectTypeNone;
159 }
160 
161 wxString Effect::GetPath()
162 {
163  if (mClient)
164  {
165  return mClient->GetPath();
166  }
167 
169 }
170 
172 {
173  if (mClient)
174  {
175  return mClient->GetSymbol();
176  }
177 
178  return {};
179 }
180 
182 {
183  if (mClient)
184  {
185  return mClient->GetVendor();
186  }
187 
188  return XO("Audacity");
189 }
190 
192 {
193  if (mClient)
194  {
195  return mClient->GetVersion();
196  }
197 
199 }
200 
202 {
203  if (mClient)
204  {
205  return mClient->GetDescription();
206  }
207 
208  return wxEmptyString;
209 }
210 
212 {
213  if (mClient)
214  {
215  return mClient->GetFamilyId();
216  }
217 
218  // Unusually, the internal and visible strings differ for the built-in
219  // effect family.
220  return { wxT("Audacity"), XO("Built-in") };
221 }
222 
224 {
225  if (mClient)
226  {
227  return mClient->IsInteractive();
228  }
229 
230  return true;
231 }
232 
234 {
235  if (mClient)
236  {
237  return mClient->IsDefault();
238  }
239 
240  return true;
241 }
242 
244 {
245  if (mClient)
246  {
247  return false;
248  }
249 
250  return true;
251 }
252 
254 {
255  if (mClient)
256  {
257  return mClient->SupportsRealtime();
258  }
259 
260  return false;
261 }
262 
264 {
265  if (mClient)
266  {
267  return mClient->SupportsAutomation();
268  }
269 
270  return true;
271 }
272 
273 // EffectClientInterface implementation
274 
276 {
277  if (mClient)
278  {
279  return mClient->SetHost(host);
280  }
281 
282  return true;
283 }
284 
286 {
287  if (mClient)
288  {
289  return mClient->GetAudioInCount();
290  }
291 
292  return 0;
293 }
294 
296 {
297  if (mClient)
298  {
299  return mClient->GetAudioOutCount();
300  }
301 
302  return 0;
303 }
304 
306 {
307  if (mClient)
308  {
309  return mClient->GetMidiInCount();
310  }
311 
312  return 0;
313 }
314 
316 {
317  if (mClient)
318  {
319  return mClient->GetMidiOutCount();
320  }
321 
322  return 0;
323 }
324 
325 void Effect::SetSampleRate(double rate)
326 {
327  if (mClient)
328  {
329  mClient->SetSampleRate(rate);
330  }
331 
332  mSampleRate = rate;
333 }
334 
335 size_t Effect::SetBlockSize(size_t maxBlockSize)
336 {
337  if (mClient)
338  {
339  return mClient->SetBlockSize(maxBlockSize);
340  }
341 
342  mBlockSize = maxBlockSize;
343 
344  return mBlockSize;
345 }
346 
348 {
349  if (mClient)
350  {
351  return mClient->GetLatency();
352  }
353 
354  return 0;
355 }
356 
358 {
359  if (mClient)
360  {
361  return mClient->GetTailSize();
362  }
363 
364  return 0;
365 }
366 
368 {
369  if (mClient)
370  {
371  return mClient->IsReady();
372  }
373 
374  return true;
375 }
376 
378 {
379  if (mClient)
380  {
381  return mClient->ProcessInitialize(totalLen, chanMap);
382  }
383 
384  return true;
385 }
386 
388 {
389  if (mClient)
390  {
391  return mClient->ProcessFinalize();
392  }
393 
394  return true;
395 }
396 
397 size_t Effect::ProcessBlock(float **inBlock, float **outBlock, size_t blockLen)
398 {
399  if (mClient)
400  {
401  return mClient->ProcessBlock(inBlock, outBlock, blockLen);
402  }
403 
404  return 0;
405 }
406 
408 {
409  if (mClient)
410  {
412  return mClient->RealtimeInitialize();
413  }
414 
415  mBlockSize = 512;
416 
417  return false;
418 }
419 
420 bool Effect::RealtimeAddProcessor(unsigned numChannels, float sampleRate)
421 {
422  if (mClient)
423  {
424  return mClient->RealtimeAddProcessor(numChannels, sampleRate);
425  }
426 
427  return true;
428 }
429 
431 {
432  if (mClient)
433  {
434  return mClient->RealtimeFinalize();
435  }
436 
437  return false;
438 }
439 
441 {
442  if (mClient)
443  {
444  if (mClient->RealtimeSuspend())
445  {
446  mRealtimeSuspendLock.Enter();
448  mRealtimeSuspendLock.Leave();
449  return true;
450  }
451 
452  return false;
453  }
454 
455  mRealtimeSuspendLock.Enter();
457  mRealtimeSuspendLock.Leave();
458 
459  return true;
460 }
461 
463 {
464  if (mClient)
465  {
466  if (mClient->RealtimeResume())
467  {
468  mRealtimeSuspendLock.Enter();
470  mRealtimeSuspendLock.Leave();
471  return true;
472  }
473 
474  return false;
475  }
476 
477  mRealtimeSuspendLock.Enter();
479  mRealtimeSuspendLock.Leave();
480 
481  return true;
482 }
483 
485 {
486  if (mClient)
487  {
488  return mClient->RealtimeProcessStart();
489  }
490 
491  return true;
492 }
493 
494 size_t Effect::RealtimeProcess(int group,
495  float **inbuf,
496  float **outbuf,
497  size_t numSamples)
498 {
499  if (mClient)
500  {
501  return mClient->RealtimeProcess(group, inbuf, outbuf, numSamples);
502  }
503 
504  return 0;
505 }
506 
508 {
509  if (mClient)
510  {
511  return mClient->RealtimeProcessEnd();
512  }
513 
514  return true;
515 }
516 
517 bool Effect::ShowInterface(wxWindow *parent, bool forceModal)
518 {
519  if (!IsInteractive())
520  {
521  return true;
522  }
523 
524  if (mUIDialog)
525  {
526  if ( mUIDialog->Close(true) )
527  mUIDialog = nullptr;
528  return false;
529  }
530 
531  if (mClient)
532  {
533  return mClient->ShowInterface(parent, forceModal);
534  }
535 
536  // mUIDialog is null
537  auto cleanup = valueRestorer( mUIDialog );
538 
539  mUIDialog = CreateUI(parent, this);
540  if (!mUIDialog)
541  {
542  return false;
543  }
544 
545 
546  mUIDialog->Layout();
547  mUIDialog->Fit();
548  mUIDialog->SetMinSize(mUIDialog->GetSize());
549 
551  return false;
552 
553  if( SupportsRealtime() && !forceModal )
554  {
555  mUIDialog->Show();
556  cleanup.release();
557 
558  // Return false to bypass effect processing
559  return false;
560  }
561 
562  bool res = mUIDialog->ShowModal() != 0;
563 
564  return res;
565 }
566 
568 {
569  if (mClient)
570  {
571  return mClient->GetAutomationParameters(parms);
572  }
573 
574  return true;
575 }
576 
578 {
579  if (mClient)
580  {
581  return mClient->SetAutomationParameters(parms);
582  }
583 
584  return true;
585 }
586 
587 bool Effect::LoadUserPreset(const wxString & name)
588 {
589  if (mClient)
590  {
591  return mClient->LoadUserPreset(name);
592  }
593 
594  wxString parms;
595  if (!GetPrivateConfig(name, wxT("Parameters"), parms))
596  {
597  return false;
598  }
599 
600  return SetAutomationParameters(parms);
601 }
602 
603 bool Effect::SaveUserPreset(const wxString & name)
604 {
605  if (mClient)
606  {
607  return mClient->SaveUserPreset(name);
608  }
609 
610  wxString parms;
611  if (!GetAutomationParameters(parms))
612  {
613  return false;
614  }
615 
616  return SetPrivateConfig(name, wxT("Parameters"), parms);
617 }
618 
620 {
621  if (mClient)
622  {
623  return mClient->GetFactoryPresets();
624  }
625 
626  return wxArrayString();
627 }
628 
630 {
631  if (mClient)
632  {
633  return mClient->LoadFactoryPreset(id);
634  }
635 
636  return true;
637 }
638 
640 {
641  if (mClient)
642  {
643  return mClient->LoadFactoryDefaults();
644  }
645 
647 }
648 
649 // EffectUIClientInterface implementation
650 
652 {
653 }
654 
655 bool Effect::PopulateUI(wxWindow *parent)
656 {
657  mUIParent = parent;
658  mUIParent->PushEventHandler(this);
659 
660 // LoadUserPreset(GetCurrentSettingsGroup());
661 
664 
665  mUIParent->SetMinSize(mUIParent->GetSizer()->GetMinSize());
666 
667  return true;
668 }
669 
671 {
672  return false;
673 }
674 
676 {
677  return mUIParent->Validate();
678 }
679 
681 {
682  return true;
683 }
684 
686 {
687  if (mUIParent)
688  mUIParent->RemoveEventHandler(this);
689 
690  mUIParent = NULL;
691  mUIDialog = NULL;
692 
693  return true;
694 }
695 
697 {
698  return false;
699 }
700 
702 {
703 }
704 
706 {
707 }
708 
710 {
711  return false;
712 }
713 
715 {
716 }
717 
718 // EffectHostInterface implementation
719 
721 {
722  return 30.0;
723 }
724 
726 {
727  if (mDuration < 0.0)
728  {
729  mDuration = 0.0;
730  }
731 
732  return mDuration;
733 }
734 
736 {
737  return mDurationFormat;
738 }
739 
741 {
743 }
744 
745 void Effect::SetDuration(double seconds)
746 {
747  if (seconds < 0.0)
748  {
749  seconds = 0.0;
750  }
751 
752  if (GetType() == EffectTypeGenerate)
753  {
754  SetPrivateConfig(GetCurrentSettingsGroup(), wxT("LastUsedDuration"), seconds);
755  }
756 
757  mDuration = seconds;
758 
759  mIsSelection = false;
760 
761  return;
762 }
763 
765 {
766  auto &project = *GetActiveProject();
767  CommandContext context( project );
768  // This is absolute hackage...but easy and I can't think of another way just now.
769  //
770  // It should callback to the EffectManager to kick off the processing
771  return GetMenuCommandHandler(project).DoEffect(GetID(), context,
773 }
774 
776 {
777  Preview(false);
778 }
779 
780 wxDialog *Effect::CreateUI(wxWindow *parent, EffectUIClientInterface *client)
781 {
783  { safenew EffectUIHost{ parent, this, client} };
784 
785  if (dlg->Initialize())
786  {
787  // release() is safe because parent will own it
788  return dlg.release();
789  }
790 
791  return NULL;
792 }
793 
794 wxString Effect::GetUserPresetsGroup(const wxString & name)
795 {
796  wxString group = wxT("UserPresets");
797  if (!name.IsEmpty())
798  {
799  group += wxCONFIG_PATH_SEPARATOR + name;
800  }
801 
802  return group;
803 }
804 
806 {
807  return wxT("CurrentSettings");
808 }
809 
811 {
812  return wxT("FactoryDefaults");
813 }
814 
816 {
817  return wxT("SavedState");
818 }
819 
820 // ConfigClientInterface implementation
821 bool Effect::HasSharedConfigGroup(const wxString & group)
822 {
823  return PluginManager::Get().HasSharedConfigGroup(GetID(), group);
824 }
825 
826 bool Effect::GetSharedConfigSubgroups(const wxString & group, wxArrayString & subgroups)
827 {
828  return PluginManager::Get().GetSharedConfigSubgroups(GetID(), group, subgroups);
829 }
830 
831 bool Effect::GetSharedConfig(const wxString & group, const wxString & key, wxString & value, const wxString & defval)
832 {
833  return PluginManager::Get().GetSharedConfig(GetID(), group, key, value, defval);
834 }
835 
836 bool Effect::GetSharedConfig(const wxString & group, const wxString & key, int & value, int defval)
837 {
838  return PluginManager::Get().GetSharedConfig(GetID(), group, key, value, defval);
839 }
840 
841 bool Effect::GetSharedConfig(const wxString & group, const wxString & key, bool & value, bool defval)
842 {
843  return PluginManager::Get().GetSharedConfig(GetID(), group, key, value, defval);
844 }
845 
846 bool Effect::GetSharedConfig(const wxString & group, const wxString & key, float & value, float defval)
847 {
848  return PluginManager::Get().GetSharedConfig(GetID(), group, key, value, defval);
849 }
850 
851 bool Effect::GetSharedConfig(const wxString & group, const wxString & key, double & value, double defval)
852 {
853  return PluginManager::Get().GetSharedConfig(GetID(), group, key, value, defval);
854 }
855 
856 bool Effect::SetSharedConfig(const wxString & group, const wxString & key, const wxString & value)
857 {
858  return PluginManager::Get().SetSharedConfig(GetID(), group, key, value);
859 }
860 
861 bool Effect::SetSharedConfig(const wxString & group, const wxString & key, const int & value)
862 {
863  return PluginManager::Get().SetSharedConfig(GetID(), group, key, value);
864 }
865 
866 bool Effect::SetSharedConfig(const wxString & group, const wxString & key, const bool & value)
867 {
868  return PluginManager::Get().SetSharedConfig(GetID(), group, key, value);
869 }
870 
871 bool Effect::SetSharedConfig(const wxString & group, const wxString & key, const float & value)
872 {
873  return PluginManager::Get().SetSharedConfig(GetID(), group, key, value);
874 }
875 
876 bool Effect::SetSharedConfig(const wxString & group, const wxString & key, const double & value)
877 {
878  return PluginManager::Get().SetSharedConfig(GetID(), group, key, value);
879 }
880 
881 bool Effect::RemoveSharedConfigSubgroup(const wxString & group)
882 {
884 }
885 
886 bool Effect::RemoveSharedConfig(const wxString & group, const wxString & key)
887 {
888  return PluginManager::Get().RemoveSharedConfig(GetID(), group, key);
889 }
890 
891 bool Effect::HasPrivateConfigGroup(const wxString & group)
892 {
894 }
895 
896 bool Effect::GetPrivateConfigSubgroups(const wxString & group, wxArrayString & subgroups)
897 {
898  return PluginManager::Get().GetPrivateConfigSubgroups(GetID(), group, subgroups);
899 }
900 
901 bool Effect::GetPrivateConfig(const wxString & group, const wxString & key, wxString & value, const wxString & defval)
902 {
903  return PluginManager::Get().GetPrivateConfig(GetID(), group, key, value, defval);
904 }
905 
906 bool Effect::GetPrivateConfig(const wxString & group, const wxString & key, int & value, int defval)
907 {
908  return PluginManager::Get().GetPrivateConfig(GetID(), group, key, value, defval);
909 }
910 
911 bool Effect::GetPrivateConfig(const wxString & group, const wxString & key, bool & value, bool defval)
912 {
913  return PluginManager::Get().GetPrivateConfig(GetID(), group, key, value, defval);
914 }
915 
916 bool Effect::GetPrivateConfig(const wxString & group, const wxString & key, float & value, float defval)
917 {
918  return PluginManager::Get().GetPrivateConfig(GetID(), group, key, value, defval);
919 }
920 
921 bool Effect::GetPrivateConfig(const wxString & group, const wxString & key, double & value, double defval)
922 {
923  return PluginManager::Get().GetPrivateConfig(GetID(), group, key, value, defval);
924 }
925 
926 bool Effect::SetPrivateConfig(const wxString & group, const wxString & key, const wxString & value)
927 {
928  return PluginManager::Get().SetPrivateConfig(GetID(), group, key, value);
929 }
930 
931 bool Effect::SetPrivateConfig(const wxString & group, const wxString & key, const int & value)
932 {
933  return PluginManager::Get().SetPrivateConfig(GetID(), group, key, value);
934 }
935 
936 bool Effect::SetPrivateConfig(const wxString & group, const wxString & key, const bool & value)
937 {
938  return PluginManager::Get().SetPrivateConfig(GetID(), group, key, value);
939 }
940 
941 bool Effect::SetPrivateConfig(const wxString & group, const wxString & key, const float & value)
942 {
943  return PluginManager::Get().SetPrivateConfig(GetID(), group, key, value);
944 }
945 
946 bool Effect::SetPrivateConfig(const wxString & group, const wxString & key, const double & value)
947 {
948  return PluginManager::Get().SetPrivateConfig(GetID(), group, key, value);
949 }
950 
951 bool Effect::RemovePrivateConfigSubgroup(const wxString & group)
952 {
954 }
955 
956 bool Effect::RemovePrivateConfig(const wxString & group, const wxString & key)
957 {
958  return PluginManager::Get().RemovePrivateConfig(GetID(), group, key);
959 }
960 
961 // Effect implementation
962 
964 {
965  if (mClient)
966  {
968  }
969 
970  return PluginManager::GetID(this);
971 }
972 
974 {
975  // Let destructor know we need to be shutdown
976  mClient = client;
977 
978  // Set host so client startup can use our services
979  if (!SetHost(this))
980  {
981  // Bail if the client startup fails
982  mClient = NULL;
983  return false;
984  }
985 
988 
989  bool haveDefaults;
990  GetPrivateConfig(GetFactoryDefaultsGroup(), wxT("Initialized"), haveDefaults, false);
991  if (!haveDefaults)
992  {
994  SetPrivateConfig(GetFactoryDefaultsGroup(), wxT("Initialized"), true);
995  }
997 
998  return Startup();
999 }
1000 
1002 {
1003  return true;
1004 }
1005 
1006 bool Effect::GetAutomationParameters(wxString & parms)
1007 {
1008  CommandParameters eap;
1009 
1011  {
1012  return false;
1013  }
1014 
1016  S.mpEap = &eap;
1017  if( DefineParams( S ) ){
1018  ;// got eap value using DefineParams.
1019  }
1020  // Won't be needed in future
1021  else if (!GetAutomationParameters(eap))
1022  {
1023  return false;
1024  }
1025 
1026  return eap.GetParameters(parms);
1027 }
1028 
1029 bool Effect::SetAutomationParameters(const wxString & parms)
1030 {
1031  wxString preset = parms;
1032  bool success = false;
1033  if (preset.StartsWith(kUserPresetIdent))
1034  {
1035  preset.Replace(kUserPresetIdent, wxEmptyString, false);
1036  success = LoadUserPreset(GetUserPresetsGroup(preset));
1037  }
1038  else if (preset.StartsWith(kFactoryPresetIdent))
1039  {
1040  preset.Replace(kFactoryPresetIdent, wxEmptyString, false);
1041  wxArrayString presets = GetFactoryPresets();
1042  success = LoadFactoryPreset(presets.Index(preset));
1043  }
1044  else if (preset.StartsWith(kCurrentSettingsIdent))
1045  {
1046  preset.Replace(kCurrentSettingsIdent, wxEmptyString, false);
1048  }
1049  else if (preset.StartsWith(kFactoryDefaultsIdent))
1050  {
1051  preset.Replace(kFactoryDefaultsIdent, wxEmptyString, false);
1053  }
1054  else
1055  {
1056  CommandParameters eap(parms);
1058  S.SetForValidating( &eap );
1059  // DefineParams returns false if not defined for this effect.
1060  if( !DefineParams( S ) )
1061  // the old method...
1062  success = SetAutomationParameters(eap);
1063  else if( !S.bOK )
1064  success = false;
1065  else{
1066  success = true;
1067  S.SetForWriting( &eap );
1068  DefineParams( S );
1069  }
1070  }
1071 
1072  if (!success)
1073  {
1075  wxString::Format(
1076  _("%s: Could not load settings below. Default settings will be used.\n\n%s"),
1078  preset
1079  )
1080  );
1081  // We are using defualt settings and we still wish to continue.
1082  return true;
1083  //return false;
1084  }
1085 
1086  if (!mUIDialog)
1087  {
1088  return true;
1089  }
1090 
1091  return TransferDataToWindow();
1092 }
1093 
1094 wxArrayString Effect::GetUserPresets()
1095 {
1096  wxArrayString presets;
1097 
1098  GetPrivateConfigSubgroups(GetUserPresetsGroup(wxEmptyString), presets);
1099 
1100  presets.Sort();
1101 
1102  return presets;
1103 }
1104 
1106 {
1108 }
1109 
1111 {
1113 }
1114 
1115 wxString Effect::GetPreset(wxWindow * parent, const wxString & parms)
1116 {
1117  EffectPresetsDialog dlg(parent, this);
1118  dlg.Layout();
1119  dlg.Fit();
1120  dlg.SetSize(dlg.GetMinSize());
1121  dlg.CenterOnParent();
1122  dlg.SetSelected(parms);
1123 
1124  if (dlg.ShowModal())
1125  {
1126  return dlg.GetSelected();
1127  }
1128 
1129  return wxEmptyString;
1130 }
1131 
1133 {
1134  return wxEmptyString;
1135 }
1136 
1138 {
1139  return wxEmptyString;
1140 }
1141 
1143 {
1144  return mIsBatch;
1145 }
1146 
1148 {
1149  mIsBatch = start;
1150 
1151  if (start)
1152  {
1154  }
1155  else
1156  {
1158  }
1159 }
1160 
1161 bool Effect::DoEffect(wxWindow *parent,
1162  double projectRate,
1163  TrackList *list,
1164  TrackFactory *factory,
1165  SelectedRegion *selectedRegion,
1166  bool shouldPrompt /* = true */)
1167 {
1168  wxASSERT(selectedRegion->duration() >= 0.0);
1169 
1170  mOutputTracks.reset();
1171 
1172  mpSelectedRegion = selectedRegion;
1173  mFactory = factory;
1174  mProjectRate = projectRate;
1175  mTracks = list;
1176 
1177  // Update track/group counts
1178  CountWaveTracks();
1179 
1180  bool isSelection = false;
1181 
1182  mDuration = 0.0;
1183  if (GetType() == EffectTypeGenerate)
1184  {
1185  GetPrivateConfig(GetCurrentSettingsGroup(), wxT("LastUsedDuration"), mDuration, GetDefaultDuration());
1186  }
1187 
1188  WaveTrack *newTrack{};
1189  bool success = false;
1190  auto oldDuration = mDuration;
1191 
1192  auto cleanup = finally( [&] {
1193  if (!success) {
1194  if (newTrack) {
1195  mTracks->Remove(newTrack);
1196  }
1197  // LastUsedDuration may have been modified by Preview.
1198  SetDuration(oldDuration);
1199  }
1200 
1201  End();
1202  ReplaceProcessedTracks( false );
1203  } );
1204 
1206  newTrack = static_cast<WaveTrack*>(mTracks->Add(mFactory->NewWaveTrack()));
1207  newTrack->SetSelected(true);
1208  }
1209 
1210  mT0 = selectedRegion->t0();
1211  mT1 = selectedRegion->t1();
1212  if (mT1 > mT0)
1213  {
1214  // there is a selection: let's fit in there...
1215  // MJS: note that this is just for the TTC and is independent of the track rate
1216  // but we do need to make sure we have the right number of samples at the project rate
1217  double quantMT0 = QUANTIZED_TIME(mT0, mProjectRate);
1218  double quantMT1 = QUANTIZED_TIME(mT1, mProjectRate);
1219  mDuration = quantMT1 - quantMT0;
1220  isSelection = true;
1221  }
1222  mT1 = mT0 + mDuration;
1223 
1224  mDurationFormat = isSelection
1227 
1228 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
1229  mF0 = selectedRegion->f0();
1230  mF1 = selectedRegion->f1();
1231  wxArrayString Names;
1233  Names.Add(wxT("control-f0"));
1235  Names.Add(wxT("control-f1"));
1236  SetPresetParameters( &Names, NULL );
1237 
1238 #endif
1239  CountWaveTracks();
1240 
1241  // Note: Init may read parameters from preferences
1242  if (!Init())
1243  {
1244  return false;
1245  }
1246 
1247  // Prompting will be bypassed when applying an effect that has already
1248  // been configured, e.g. repeating the last effect on a different selection.
1249  // Prompting may call Effect::Preview
1250  if (shouldPrompt && IsInteractive() && !PromptUser(parent))
1251  {
1252  return false;
1253  }
1254 
1255  bool returnVal = true;
1256  bool skipFlag = CheckWhetherSkipEffect();
1257  if (skipFlag == false)
1258  {
1259  auto name = GetTranslatedName();
1260  ProgressDialog progress{
1261  name,
1262  wxString::Format(_("Applying %s..."), name),
1264  };
1265  auto vr = valueRestorer( mProgress, &progress );
1266 
1267  returnVal = Process();
1268  }
1269 
1270  if (returnVal && (mT1 >= mT0 ))
1271  {
1272  selectedRegion->setTimes(mT0, mT1);
1273  }
1274 
1275  success = returnVal;
1276  return returnVal;
1277 }
1278 
1279 bool Effect::Delegate( Effect &delegate, wxWindow *parent, bool shouldPrompt)
1280 {
1281  return delegate.DoEffect( parent, mProjectRate, mTracks, mFactory,
1282  mpSelectedRegion, shouldPrompt );
1283 }
1284 
1285 // All legacy effects should have this overridden
1287 {
1288  return true;
1289 }
1290 
1291 // Remove this method once NoiseReduction gets migrated
1292 bool Effect::PromptUser(wxWindow *parent)
1293 {
1294  return ShowInterface(parent, IsBatchProcessing());
1295 }
1296 
1298 {
1299  return mPass;
1300 }
1301 
1303 {
1304  return true;
1305 }
1306 
1308 {
1309  return false;
1310 }
1311 
1313 {
1314  CopyInputTracks(true);
1315  bool bGoodResult = true;
1316 
1317  // It's possible that the number of channels the effect expects changed based on
1318  // the parameters (the Audacity Reverb effect does when the stereo width is 0).
1321 
1322  mPass = 1;
1323  if (InitPass1())
1324  {
1325  bGoodResult = ProcessPass();
1326  mPass = 2;
1327  if (bGoodResult && InitPass2())
1328  {
1329  bGoodResult = ProcessPass();
1330  }
1331  }
1332 
1333  ReplaceProcessedTracks(bGoodResult);
1334 
1335  return bGoodResult;
1336 }
1337 
1339 {
1340  bool bGoodResult = true;
1341  bool isGenerator = GetType() == EffectTypeGenerate;
1342 
1343  FloatBuffers inBuffer, outBuffer;
1344  ArrayOf<float *> inBufPos, outBufPos;
1345 
1346  ChannelName map[3];
1347 
1348  mBufferSize = 0;
1349  mBlockSize = 0;
1350 
1351  int count = 0;
1352  bool clear = false;
1353 
1354  const bool multichannel = mNumAudioIn > 1;
1355  auto range = multichannel
1356  ? mOutputTracks->Leaders()
1357  : mOutputTracks->Any();
1358  range.VisitWhile( bGoodResult,
1359  [&](WaveTrack *left, const Track::Fallthrough &fallthrough) {
1360  if (!left->GetSelected())
1361  return fallthrough();
1362 
1363  sampleCount len;
1364  sampleCount leftStart;
1365  sampleCount rightStart = 0;
1366 
1367  if (!isGenerator)
1368  {
1369  GetSamples(left, &leftStart, &len);
1370  mSampleCnt = len;
1371  }
1372  else
1373  {
1374  len = 0;
1375  leftStart = 0;
1377  }
1378 
1379  mNumChannels = 0;
1380  WaveTrack *right{};
1381 
1382  // Iterate either over one track which could be any channel,
1383  // or if multichannel, then over all channels of left,
1384  // which is a leader.
1385  for (auto channel :
1386  TrackList::Channels(left).StartingWith(left)) {
1387  if (channel->GetChannel() == Track::LeftChannel)
1389  else if (channel->GetChannel() == Track::RightChannel)
1391  else
1393 
1394  ++ mNumChannels;
1396 
1397  if (! multichannel)
1398  break;
1399 
1400  if (mNumChannels == 2) {
1401  // TODO: more-than-two-channels
1402  right = channel;
1403  clear = false;
1404  if (!isGenerator)
1405  GetSamples(right, &rightStart, &len);
1406 
1407  // Ignore other channels
1408  break;
1409  }
1410  }
1411 
1412  // Let the client know the sample rate
1413  SetSampleRate(left->GetRate());
1414 
1415  // Get the block size the client wants to use
1416  auto max = left->GetMaxBlockSize() * 2;
1417  mBlockSize = SetBlockSize(max);
1418 
1419  // Calculate the buffer size to be at least the max rounded up to the clients
1420  // selected block size.
1421  const auto prevBufferSize = mBufferSize;
1422  mBufferSize = ((max + (mBlockSize - 1)) / mBlockSize) * mBlockSize;
1423 
1424  // If the buffer size has changed, then (re)allocate the buffers
1425  if (prevBufferSize != mBufferSize)
1426  {
1427  // Always create the number of input buffers the client expects even if we don't have
1428  // the same number of channels.
1429  inBufPos.reinit( mNumAudioIn );
1430  inBuffer.reinit( mNumAudioIn, mBufferSize );
1431 
1432  // We won't be using more than the first 2 buffers, so clear the rest (if any)
1433  for (size_t i = 2; i < mNumAudioIn; i++)
1434  {
1435  for (size_t j = 0; j < mBufferSize; j++)
1436  {
1437  inBuffer[i][j] = 0.0;
1438  }
1439  }
1440 
1441  // Always create the number of output buffers the client expects even if we don't have
1442  // the same number of channels.
1443  outBufPos.reinit( mNumAudioOut );
1444  // Output buffers get an extra mBlockSize worth to give extra room if
1445  // the plugin adds latency
1446  outBuffer.reinit( mNumAudioOut, mBufferSize + mBlockSize );
1447  }
1448 
1449  // (Re)Set the input buffer positions
1450  for (size_t i = 0; i < mNumAudioIn; i++)
1451  {
1452  inBufPos[i] = inBuffer[i].get();
1453  }
1454 
1455  // (Re)Set the output buffer positions
1456  for (size_t i = 0; i < mNumAudioOut; i++)
1457  {
1458  outBufPos[i] = outBuffer[i].get();
1459  }
1460 
1461  // Clear unused input buffers
1462  if (!right && !clear && mNumAudioIn > 1)
1463  {
1464  for (size_t j = 0; j < mBufferSize; j++)
1465  {
1466  inBuffer[1][j] = 0.0;
1467  }
1468  clear = true;
1469  }
1470 
1471  // Go process the track(s)
1472  bGoodResult = ProcessTrack(
1473  count, map, left, right, leftStart, rightStart, len,
1474  inBuffer, outBuffer, inBufPos, outBufPos);
1475  if (!bGoodResult)
1476  return;
1477 
1478  count++;
1479  },
1480  [&](Track *t) {
1481  if (t->IsSyncLockSelected())
1482  t->SyncLockAdjust(mT1, mT0 + mDuration);
1483  }
1484  );
1485 
1486  if (bGoodResult && GetType() == EffectTypeGenerate)
1487  {
1488  mT1 = mT0 + mDuration;
1489  }
1490 
1491  return bGoodResult;
1492 }
1493 
1494 bool Effect::ProcessTrack(int count,
1495  ChannelNames map,
1496  WaveTrack *left,
1497  WaveTrack *right,
1498  sampleCount leftStart,
1499  sampleCount rightStart,
1500  sampleCount len,
1501  FloatBuffers &inBuffer,
1502  FloatBuffers &outBuffer,
1503  ArrayOf< float * > &inBufPos,
1504  ArrayOf< float *> &outBufPos)
1505 {
1506  bool rc = true;
1507 
1508  // Give the plugin a chance to initialize
1509  if (!ProcessInitialize(len, map))
1510  {
1511  return false;
1512  }
1513 
1514  { // Start scope for cleanup
1515  auto cleanup = finally( [&] {
1516  // Allow the plugin to cleanup
1517  if (!ProcessFinalize())
1518  {
1519  // In case of non-exceptional flow of control, set rc
1520  rc = false;
1521  }
1522  } );
1523 
1524  // For each input block of samples, we pass it to the effect along with a
1525  // variable output location. This output location is simply a pointer into a
1526  // much larger buffer. This reduces the number of calls required to add the
1527  // samples to the output track.
1528  //
1529  // Upon return from the effect, the output samples are "moved to the left" by
1530  // the number of samples in the current latency setting, effectively removing any
1531  // delay introduced by the effect.
1532  //
1533  // At the same time the total number of delayed samples are gathered and when
1534  // there is no further input data to process, the loop continues to call the
1535  // effect with an empty input buffer until the effect has had a chance to
1536  // return all of the remaining delayed samples.
1537  auto inLeftPos = leftStart;
1538  auto inRightPos = rightStart;
1539  auto outLeftPos = leftStart;
1540  auto outRightPos = rightStart;
1541 
1542  auto inputRemaining = len;
1543  decltype(GetLatency()) curDelay = 0, delayRemaining = 0;
1544  decltype(mBlockSize) curBlockSize = 0;
1545 
1546  decltype(mBufferSize) inputBufferCnt = 0;
1547  decltype(mBufferSize) outputBufferCnt = 0;
1548  bool cleared = false;
1549 
1550  auto chans = std::min<unsigned>(mNumAudioOut, mNumChannels);
1551 
1552  std::unique_ptr<WaveTrack> genLeft, genRight;
1553 
1554  decltype(len) genLength = 0;
1555  bool isGenerator = GetType() == EffectTypeGenerate;
1556  bool isProcessor = GetType() == EffectTypeProcess;
1557  double genDur = 0;
1558  if (isGenerator)
1559  {
1560  if (mIsPreview) {
1561  gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &genDur, 6.0);
1562  genDur = wxMin(mDuration, CalcPreviewInputLength(genDur));
1563  }
1564  else {
1565  genDur = mDuration;
1566  }
1567 
1568  genLength = sampleCount((left->GetRate() * genDur) + 0.5); // round to nearest sample
1569  delayRemaining = genLength;
1570  cleared = true;
1571 
1572  // Create temporary tracks
1573  genLeft = mFactory->NewWaveTrack(left->GetSampleFormat(), left->GetRate());
1574  genLeft->SetWaveColorIndex( left->GetWaveColorIndex() );
1575 
1576  if (right)
1577  {
1578  genRight = mFactory->NewWaveTrack(right->GetSampleFormat(), right->GetRate());
1579  genRight->SetWaveColorIndex( right->GetWaveColorIndex() );
1580  }
1581  }
1582 
1583  // Call the effect until we run out of input or delayed samples
1584  while (inputRemaining != 0 || delayRemaining != 0)
1585  {
1586  // Still working on the input samples
1587  if (inputRemaining != 0)
1588  {
1589  // Need to refill the input buffers
1590  if (inputBufferCnt == 0)
1591  {
1592  // Calculate the number of samples to get
1593  inputBufferCnt =
1594  limitSampleBufferSize( mBufferSize, inputRemaining );
1595 
1596  // Fill the input buffers
1597  left->Get((samplePtr) inBuffer[0].get(), floatSample, inLeftPos, inputBufferCnt);
1598  if (right)
1599  {
1600  right->Get((samplePtr) inBuffer[1].get(), floatSample, inRightPos, inputBufferCnt);
1601  }
1602 
1603  // Reset the input buffer positions
1604  for (size_t i = 0; i < mNumChannels; i++)
1605  {
1606  inBufPos[i] = inBuffer[i].get();
1607  }
1608  }
1609 
1610  // Calculate the number of samples to process
1611  curBlockSize = mBlockSize;
1612  if (curBlockSize > inputRemaining)
1613  {
1614  // We've reached the last block...set current block size to what's left
1615  // inputRemaining is positive and bounded by a size_t
1616  curBlockSize = inputRemaining.as_size_t();
1617  inputRemaining = 0;
1618 
1619  // Clear the remainder of the buffers so that a full block can be passed
1620  // to the effect
1621  auto cnt = mBlockSize - curBlockSize;
1622  for (size_t i = 0; i < mNumChannels; i++)
1623  {
1624  for (decltype(cnt) j = 0 ; j < cnt; j++)
1625  {
1626  inBufPos[i][j + curBlockSize] = 0.0;
1627  }
1628  }
1629 
1630  // Might be able to use up some of the delayed samples
1631  if (delayRemaining != 0)
1632  {
1633  // Don't use more than needed
1634  cnt = limitSampleBufferSize(cnt, delayRemaining);
1635  delayRemaining -= cnt;
1636  curBlockSize += cnt;
1637  }
1638  }
1639  }
1640  // We've exhausted the input samples and are now working on the delay
1641  else if (delayRemaining != 0)
1642  {
1643  // Calculate the number of samples to process
1644  curBlockSize = limitSampleBufferSize( mBlockSize, delayRemaining );
1645  delayRemaining -= curBlockSize;
1646 
1647  // From this point on, we only want to feed zeros to the plugin
1648  if (!cleared)
1649  {
1650  // Reset the input buffer positions
1651  for (size_t i = 0; i < mNumChannels; i++)
1652  {
1653  inBufPos[i] = inBuffer[i].get();
1654 
1655  // And clear
1656  for (size_t j = 0; j < mBlockSize; j++)
1657  {
1658  inBuffer[i][j] = 0.0;
1659  }
1660  }
1661  cleared = true;
1662  }
1663  }
1664 
1665  // Finally call the plugin to process the block
1666  decltype(curBlockSize) processed;
1667  try
1668  {
1669  processed = ProcessBlock(inBufPos.get(), outBufPos.get(), curBlockSize);
1670  }
1671  catch( const AudacityException & WXUNUSED(e) )
1672  {
1673  // PRL: Bug 437:
1674  // Pass this along to our application-level handler
1675  throw;
1676  }
1677  catch(...)
1678  {
1679  // PRL:
1680  // Exceptions for other reasons, maybe in third-party code...
1681  // Continue treating them as we used to, but I wonder if these
1682  // should now be treated the same way.
1683  return false;
1684  }
1685  wxASSERT(processed == curBlockSize);
1686  wxUnusedVar(processed);
1687 
1688  // Bump to next input buffer position
1689  if (inputRemaining != 0)
1690  {
1691  for (size_t i = 0; i < mNumChannels; i++)
1692  {
1693  inBufPos[i] += curBlockSize;
1694  }
1695  inputRemaining -= curBlockSize;
1696  inputBufferCnt -= curBlockSize;
1697  }
1698 
1699  // "ls" and "rs" serve as the input sample index for the left and
1700  // right channels when processing the input samples. If we flip
1701  // over to processing delayed samples, they simply become counters
1702  // for the progress display.
1703  inLeftPos += curBlockSize;
1704  inRightPos += curBlockSize;
1705 
1706  // Get the current number of delayed samples and accumulate
1707  if (isProcessor)
1708  {
1709  {
1710  auto delay = GetLatency();
1711  curDelay += delay;
1712  delayRemaining += delay;
1713  }
1714 
1715  // If the plugin has delayed the output by more samples than our current
1716  // block size, then we leave the output pointers alone. This effectively
1717  // removes those delayed samples from the output buffer.
1718  if (curDelay >= curBlockSize)
1719  {
1720  curDelay -= curBlockSize;
1721  curBlockSize = 0;
1722  }
1723  // We have some delayed samples, at the beginning of the output samples,
1724  // so overlay them by shifting the remaining output samples.
1725  else if (curDelay > 0)
1726  {
1727  // curDelay is bounded by curBlockSize:
1728  auto delay = curDelay.as_size_t();
1729  curBlockSize -= delay;
1730  for (size_t i = 0; i < chans; i++)
1731  {
1732  memmove(outBufPos[i], outBufPos[i] + delay, sizeof(float) * curBlockSize);
1733  }
1734  curDelay = 0;
1735  }
1736  }
1737 
1738  // Adjust the number of samples in the output buffers
1739  outputBufferCnt += curBlockSize;
1740 
1741  // Still have room in the output buffers
1742  if (outputBufferCnt < mBufferSize)
1743  {
1744  // Bump to next output buffer position
1745  for (size_t i = 0; i < chans; i++)
1746  {
1747  outBufPos[i] += curBlockSize;
1748  }
1749  }
1750  // Output buffers have filled
1751  else
1752  {
1753  if (isProcessor)
1754  {
1755  // Write them out
1756  left->Set((samplePtr) outBuffer[0].get(), floatSample, outLeftPos, outputBufferCnt);
1757  if (right)
1758  {
1759  if (chans >= 2)
1760  {
1761  right->Set((samplePtr) outBuffer[1].get(), floatSample, outRightPos, outputBufferCnt);
1762  }
1763  else
1764  {
1765  right->Set((samplePtr) outBuffer[0].get(), floatSample, outRightPos, outputBufferCnt);
1766  }
1767  }
1768  }
1769  else if (isGenerator)
1770  {
1771  genLeft->Append((samplePtr) outBuffer[0].get(), floatSample, outputBufferCnt);
1772  if (genRight)
1773  {
1774  genRight->Append((samplePtr) outBuffer[1].get(), floatSample, outputBufferCnt);
1775  }
1776  }
1777 
1778  // Reset the output buffer positions
1779  for (size_t i = 0; i < chans; i++)
1780  {
1781  outBufPos[i] = outBuffer[i].get();
1782  }
1783 
1784  // Bump to the next track position
1785  outLeftPos += outputBufferCnt;
1786  outRightPos += outputBufferCnt;
1787  outputBufferCnt = 0;
1788  }
1789 
1790  if (mNumChannels > 1)
1791  {
1792  if (TrackGroupProgress(count,
1793  (inLeftPos - leftStart).as_double() /
1794  (isGenerator ? genLength : len).as_double()))
1795  {
1796  rc = false;
1797  break;
1798  }
1799  }
1800  else
1801  {
1802  if (TrackProgress(count,
1803  (inLeftPos - leftStart).as_double() /
1804  (isGenerator ? genLength : len).as_double()))
1805  {
1806  rc = false;
1807  break;
1808  }
1809  }
1810  }
1811 
1812  // Put any remaining output
1813  if (rc && outputBufferCnt)
1814  {
1815  if (isProcessor)
1816  {
1817  left->Set((samplePtr) outBuffer[0].get(), floatSample, outLeftPos, outputBufferCnt);
1818  if (right)
1819  {
1820  if (chans >= 2)
1821  {
1822  right->Set((samplePtr) outBuffer[1].get(), floatSample, outRightPos, outputBufferCnt);
1823  }
1824  else
1825  {
1826  right->Set((samplePtr) outBuffer[0].get(), floatSample, outRightPos, outputBufferCnt);
1827  }
1828  }
1829  }
1830  else if (isGenerator)
1831  {
1832  genLeft->Append((samplePtr) outBuffer[0].get(), floatSample, outputBufferCnt);
1833  if (genRight)
1834  {
1835  genRight->Append((samplePtr) outBuffer[1].get(), floatSample, outputBufferCnt);
1836  }
1837  }
1838  }
1839 
1840  if (rc && isGenerator)
1841  {
1843 
1844  // PRL: this code was here and could not have been the right
1845  // intent, mixing time and sampleCount values:
1846  // StepTimeWarper warper(mT0 + genLength, genLength - (mT1 - mT0));
1847 
1848  // This looks like what it should have been:
1849  // StepTimeWarper warper(mT0 + genDur, genDur - (mT1 - mT0));
1850  // But rather than fix it, I will just disable the use of it for now.
1851  // The purpose was to remap split lines inside the selected region when
1852  // a generator replaces it with sound of different duration. But
1853  // the "correct" version might have the effect of mapping some splits too
1854  // far left, to before the selection.
1855  // In practice the wrong version probably did nothing most of the time,
1856  // because the cutoff time for the step time warper was 44100 times too
1857  // far from mT0.
1858 
1859  // Transfer the data from the temporary tracks to the actual ones
1860  genLeft->Flush();
1861  // mT1 gives us the NEW selection. We want to replace up to GetSel1().
1862  left->ClearAndPaste(mT0, p->GetSel1(), genLeft.get(), true, true,
1863  nullptr /* &warper */);
1864 
1865  if (genRight)
1866  {
1867  genRight->Flush();
1868  right->ClearAndPaste(mT0, mT1, genRight.get(), true, true,
1869  nullptr /* &warper */);
1870  }
1871  }
1872 
1873  } // End scope for cleanup
1874  return rc;
1875 }
1876 
1878 {
1879 }
1880 
1882 {
1883  return;
1884 }
1885 
1887 {
1888  return true;
1889 }
1890 
1892 {
1893  return true;
1894 }
1895 
1896 bool Effect::EnableApply(bool enable)
1897 {
1898  // May be called during initialization, so try to find the dialog
1899  wxWindow *dlg = mUIDialog;
1900  if (!dlg && mUIParent)
1901  {
1902  dlg = wxGetTopLevelParent(mUIParent);
1903  }
1904 
1905  if (dlg)
1906  {
1907  wxWindow *apply = dlg->FindWindow(wxID_APPLY);
1908 
1909  // Don't allow focus to get trapped
1910  if (!enable)
1911  {
1912  wxWindow *focus = dlg->FindFocus();
1913  if (focus == apply)
1914  {
1915  dlg->FindWindow(wxID_CLOSE)->SetFocus();
1916  }
1917  }
1918 
1919  apply->Enable(enable);
1920  }
1921 
1922  EnablePreview(enable);
1923 
1924  return enable;
1925 }
1926 
1927 bool Effect::EnablePreview(bool enable)
1928 {
1929  // May be called during initialization, so try to find the dialog
1930  wxWindow *dlg = mUIDialog;
1931  if (!dlg && mUIParent)
1932  {
1933  dlg = wxGetTopLevelParent(mUIParent);
1934  }
1935 
1936  if (dlg)
1937  {
1938  wxWindow *play = dlg->FindWindow(kPlayID);
1939  if (play)
1940  {
1941  wxWindow *rewind = dlg->FindWindow(kRewindID);
1942  wxWindow *ffwd = dlg->FindWindow(kFFwdID);
1943 
1944  // Don't allow focus to get trapped
1945  if (!enable)
1946  {
1947  wxWindow *focus = dlg->FindFocus();
1948  if (focus && (focus == play || focus == rewind || focus == ffwd))
1949  {
1950  dlg->FindWindow(wxID_CLOSE)->SetFocus();
1951  }
1952  }
1953 
1954  play->Enable(enable);
1955  if (SupportsRealtime())
1956  {
1957  rewind->Enable(enable);
1958  ffwd->Enable(enable);
1959  }
1960  }
1961  }
1962 
1963  return enable;
1964 }
1965 
1966 void Effect::EnableDebug(bool enable)
1967 {
1968  mUIDebug = enable;
1969 }
1970 
1971 void Effect::SetLinearEffectFlag(bool linearEffectFlag)
1972 {
1973  mIsLinearEffect = linearEffectFlag;
1974 }
1975 
1976 void Effect::SetPreviewFullSelectionFlag(bool previewDurationFlag)
1977 {
1978  mPreviewFullSelection = previewDurationFlag;
1979 }
1980 
1981 
1982 void Effect::IncludeNotSelectedPreviewTracks(bool includeNotSelected)
1983 {
1984  mPreviewWithNotSelected = includeNotSelected;
1985 }
1986 
1987 bool Effect::TotalProgress(double frac, const wxString &msg)
1988 {
1989  auto updateResult = (mProgress ?
1990  mProgress->Update(frac, msg) :
1992  return (updateResult != ProgressResult::Success);
1993 }
1994 
1995 bool Effect::TrackProgress(int whichTrack, double frac, const wxString &msg)
1996 {
1997  auto updateResult = (mProgress ?
1998  mProgress->Update(whichTrack + frac, (double) mNumTracks, msg) :
2000  return (updateResult != ProgressResult::Success);
2001 }
2002 
2003 bool Effect::TrackGroupProgress(int whichGroup, double frac, const wxString &msg)
2004 {
2005  auto updateResult = (mProgress ?
2006  mProgress->Update(whichGroup + frac, (double) mNumGroups, msg) :
2008  return (updateResult != ProgressResult::Success);
2009 }
2010 
2012  const WaveTrack *track, sampleCount *start, sampleCount *len)
2013 {
2014  double trackStart = track->GetStartTime();
2015  double trackEnd = track->GetEndTime();
2016  double t0 = mT0 < trackStart ? trackStart : mT0;
2017  double t1 = mT1 > trackEnd ? trackEnd : mT1;
2018 
2019 #if 0
2020  if (GetType() & INSERT_EFFECT) {
2021  t1 = t0 + mDuration;
2022  if (mT0 == mT1) {
2023  // Not really part of the calculation, but convenient to put here
2024  track->InsertSilence(t0, t1);
2025  }
2026  }
2027 #endif
2028 
2029  if (t1 > t0) {
2030  *start = track->TimeToLongSamples(t0);
2031  auto end = track->TimeToLongSamples(t1);
2032  *len = end - *start;
2033  }
2034  else {
2035  *start = 0;
2036  *len = 0;
2037  }
2038 }
2039 
2040 //
2041 // private methods
2042 //
2043 // Use this method to copy the input tracks to mOutputTracks, if
2044 // doing the processing on them, and replacing the originals only on success (and not cancel).
2045 // Copy the group tracks that have tracks selected
2046 // If not all sync-locked selected, then only selected wave tracks.
2047 void Effect::CopyInputTracks(bool allSyncLockSelected)
2048 {
2049  // Reset map
2050  mIMap.clear();
2051  mOMap.clear();
2052 
2054 
2055  auto trackRange = mTracks->Any() +
2056  [&] (const Track *pTrack) {
2057  return allSyncLockSelected
2058  ? pTrack->IsSelectedOrSyncLockSelected()
2059  : track_cast<const WaveTrack*>( pTrack ) && pTrack->GetSelected();
2060  };
2061 
2062  t2bHash added;
2063 
2064  for (auto aTrack : trackRange)
2065  {
2066  Track *o = mOutputTracks->Add(aTrack->Duplicate());
2067  mIMap.push_back(aTrack);
2068  mOMap.push_back(o);
2069  }
2070 }
2071 
2072 Track *Effect::AddToOutputTracks(std::unique_ptr<Track> &&t)
2073 {
2074  mIMap.push_back(NULL);
2075  mOMap.push_back(t.get());
2076  return mOutputTracks->Add(std::move(t));
2077 }
2078 
2080  : mpEffect(pEffect)
2081 {
2082  LabelTrack::Holder pTrack{ pEffect->mFactory->NewLabelTrack() };
2083  mpTrack = pTrack.get();
2084  if (!name.empty())
2085  pTrack->SetName(name);
2086  pEffect->mTracks->Add(std::move(pTrack));
2087 }
2088 
2090 {
2091  mpEffect = that.mpEffect;
2092  mpTrack = that.mpTrack;
2093  that.Commit();
2094 }
2095 
2097 {
2098  mpEffect = nullptr;
2099 }
2100 
2102 {
2103  if (mpEffect) {
2104  // not committed -- DELETE the label track
2105  mpEffect->mTracks->Remove(mpTrack);
2106  }
2107 }
2108 
2109 auto Effect::AddAnalysisTrack(const wxString &name) -> std::shared_ptr<AddedAnalysisTrack>
2110 {
2111  return std::shared_ptr<AddedAnalysisTrack>
2112  { safenew AddedAnalysisTrack{ this, name } };
2113 }
2114 
2116  (Effect *pEffect, const LabelTrack *pOrigTrack, const wxString &name)
2117  : mpEffect(pEffect)
2118 {
2119  // copy LabelTrack here, so it can be undone on cancel
2120  auto newTrack = pOrigTrack->Copy(pOrigTrack->GetStartTime(), pOrigTrack->GetEndTime());
2121 
2122  mpTrack = static_cast<LabelTrack*>(newTrack.get());
2123 
2124  // Why doesn't LabelTrack::Copy complete the job? :
2125  mpTrack->SetOffset(pOrigTrack->GetStartTime());
2126  if (!name.empty())
2127  mpTrack->SetName(name);
2128 
2129  // mpOrigTrack came from mTracks which we own but expose as const to subclasses
2130  // So it's okay that we cast it back to const
2131  mpOrigTrack =
2132  pEffect->mTracks->Replace(const_cast<LabelTrack*>(pOrigTrack),
2133  std::move(newTrack) );
2134 }
2135 
2137 {
2138  mpEffect = that.mpEffect;
2139  mpTrack = that.mpTrack;
2140  mpOrigTrack = std::move(that.mpOrigTrack);
2141  that.Commit();
2142 }
2143 
2145 {
2146  mpEffect = nullptr;
2147 }
2148 
2150 {
2151  if (mpEffect) {
2152  // not committed -- DELETE the label track
2153  // mpOrigTrack came from mTracks which we own but expose as const to subclasses
2154  // So it's okay that we cast it back to const
2155  mpEffect->mTracks->Replace(mpTrack, std::move(mpOrigTrack));
2156  }
2157 }
2158 
2160  (const LabelTrack *pOrigTrack, const wxString &name) -> ModifiedAnalysisTrack
2161 {
2162  return{ this, pOrigTrack, name };
2163 }
2164 
2165 // If bGoodResult, replace mTracks tracks with successfully processed mOutputTracks copies.
2166 // Else clear and DELETE mOutputTracks copies.
2167 void Effect::ReplaceProcessedTracks(const bool bGoodResult)
2168 {
2169  if (!bGoodResult) {
2170  // Free resources, unless already freed.
2171 
2172  // Processing failed or was cancelled so throw away the processed tracks.
2173  if ( mOutputTracks )
2174  mOutputTracks->Clear();
2175 
2176  // Reset map
2177  mIMap.clear();
2178  mOMap.clear();
2179 
2180  //TODO:undo the non-gui ODTask transfer
2181  return;
2182  }
2183 
2184  // Assume resources need to be freed.
2185  wxASSERT(mOutputTracks); // Make sure we at least did the CopyInputTracks().
2186 
2187  auto iterOut = mOutputTracks->ListOfTracks::begin(),
2188  iterEnd = mOutputTracks->ListOfTracks::end();
2189 
2190  size_t cnt = mOMap.size();
2191  size_t i = 0;
2192 
2193  for (; iterOut != iterEnd; ++i) {
2194  ListOfTracks::value_type o = std::move(*iterOut);
2195  // If tracks were removed from mOutputTracks, then there will be
2196  // tracks in the map that must be removed from mTracks.
2197  while (i < cnt && mOMap[i] != o.get()) {
2198  const auto t = mIMap[i];
2199  if (t) {
2200  mTracks->Remove(t);
2201  }
2202  i++;
2203  }
2204 
2205  // This should never happen
2206  wxASSERT(i < cnt);
2207 
2208  // Remove the track from the output list...don't DELETE it
2209  iterOut = mOutputTracks->erase(iterOut);
2210 
2211  const auto t = mIMap[i];
2212  if (t == NULL)
2213  {
2214  // This track is a NEW addition to output tracks; add it to mTracks
2215  mTracks->Add(std::move(o));
2216  }
2217  else
2218  {
2219  // Replace mTracks entry with the NEW track
2220  auto newTrack = o.get();
2221  mTracks->Replace(t, std::move(o));
2222 
2223  // If the track is a wave track,
2224  // Swap the wavecache track the ondemand task uses, since now the NEW
2225  // one will be kept in the project
2227  ODManager::Instance()->ReplaceWaveTrack( t, newTrack );
2228  }
2229  }
2230  }
2231 
2232  // If tracks were removed from mOutputTracks, then there may be tracks
2233  // left at the end of the map that must be removed from mTracks.
2234  while (i < cnt) {
2235  const auto t = mIMap[i];
2236  if (t) {
2237  mTracks->Remove(t);
2238  }
2239  i++;
2240  }
2241 
2242  // Reset map
2243  mIMap.clear();
2244  mOMap.clear();
2245 
2246  // Make sure we processed everything
2247  wxASSERT(mOutputTracks->empty());
2248 
2249  // The output list is no longer needed
2250  mOutputTracks.reset();
2251  nEffectsDone++;
2252 }
2253 
2255 {
2256  mNumTracks = mTracks->Selected< const WaveTrack >().size();
2257  mNumGroups = mTracks->SelectedLeaders< const WaveTrack >().size();
2258 }
2259 
2260 double Effect::CalcPreviewInputLength(double previewLength)
2261 {
2262  return previewLength;
2263 }
2264 
2265 // RealtimeAddProcessor and RealtimeProcess use the same method of
2266 // determining the current processor index, so updates to one should
2267 // be reflected in the other.
2268 bool Effect::RealtimeAddProcessor(int group, unsigned chans, float rate)
2269 {
2270  auto ichans = chans;
2271  auto ochans = chans;
2272  auto gchans = chans;
2273 
2274  // Reset processor index
2275  if (group == 0)
2276  {
2277  mCurrentProcessor = 0;
2278  mGroupProcessor.clear();
2279  }
2280 
2281  // Remember the processor starting index
2283 
2284  // Call the client until we run out of input or output channels
2285  while (ichans > 0 && ochans > 0)
2286  {
2287  // If we don't have enough input channels to accomodate the client's
2288  // requirements, then we replicate the input channels until the
2289  // client's needs are met.
2290  if (ichans < mNumAudioIn)
2291  {
2292  // All input channels have been consumed
2293  ichans = 0;
2294  }
2295  // Otherwise fullfil the client's needs with as many input channels as possible.
2296  // After calling the client with this set, we will loop back up to process more
2297  // of the input/output channels.
2298  else if (ichans >= mNumAudioIn)
2299  {
2300  gchans = mNumAudioIn;
2301  ichans -= gchans;
2302  }
2303 
2304  // If we don't have enough output channels to accomodate the client's
2305  // requirements, then we provide all of the output channels and fulfill
2306  // the client's needs with dummy buffers. These will just get tossed.
2307  if (ochans < mNumAudioOut)
2308  {
2309  // All output channels have been consumed
2310  ochans = 0;
2311  }
2312  // Otherwise fullfil the client's needs with as many output channels as possible.
2313  // After calling the client with this set, we will loop back up to process more
2314  // of the input/output channels.
2315  else if (ochans >= mNumAudioOut)
2316  {
2317  ochans -= mNumAudioOut;
2318  }
2319 
2320  // Add a NEW processor
2321  RealtimeAddProcessor(gchans, rate);
2322 
2323  // Bump to next processor
2325  }
2326 
2327  return true;
2328 }
2329 
2330 // RealtimeAddProcessor and RealtimeProcess use the same method of
2331 // determining the current processor group, so updates to one should
2332 // be reflected in the other.
2333 size_t Effect::RealtimeProcess(int group,
2334  unsigned chans,
2335  float **inbuf,
2336  float **outbuf,
2337  size_t numSamples)
2338 {
2339  //
2340  // The caller passes the number of channels to process and specifies
2341  // the number of input and output buffers. There will always be the
2342  // same number of output buffers as there are input buffers.
2343  //
2344  // Effects always require a certain number of input and output buffers,
2345  // so if the number of channels we're curently processing are different
2346  // than what the effect expects, then we use a few methods of satisfying
2347  // the effects requirements.
2348  float **clientIn = (float **) alloca(mNumAudioIn * sizeof(float *));
2349  float **clientOut = (float **) alloca(mNumAudioOut * sizeof(float *));
2350  float *dummybuf = (float *) alloca(numSamples * sizeof(float));
2351  decltype(numSamples) len = 0;
2352  auto ichans = chans;
2353  auto ochans = chans;
2354  auto gchans = chans;
2355  unsigned indx = 0;
2356  unsigned ondx = 0;
2357 
2358  int processor = mGroupProcessor[group];
2359 
2360  // Call the client until we run out of input or output channels
2361  while (ichans > 0 && ochans > 0)
2362  {
2363  // If we don't have enough input channels to accomodate the client's
2364  // requirements, then we replicate the input channels until the
2365  // client's needs are met.
2366  if (ichans < mNumAudioIn)
2367  {
2368  for (size_t i = 0; i < mNumAudioIn; i++)
2369  {
2370  if (indx == ichans)
2371  {
2372  indx = 0;
2373  }
2374  clientIn[i] = inbuf[indx++];
2375  }
2376 
2377  // All input channels have been consumed
2378  ichans = 0;
2379  }
2380  // Otherwise fullfil the client's needs with as many input channels as possible.
2381  // After calling the client with this set, we will loop back up to process more
2382  // of the input/output channels.
2383  else if (ichans >= mNumAudioIn)
2384  {
2385  gchans = 0;
2386  for (size_t i = 0; i < mNumAudioIn; i++, ichans--, gchans++)
2387  {
2388  clientIn[i] = inbuf[indx++];
2389  }
2390  }
2391 
2392  // If we don't have enough output channels to accomodate the client's
2393  // requirements, then we provide all of the output channels and fulfill
2394  // the client's needs with dummy buffers. These will just get tossed.
2395  if (ochans < mNumAudioOut)
2396  {
2397  for (size_t i = 0; i < mNumAudioOut; i++)
2398  {
2399  if (i < ochans)
2400  {
2401  clientOut[i] = outbuf[i];
2402  }
2403  else
2404  {
2405  clientOut[i] = dummybuf;
2406  }
2407  }
2408 
2409  // All output channels have been consumed
2410  ochans = 0;
2411  }
2412  // Otherwise fullfil the client's needs with as many output channels as possible.
2413  // After calling the client with this set, we will loop back up to process more
2414  // of the input/output channels.
2415  else if (ochans >= mNumAudioOut)
2416  {
2417  for (size_t i = 0; i < mNumAudioOut; i++, ochans--)
2418  {
2419  clientOut[i] = outbuf[ondx++];
2420  }
2421  }
2422 
2423  // Finally call the plugin to process the block
2424  len = 0;
2425  for (decltype(numSamples) block = 0; block < numSamples; block += mBlockSize)
2426  {
2427  auto cnt = std::min(numSamples - block, mBlockSize);
2428  len += RealtimeProcess(processor, clientIn, clientOut, cnt);
2429 
2430  for (size_t i = 0 ; i < mNumAudioIn; i++)
2431  {
2432  clientIn[i] += cnt;
2433  }
2434 
2435  for (size_t i = 0 ; i < mNumAudioOut; i++)
2436  {
2437  clientOut[i] += cnt;
2438  }
2439  }
2440 
2441  // Bump to next processor
2442  processor++;
2443  }
2444 
2445  return len;
2446 }
2447 
2449 {
2450  return mRealtimeSuspendCount == 0;
2451 }
2452 
2454 {
2455  return false;
2456 }
2457 
2458 void Effect::Preview(bool dryOnly)
2459 {
2460  if (mNumTracks == 0) { // nothing to preview
2461  return;
2462  }
2463 
2464  if (gAudioIO->IsBusy()) {
2465  return;
2466  }
2467 
2468  wxWindow *FocusDialog = wxWindow::FindFocus();
2469 
2470  double previewDuration;
2471  bool isNyquist = GetFamilyId() == NYQUISTEFFECTS_FAMILY;
2472  bool isGenerator = GetType() == EffectTypeGenerate;
2473 
2474  // Mix a few seconds of audio from all of the tracks
2475  double previewLen;
2476  gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &previewLen, 6.0);
2477 
2478  const double rate = mProjectRate;
2479 
2480  if (isNyquist && isGenerator) {
2481  previewDuration = CalcPreviewInputLength(previewLen);
2482  }
2483  else {
2484  previewDuration = wxMin(mDuration, CalcPreviewInputLength(previewLen));
2485  }
2486 
2487  double t1 = mT0 + previewDuration;
2488 
2489  if ((t1 > mT1) && !(isNyquist && isGenerator)) {
2490  t1 = mT1;
2491  }
2492 
2493  if (t1 <= mT0)
2494  return;
2495 
2496  bool success = true;
2497 
2498  auto cleanup = finally( [&] {
2499 
2500  // Effect is already inited; we will call Process, End, and then Init
2501  // again, so the state is exactly the way it was before Preview
2502  // was called.
2503  if (!dryOnly) {
2504  End();
2505  GuardedCall( [&]{ Init(); } );
2506  }
2507  } );
2508 
2509  auto vr0 = valueRestorer( mT0 );
2510  auto vr1 = valueRestorer( mT1 );
2511  // Most effects should stop at t1.
2512  if (!mPreviewFullSelection)
2513  mT1 = t1;
2514 
2515  // Save the original track list
2516  TrackList *saveTracks = mTracks;
2517 
2518  auto cleanup2 = finally( [&] {
2519  mTracks = saveTracks;
2520  if (FocusDialog) {
2521  FocusDialog->SetFocus();
2522  }
2523 
2524  // In case of failed effect, be sure to free memory.
2525  ReplaceProcessedTracks( false );
2526  } );
2527 
2528  // Build NEW tracklist from rendering tracks
2529  auto uTracks = TrackList::Create();
2530  mTracks = uTracks.get();
2531 
2532  // Linear Effect preview optimised by pre-mixing to one track.
2533  // Generators need to generate per track.
2534  if (mIsLinearEffect && !isGenerator) {
2535  WaveTrack::Holder mixLeft, mixRight;
2536  MixAndRender(saveTracks, mFactory, rate, floatSample, mT0, t1, mixLeft, mixRight);
2537  if (!mixLeft)
2538  return;
2539 
2540  mixLeft->Offset(-mixLeft->GetStartTime());
2541  mixLeft->SetSelected(true);
2542  mixLeft->SetDisplay(WaveTrack::NoDisplay);
2543  auto pLeft = mTracks->Add(std::move(mixLeft));
2544  Track *pRight{};
2545  if (mixRight) {
2546  mixRight->Offset(-mixRight->GetStartTime());
2547  mixRight->SetSelected(true);
2548  pRight = mTracks->Add(std::move(mixRight));
2549  }
2550  mTracks->GroupChannels(*pLeft, pRight ? 2 : 1);
2551  }
2552  else {
2553  for (auto src : saveTracks->Any< const WaveTrack >()) {
2554  if (src->GetSelected() || mPreviewWithNotSelected) {
2555  auto dest = src->Copy(mT0, t1);
2556  dest->SetSelected(src->GetSelected());
2557  static_cast<WaveTrack*>(dest.get())->SetDisplay(WaveTrack::NoDisplay);
2558  mTracks->Add(std::move(dest));
2559  }
2560  }
2561  }
2562 
2563  // NEW tracks start at time zero.
2564  // Adjust mT0 and mT1 to be the times to process, and to
2565  // play back in these tracks
2566  mT1 -= mT0;
2567  mT0 = 0.0;
2568 
2569  // Update track/group counts
2570  CountWaveTracks();
2571 
2572  // Apply effect
2573  if (!dryOnly) {
2574  ProgressDialog progress{
2576  _("Preparing preview"),
2578  }; // Have only "Stop" button.
2579  auto vr = valueRestorer( mProgress, &progress );
2580 
2581  auto vr2 = valueRestorer( mIsPreview, true );
2582 
2583  success = Process();
2584  }
2585 
2586  if (success)
2587  {
2588  auto tracks = GetAllPlaybackTracks(*mTracks, true);
2589 
2590  // Some effects (Paulstretch) may need to generate more
2591  // than previewLen, so take the min.
2592  t1 = std::min(mT0 + previewLen, mT1);
2593 
2594  // Start audio playing
2595  AudioIOStartStreamOptions options { rate };
2596  int token =
2597  gAudioIO->StartStream(tracks, mT0, t1, options);
2598 
2599  if (token) {
2600  auto previewing = ProgressResult::Success;
2601  // The progress dialog must be deleted before stopping the stream
2602  // to allow events to flow to the app during StopStream processing.
2603  // The progress dialog blocks these events.
2604  {
2605  ProgressDialog progress
2606  (GetTranslatedName(), _("Previewing"), pdlgHideCancelButton);
2607 
2608  while (gAudioIO->IsStreamActive(token) && previewing == ProgressResult::Success) {
2609  ::wxMilliSleep(100);
2610  previewing = progress.Update(gAudioIO->GetStreamTime() - mT0, t1 - mT0);
2611  }
2612  }
2613 
2614  gAudioIO->StopStream();
2615 
2616  while (gAudioIO->IsBusy()) {
2617  ::wxMilliSleep(100);
2618  }
2619  }
2620  else {
2621  ShowErrorDialog(FocusDialog, _("Error"),
2622  _("Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."),
2623  wxT("Error_opening_sound_device"));
2624  }
2625  }
2626 }
2627 
2629 (const wxString& message, long style, const wxString &titleStr)
2630 {
2631  wxString title;
2632  if (titleStr.empty())
2633  title = GetTranslatedName();
2634  else
2635  title = wxString::Format(_("%s: %s"), GetTranslatedName(), titleStr);
2636  return AudacityMessageBox(message, title, style, mUIParent);
2637 }
2638 
2639 BEGIN_EVENT_TABLE(EffectDialog, wxDialogWrapper)
2640  EVT_BUTTON(wxID_OK, EffectDialog::OnOk)
2642 
2643 EffectDialog::EffectDialog(wxWindow * parent,
2644  const wxString & title,
2645  int type,
2646  int flags,
2647  int additionalButtons)
2648 : wxDialogWrapper(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, flags)
2649 {
2650  mType = type;
2651  mAdditionalButtons = additionalButtons;
2652 }
2653 
2655 {
2656  ShuttleGui S(this, eIsCreating);
2657 
2658  S.SetBorder(5);
2659  S.StartVerticalLay(true);
2660  {
2661  PopulateOrExchange(S);
2662 
2663  long buttons = eOkButton;
2664  if ((mType != EffectTypeAnalyze) && (mType != EffectTypeTool))
2665  {
2666  buttons |= eCancelButton;
2667  if (mType == EffectTypeProcess)
2668  {
2669  buttons |= ePreviewButton;
2670  }
2671  }
2672  S.AddStandardButtons(buttons|mAdditionalButtons);
2673  }
2674  S.EndVerticalLay();
2675 
2676  Layout();
2677  Fit();
2678  SetMinSize(GetSize());
2679  Center();
2680 }
2681 
2686 {
2687  return;
2688 }
2689 
2691 {
2692  ShuttleGui S(this, eIsSettingToDialog);
2693  PopulateOrExchange(S);
2694 
2695  return true;
2696 }
2697 
2699 {
2701  PopulateOrExchange(S);
2702 
2703  return true;
2704 }
2705 
2707 {
2708  return true;
2709 }
2710 
2711 void EffectDialog::OnPreview(wxCommandEvent & WXUNUSED(evt))
2712 {
2713  return;
2714 }
2715 
2716 void EffectDialog::OnOk(wxCommandEvent & WXUNUSED(evt))
2717 {
2718  // On wxGTK (wx2.8.12), the default action is still executed even if
2719  // the button is disabled. This appears to affect all wxDialogs, not
2720  // just our Effects dialogs. So, this is a only temporary workaround
2721  // for legacy effects that disable the OK button. Hopefully this has
2722  // been corrected in wx3.
2723  if (FindWindow(wxID_OK)->IsEnabled() && Validate() && TransferDataFromWindow())
2724  {
2725  EndModal(true);
2726  }
2727 
2728  return;
2729 }
2730 
2732 //
2733 // EffectPanel
2734 //
2736 
2737 class EffectPanel final : public wxPanelWrapper
2738 {
2739 public:
2740  EffectPanel(wxWindow *parent)
2741  : wxPanelWrapper(parent)
2742  {
2743  // This fools NVDA into not saying "Panel" when the dialog gets focus
2744  SetName(wxT("\a"));
2745  SetLabel(wxT("\a"));
2746 
2747  mAcceptsFocus = true;
2748  }
2749 
2750  virtual ~EffectPanel()
2751  {
2752  }
2753 
2754  // ============================================================================
2755  // wxWindow implementation
2756  // ============================================================================
2757 
2758  bool AcceptsFocus() const override
2759  {
2760  return mAcceptsFocus;
2761  }
2762 
2763  // So that wxPanel is not included in Tab traversal, when required - see wxWidgets bug 15581
2764  bool AcceptsFocusFromKeyboard() const override
2765  {
2766  return mAcceptsFocus;
2767  }
2768 
2769  // ============================================================================
2770  // EffectPanel implementation
2771  // ============================================================================
2772  void SetAccept(bool accept)
2773  {
2774  mAcceptsFocus = accept;
2775  }
2776 
2777 private:
2779 };
2780 
2782 //
2783 // EffectUIHost
2784 //
2786 
2787 #include "../../images/Effect.h"
2788 
2789 BEGIN_EVENT_TABLE(EffectUIHost, wxDialogWrapper)
2790  EVT_INIT_DIALOG(EffectUIHost::OnInitDialog)
2791  EVT_ERASE_BACKGROUND(EffectUIHost::OnErase)
2792  EVT_PAINT(EffectUIHost::OnPaint)
2793  EVT_CLOSE(EffectUIHost::OnClose)
2794  EVT_BUTTON(wxID_APPLY, EffectUIHost::OnApply)
2795  EVT_BUTTON(wxID_CANCEL, EffectUIHost::OnCancel)
2796  EVT_BUTTON(wxID_HELP, EffectUIHost::OnHelp)
2797  EVT_BUTTON(eDebugID, EffectUIHost::OnDebug)
2798  EVT_BUTTON(kMenuID, EffectUIHost::OnMenu)
2799  EVT_CHECKBOX(kEnableID, EffectUIHost::OnEnable)
2800  EVT_BUTTON(kPlayID, EffectUIHost::OnPlay)
2801  EVT_BUTTON(kRewindID, EffectUIHost::OnRewind)
2802  EVT_BUTTON(kFFwdID, EffectUIHost::OnFFwd)
2803  EVT_MENU(kSaveAsID, EffectUIHost::OnSaveAs)
2804  EVT_MENU(kImportID, EffectUIHost::OnImport)
2805  EVT_MENU(kExportID, EffectUIHost::OnExport)
2806  EVT_MENU(kOptionsID, EffectUIHost::OnOptions)
2807  EVT_MENU(kDefaultsID, EffectUIHost::OnDefaults)
2808  EVT_MENU_RANGE(kUserPresetsID, kUserPresetsID + 999, EffectUIHost::OnUserPreset)
2809  EVT_MENU_RANGE(kDeletePresetID, kDeletePresetID + 999, EffectUIHost::OnDeletePreset)
2810  EVT_MENU_RANGE(kFactoryPresetsID, kFactoryPresetsID + 999, EffectUIHost::OnFactoryPreset)
2812 
2813 EffectUIHost::EffectUIHost(wxWindow *parent,
2814  Effect *effect,
2815  EffectUIClientInterface *client)
2816 : wxDialogWrapper(parent, wxID_ANY, effect->GetTranslatedName(),
2817  wxDefaultPosition, wxDefaultSize,
2818  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX)
2819 {
2820 #if defined(__WXMAC__)
2821  // Make sure the effect window actually floats above the main window
2822  [ [((NSView *)GetHandle()) window] setLevel:NSFloatingWindowLevel];
2823 #endif
2824 
2825  SetName( effect->GetTranslatedName() );
2826  SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
2827 
2828  mParent = parent;
2829  mEffect = effect;
2830  mCommand = NULL;
2831  mClient = client;
2832 
2833  mProject = GetActiveProject();
2834 
2835  mInitialized = false;
2836  mSupportsRealtime = false;
2837 
2838  mDisableTransport = false;
2839 
2840  mEnabled = true;
2841 
2842  mPlayPos = 0.0;
2843  mClient->SetHostUI(this);
2844 }
2845 
2847  AudacityCommand *command,
2848  EffectUIClientInterface *client)
2849 : wxDialogWrapper(parent, wxID_ANY, _("Some Command") /*command->GetTranslatedName()*/,
2850  wxDefaultPosition, wxDefaultSize,
2851  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX)
2852 {
2853 #if defined(__WXMAC__)
2854  // Make sure the effect window actually floats above the main window
2855  [ [((NSView *)GetHandle()) window] setLevel:NSFloatingWindowLevel];
2856 #endif
2857 
2858  //SetName( command->GetTranslatedName() );
2859  SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
2860 
2861  mParent = parent;
2862  mEffect = NULL;
2863  mCommand = command;
2864  mClient = client;
2865 
2867 
2868  mInitialized = false;
2869  mSupportsRealtime = false;
2870 
2871  mDisableTransport = false;
2872 
2873  mEnabled = true;
2874 
2875  mPlayPos = 0.0;
2876  mClient->SetHostUI(this);
2877 }
2878 
2879 
2880 
2881 
2883 {
2884  CleanupRealtime();
2885 
2886  if (mClient)
2887  {
2888  if (mNeedsResume)
2889  Resume();
2890 
2891  mClient->CloseUI();
2892  mClient = NULL;
2893  }
2894 }
2895 
2896 // ============================================================================
2897 // wxWindow implementation
2898 // ============================================================================
2899 
2901 {
2902  if( mEffect )
2903  return mEffect->TransferDataToWindow();
2904  if( mCommand )
2905  return mCommand->TransferDataToWindow();
2906  return false;
2907 }
2908 
2910 {
2911  if( mEffect)
2912  return mEffect->TransferDataFromWindow();
2913  if( mCommand)
2914  return mCommand->TransferDataFromWindow();
2915  return false;
2916 }
2917 
2918 // ============================================================================
2919 // wxDialog implementation
2920 // ============================================================================
2921 
2923 {
2924 #if defined(__WXMSW__)
2925  // Swap the Close and Apply buttons
2926  wxSizer *sz = mApplyBtn->GetContainingSizer();
2927  wxASSERT(mApplyBtn->GetParent()); // To justify safenew
2928  wxButton *apply = safenew wxButton(mApplyBtn->GetParent(), wxID_APPLY);
2929  sz->Replace(mCloseBtn, apply);
2930  sz->Replace(mApplyBtn, mCloseBtn);
2931  sz->Layout();
2932  mApplyBtn->Destroy();
2933  mApplyBtn = apply;
2934  mApplyBtn->SetDefault();
2935  mApplyBtn->SetLabel(wxGetStockLabel(wxID_OK, 0));
2936  mCloseBtn->SetLabel(wxGetStockLabel(wxID_CANCEL, 0));
2937 #else
2938  mApplyBtn->SetLabel(wxGetStockLabel(wxID_OK));
2939  mCloseBtn->SetLabel(wxGetStockLabel(wxID_CANCEL));
2940 #endif
2941 
2942  Layout();
2943 
2944  return wxDialogWrapper::ShowModal();
2945 }
2946 
2947 // ============================================================================
2948 // EffectUIHost implementation
2949 // ============================================================================
2950 
2952 {
2953  EffectPanel *w = safenew EffectPanel(this);
2954  RTL_WORKAROUND(w);
2955  {
2956  auto vs = std::make_unique<wxBoxSizer>(wxVERTICAL);
2957  {
2958  auto hs = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
2959 
2960  // Try to give the window a sensible default/minimum size
2961  w->SetMinSize(wxSize(wxMax(600, mParent->GetSize().GetWidth() * 2 / 3),
2962  mParent->GetSize().GetHeight() / 2));
2963 
2965  mPlaying = gAudioIO->IsStreamActive(); // not exactly right, but will suffice
2967 
2968  if (!mClient->PopulateUI(w))
2969  {
2970  return false;
2971  }
2972 
2973  hs->Add(w, 1, wxEXPAND);
2974  vs->Add(hs.release(), 1, wxEXPAND);
2975  }
2976 
2977  wxPanel *buttonPanel = safenew wxPanelWrapper(this, wxID_ANY);
2978  wxPanel *const bar = safenew wxPanelWrapper(buttonPanel, wxID_ANY);
2979 
2980  // This fools NVDA into not saying "Panel" when the dialog gets focus
2981  bar->SetName(wxT("\a"));
2982  bar->SetLabel(wxT("\a"));
2983 
2984  {
2985  auto bs = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
2986 
2991 
2992  wxBitmapButton *bb;
2993 
2994  int margin = 0;
2995 
2996 #if defined(__WXMAC__)
2997  margin = 3; // I'm sure it's needed because of the order things are created...
2998 #endif
2999 
3000  if (!mIsGUI)
3001  {
3002  wxASSERT(bar); // To justify safenew
3003  mMenuBtn = safenew wxButton(bar, kMenuID, _("&Manage"));
3004  bs->Add(mMenuBtn, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, margin);
3005  }
3006  else
3007  {
3008  wxASSERT(bar); // To justify safenew
3009  mMenuBtn = safenew wxBitmapButton(bar, kMenuID, CreateBitmap(effect_menu_xpm, true, true));
3010  mMenuBtn->SetBitmapPressed(CreateBitmap(effect_menu_xpm, false, true));
3011 #if defined(__WXMAC__)
3012  mMenuBtn->SetName(_("&Manage"));
3013 #else
3014  mMenuBtn->SetLabel(_("&Manage"));
3015 #endif
3016  bs->Add(mMenuBtn);
3017  }
3018  mMenuBtn->SetToolTip(_("Manage presets and options"));
3019 
3020  bs->Add(5, 5);
3021 
3022  if (!mIsBatch)
3023  {
3024  if (!mIsGUI)
3025  {
3026  if (mSupportsRealtime)
3027  {
3028  wxASSERT(bar); // To justify safenew
3029  mPlayToggleBtn = safenew wxButton(bar, kPlayID, _("Start &Playback"));
3030  mPlayToggleBtn->SetToolTip(_("Start and stop playback"));
3031  bs->Add(mPlayToggleBtn, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, margin);
3032  }
3033  else if (mEffect &&
3034  (mEffect->GetType() != EffectTypeAnalyze) &&
3036  )
3037  {
3038  wxASSERT(bar); // To justify safenew
3039  mPlayToggleBtn = safenew wxButton(bar, kPlayID, _("&Preview"));
3040  mPlayToggleBtn->SetToolTip(_("Preview effect"));
3041  bs->Add(mPlayToggleBtn, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, margin);
3042  }
3043  }
3044  else
3045  {
3046  mPlayBM = CreateBitmap(effect_play_xpm, true, false);
3047  mPlayDisabledBM = CreateBitmap(effect_play_disabled_xpm, true, true);
3048  mStopBM = CreateBitmap(effect_stop_xpm, true, false);
3049  mStopDisabledBM = CreateBitmap(effect_stop_disabled_xpm, true, false);
3050  wxASSERT(bar); // To justify safenew
3051  bb = safenew wxBitmapButton(bar, kPlayID, mPlayBM);
3052  bb->SetBitmapDisabled(mPlayDisabledBM);
3053  bb->SetBitmapPressed(CreateBitmap(effect_play_xpm, false, true));
3054  mPlayBtn = bb;
3055  bs->Add(mPlayBtn);
3056  if (!mSupportsRealtime)
3057  {
3058  mPlayBtn->SetToolTip(_("Preview effect"));
3059 #if defined(__WXMAC__)
3060  mPlayBtn->SetName(_("Preview effect"));
3061 #else
3062  mPlayBtn->SetLabel(_("&Preview effect"));
3063 #endif
3064  }
3065  }
3066 
3067  if (mSupportsRealtime)
3068  {
3069  if (!mIsGUI)
3070  {
3071  wxASSERT(bar); // To justify safenew
3072  mRewindBtn = safenew wxButton(bar, kRewindID, _("Skip &Backward"));
3073  bs->Add(mRewindBtn, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, margin);
3074  }
3075  else
3076  {
3077  wxASSERT(bar); // To justify safenew
3078  bb = safenew wxBitmapButton(bar, kRewindID, CreateBitmap(effect_rewind_xpm, true, true));
3079  bb->SetBitmapDisabled(CreateBitmap(effect_rewind_disabled_xpm, true, false));
3080  bb->SetBitmapPressed(CreateBitmap(effect_rewind_xpm, false, true));
3081  mRewindBtn = bb;
3082 #if defined(__WXMAC__)
3083  mRewindBtn->SetName(_("Skip &Backward"));
3084 #else
3085  mRewindBtn->SetLabel(_("Skip &Backward"));
3086 #endif
3087  bs->Add(mRewindBtn);
3088  }
3089  mRewindBtn->SetToolTip(_("Skip backward"));
3090 
3091  if (!mIsGUI)
3092  {
3093  wxASSERT(bar); // To justify safenew
3094  mFFwdBtn = safenew wxButton(bar, kFFwdID, _("Skip &Forward"));
3095  bs->Add(mFFwdBtn, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, margin);
3096  }
3097  else
3098  {
3099  wxASSERT(bar); // To justify safenew
3100  bb = safenew wxBitmapButton(bar, kFFwdID, CreateBitmap(effect_ffwd_xpm, true, true));
3101  bb->SetBitmapDisabled(CreateBitmap(effect_ffwd_disabled_xpm, true, false));
3102  bb->SetBitmapPressed(CreateBitmap(effect_ffwd_xpm, false, true));
3103  mFFwdBtn = bb;
3104 #if defined(__WXMAC__)
3105  mFFwdBtn->SetName(_("Skip &Forward"));
3106 #else
3107  mFFwdBtn->SetLabel(_("Skip &Forward"));
3108 #endif
3109  bs->Add(mFFwdBtn);
3110  }
3111  mFFwdBtn->SetToolTip(_("Skip forward"));
3112 
3113  bs->Add(5, 5);
3114 
3115  mEnableCb = safenew wxCheckBox(bar, kEnableID, _("&Enable"));
3116  mEnableCb->SetValue(mEnabled);
3117  mEnableCb->SetName(_("Enable"));
3118  bs->Add(mEnableCb, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, margin);
3119  }
3120  }
3121 
3122  bar->SetSizerAndFit(bs.release());
3123  }
3124 
3125  long buttons;
3126  if ( mEffect && mEffect->ManualPage().IsEmpty() && mEffect->HelpPage().IsEmpty()) {
3127  buttons = eApplyButton + eCloseButton;
3128  this->SetAcceleratorTable(wxNullAcceleratorTable);
3129  }
3130  else {
3131  buttons = eApplyButton + eCloseButton + eHelpButton;
3132  wxAcceleratorEntry entries[1];
3133 #if defined(__WXMAC__)
3134  // Is there a standard shortcut on Mac?
3135 #else
3136  entries[0].Set(wxACCEL_NORMAL, (int) WXK_F1, wxID_HELP);
3137 #endif
3138  wxAcceleratorTable accel(1, entries);
3139  this->SetAcceleratorTable(accel);
3140  }
3141 
3142  if (mEffect && mEffect->mUIDebug) {
3143  buttons += eDebugButton;
3144  }
3145 
3146  buttonPanel->SetSizer(CreateStdButtonSizer(buttonPanel, buttons, bar).release());
3147  vs->Add(buttonPanel, 0, wxEXPAND);
3148 
3149  SetSizer(vs.release());
3150  }
3151 
3152  Layout();
3153  Fit();
3154  Center();
3155 
3156  mApplyBtn = (wxButton *) FindWindow(wxID_APPLY);
3157  mCloseBtn = (wxButton *) FindWindow(wxID_CANCEL);
3158 
3159  UpdateControls();
3160 
3161  w->SetAccept(!mIsGUI);
3162  (!mIsGUI ? w : FindWindow(wxID_APPLY))->SetFocus();
3163 
3164  LoadUserPresets();
3165 
3167 
3168  SetMinSize(GetSize());
3169  return true;
3170 }
3171 
3172 void EffectUIHost::OnInitDialog(wxInitDialogEvent & evt)
3173 {
3174  // Do default handling
3175  wxDialogWrapper::OnInitDialog(evt);
3176 
3177 #if wxCHECK_VERSION(3, 0, 0)
3178 //#warning "check to see if this still needed in wx3"
3179 #endif
3180 
3181  // Pure hackage coming down the pike...
3182  //
3183  // I have no idea why, but if a wxTextCtrl is the first control in the
3184  // panel, then its contents will not be automatically selected when the
3185  // dialog is displayed.
3186  //
3187  // So, we do the selection manually.
3188  wxTextCtrl *focused = wxDynamicCast(FindFocus(), wxTextCtrl);
3189  if (focused)
3190  {
3191  focused->SelectAll();
3192  }
3193 }
3194 
3195 void EffectUIHost::OnErase(wxEraseEvent & WXUNUSED(evt))
3196 {
3197  // Ignore it
3198 }
3199 
3200 void EffectUIHost::OnPaint(wxPaintEvent & WXUNUSED(evt))
3201 {
3202  wxPaintDC dc(this);
3203 
3204  dc.Clear();
3205 }
3206 
3207 void EffectUIHost::OnClose(wxCloseEvent & WXUNUSED(evt))
3208 {
3209  DoCancel();
3210 
3211  CleanupRealtime();
3212 
3213  Hide();
3214 
3215  if (mNeedsResume)
3216  Resume();
3217  mClient->CloseUI();
3218  mClient = NULL;
3219 
3220  Destroy();
3221 }
3222 
3223 void EffectUIHost::OnApply(wxCommandEvent & evt)
3224 {
3225  // On wxGTK (wx2.8.12), the default action is still executed even if
3226  // the button is disabled. This appears to affect all wxDialogs, not
3227  // just our Effects dialogs. So, this is a only temporary workaround
3228  // for legacy effects that disable the OK button. Hopefully this has
3229  // been corrected in wx3.
3230  if (!FindWindow(wxID_APPLY)->IsEnabled())
3231  {
3232  return;
3233  }
3234 
3235  // Honor the "select all if none" preference...a little hackish, but whatcha gonna do...
3236  if (!mIsBatch &&
3237  mEffect &&
3239  mEffect->GetType() != EffectTypeTool &&
3241  {
3242  auto flags = AlwaysEnabledFlag;
3243  bool allowed =
3245  *mProject,
3247  flags,
3250  if (!allowed)
3251  return;
3252  }
3253 
3254  if (!mClient->ValidateUI())
3255  {
3256  return;
3257  }
3258 
3259  // This will take care of calling TransferDataFromWindow() for an effect.
3261  {
3262  return;
3263  }
3264  // This will take care of calling TransferDataFromWindow() for a command.
3265  if (mCommand ){
3266  wxString params;
3267  mCommand->GetAutomationParameters( params );
3268  }
3269 
3270  if( mEffect )
3271  mEffect->mUIResultID = evt.GetId();
3272 
3273  if (IsModal())
3274  {
3275  mDismissed = true;
3276 
3277  EndModal(true);
3278 
3279  Close();
3280 
3281  return;
3282  }
3283 
3284  // Progress dialog no longer yields, so this "shouldn't" be necessary (yet to be proven
3285  // for sure), but it is a nice visual cue that something is going on.
3286  mApplyBtn->Disable();
3287  auto cleanup = finally( [&] { mApplyBtn->Enable(); } );
3288 
3289  if( mEffect )
3290  mEffect->Apply();
3291  if( mCommand )
3292  mCommand->Apply();
3293 }
3294 
3296 {
3297  if (!mDismissed) {
3298  if( mEffect )
3299  mEffect->mUIResultID = wxID_CANCEL;
3300 
3301  if (IsModal())
3302  EndModal(false);
3303  else
3304  Hide();
3305 
3306  mDismissed = true;
3307  }
3308 }
3309 
3310 void EffectUIHost::OnCancel(wxCommandEvent & WXUNUSED(evt))
3311 {
3312  DoCancel();
3313  Close();
3314 }
3315 
3316 void EffectUIHost::OnHelp(wxCommandEvent & WXUNUSED(event))
3317 {
3318  if (mEffect && mEffect->GetFamilyId() == NYQUISTEFFECTS_FAMILY && (mEffect->ManualPage().IsEmpty())) {
3319  // Old ShowHelp required when there is no on-line manual.
3320  // Always use default web browser to allow full-featured HTML pages.
3321  HelpSystem::ShowHelp(FindWindow(wxID_HELP), mEffect->HelpPage(), wxEmptyString, true, true);
3322  }
3323  else if( mEffect )
3324  {
3325  // otherwise use the NEW ShowHelp
3326  HelpSystem::ShowHelp(FindWindow(wxID_HELP), mEffect->ManualPage(), true);
3327  }
3328 }
3329 
3330 void EffectUIHost::OnDebug(wxCommandEvent & evt)
3331 {
3332  OnApply(evt);
3333  if( mEffect )
3334  mEffect->mUIResultID = evt.GetId();
3335 }
3336 
3337 void EffectUIHost::OnMenu(wxCommandEvent & WXUNUSED(evt))
3338 {
3339  wxMenu menu;
3340  if( !mEffect )
3341  return;
3342 
3343  LoadUserPresets();
3344 
3345  if (mUserPresets.GetCount() == 0)
3346  {
3347  menu.Append(kUserPresetsDummyID, _("User Presets"))->Enable(false);
3348  }
3349  else
3350  {
3351  auto sub = std::make_unique<wxMenu>();
3352  for (size_t i = 0, cnt = mUserPresets.GetCount(); i < cnt; i++)
3353  {
3354  sub->Append(kUserPresetsID + i, mUserPresets[i]);
3355  }
3356  menu.Append(0, _("User Presets"), sub.release());
3357  }
3358 
3359  menu.Append(kSaveAsID, _("Save Preset..."));
3360 
3361  if (mUserPresets.GetCount() == 0)
3362  {
3363  menu.Append(kDeletePresetDummyID, _("Delete Preset"))->Enable(false);
3364  }
3365  else
3366  {
3367  auto sub = std::make_unique<wxMenu>();
3368  for (size_t i = 0, cnt = mUserPresets.GetCount(); i < cnt; i++)
3369  {
3370  sub->Append(kDeletePresetID + i, mUserPresets[i]);
3371  }
3372  menu.Append(0, _("Delete Preset"), sub.release());
3373  }
3374 
3375  menu.AppendSeparator();
3376 
3377  wxArrayString factory = mEffect->GetFactoryPresets();
3378 
3379  {
3380  auto sub = std::make_unique<wxMenu>();
3381  sub->Append(kDefaultsID, _("Defaults"));
3382  if (factory.GetCount() > 0)
3383  {
3384  sub->AppendSeparator();
3385  for (size_t i = 0, cnt = factory.GetCount(); i < cnt; i++)
3386  {
3387  wxString label = factory[i];
3388  if (label.IsEmpty())
3389  {
3390  label = _("None");
3391  }
3392 
3393  sub->Append(kFactoryPresetsID + i, label);
3394  }
3395  }
3396  menu.Append(0, _("Factory Presets"), sub.release());
3397  }
3398 
3399  menu.AppendSeparator();
3400  menu.Append(kImportID, _("Import..."))->Enable(mClient->CanExportPresets());
3401  menu.Append(kExportID, _("Export..."))->Enable(mClient->CanExportPresets());
3402  menu.AppendSeparator();
3403  menu.Append(kOptionsID, _("Options..."))->Enable(mClient->HasOptions());
3404  menu.AppendSeparator();
3405 
3406  {
3407  auto sub = std::make_unique<wxMenu>();
3408 
3409  sub->Append(kDummyID, wxString::Format(_("Type: %s"),
3410  ::wxGetTranslation( mEffect->GetFamilyId().Translation() )));
3411  sub->Append(kDummyID, wxString::Format(_("Name: %s"), mEffect->GetTranslatedName()));
3412  sub->Append(kDummyID, wxString::Format(_("Version: %s"), mEffect->GetVersion()));
3413  sub->Append(kDummyID, wxString::Format(_("Vendor: %s"), mEffect->GetVendor().Translation()));
3414  sub->Append(kDummyID, wxString::Format(_("Description: %s"), mEffect->GetDescription()));
3415 
3416  menu.Append(0, _("About"), sub.release());
3417  }
3418 
3419  wxWindow *btn = FindWindow(kMenuID);
3420  wxRect r = btn->GetRect();
3421  btn->PopupMenu(&menu, r.GetLeft(), r.GetBottom());
3422 }
3423 
3425 {
3426  if (!mClient->ValidateUI()) {
3427  // If we're previewing we should still be able to stop playback
3428  // so don't disable transport buttons.
3429  // mEffect->EnableApply(false); // currently this would also disable transport buttons.
3430  // The preferred behaviour is currently undecided, so for now
3431  // just disallow enabling until settings are valid.
3432  mEnabled = false;
3433  mEnableCb->SetValue(mEnabled);
3434  return;
3435  }
3437 }
3438 
3439 void EffectUIHost::OnEnable(wxCommandEvent & WXUNUSED(evt))
3440 {
3441  mEnabled = mEnableCb->GetValue();
3442 
3443  if (mEnabled) {
3444  Resume();
3445  mNeedsResume = false;
3446  }
3447  else
3448  {
3450  mNeedsResume = true;
3451  }
3452 
3453  UpdateControls();
3454 }
3455 
3456 void EffectUIHost::OnPlay(wxCommandEvent & WXUNUSED(evt))
3457 {
3458  if (!mSupportsRealtime)
3459  {
3461  {
3462  return;
3463  }
3464 
3465  mEffect->Preview(false);
3466 
3467  return;
3468  }
3469 
3470  if (mPlaying)
3471  {
3474  }
3475  else
3476  {
3478  {
3479  double t0, t1;
3480  mProject->GetPlayRegion(&t0, &t1);
3481  mRegion.setTimes(t0, t1);
3482  mPlayPos = mRegion.t0();
3483  }
3484  else if (mProject->mViewInfo.selectedRegion.t0() != mRegion.t0() ||
3486  {
3488  mPlayPos = mRegion.t0();
3489  }
3490 
3491  if (mPlayPos > mRegion.t1())
3492  {
3493  mPlayPos = mRegion.t1();
3494  }
3495 
3499  }
3500 }
3501 
3502 void EffectUIHost::OnRewind(wxCommandEvent & WXUNUSED(evt))
3503 {
3504  if (mPlaying)
3505  {
3506  double seek;
3507  gPrefs->Read(wxT("/AudioIO/SeekShortPeriod"), &seek, 1.0);
3508 
3509  double pos = gAudioIO->GetStreamTime();
3510  if (pos - seek < mRegion.t0())
3511  {
3512  seek = pos - mRegion.t0();
3513  }
3514 
3515  gAudioIO->SeekStream(-seek);
3516  }
3517  else
3518  {
3519  mPlayPos = mRegion.t0();
3520  }
3521 }
3522 
3523 void EffectUIHost::OnFFwd(wxCommandEvent & WXUNUSED(evt))
3524 {
3525  if (mPlaying)
3526  {
3527  double seek;
3528  gPrefs->Read(wxT("/AudioIO/SeekShortPeriod"), &seek, 1.0);
3529 
3530  double pos = gAudioIO->GetStreamTime();
3531  if (mRegion.t0() < mRegion.t1() && pos + seek > mRegion.t1())
3532  {
3533  seek = mRegion.t1() - pos;
3534  }
3535 
3536  gAudioIO->SeekStream(seek);
3537  }
3538  else
3539  {
3540  // It allows to play past end of selection...probably useless
3541  mPlayPos = mRegion.t1();
3542  }
3543 }
3544 
3545 void EffectUIHost::OnPlayback(wxCommandEvent & evt)
3546 {
3547  evt.Skip();
3548 
3549  if (evt.GetInt() != 0)
3550  {
3551  if (evt.GetEventObject() != mProject)
3552  {
3553  mDisableTransport = true;
3554  }
3555  else
3556  {
3557  mPlaying = true;
3558  }
3559  }
3560  else
3561  {
3562  mDisableTransport = false;
3563  mPlaying = false;
3564  }
3565 
3566  if (mPlaying)
3567  {
3569  mPlayPos = mRegion.t0();
3570  }
3571 
3572  UpdateControls();
3573 }
3574 
3575 void EffectUIHost::OnCapture(wxCommandEvent & evt)
3576 {
3577  evt.Skip();
3578 
3579  if (evt.GetInt() != 0)
3580  {
3581  if (evt.GetEventObject() != mProject)
3582  {
3583  mDisableTransport = true;
3584  }
3585  else
3586  {
3587  mCapturing = true;
3588  }
3589  }
3590  else
3591  {
3592  mDisableTransport = false;
3593  mCapturing = false;
3594  }
3595 
3596  UpdateControls();
3597 }
3598 
3599 void EffectUIHost::OnUserPreset(wxCommandEvent & evt)
3600 {
3601  int preset = evt.GetId() - kUserPresetsID;
3602 
3604 
3605  return;
3606 }
3607 
3608 void EffectUIHost::OnFactoryPreset(wxCommandEvent & evt)
3609 {
3611 
3612  return;
3613 }
3614 
3615 void EffectUIHost::OnDeletePreset(wxCommandEvent & evt)
3616 {
3617  wxString preset = mUserPresets[evt.GetId() - kDeletePresetID];
3618 
3619  int res = AudacityMessageBox(wxString::Format(_("Are you sure you want to delete \"%s\"?"), preset),
3620  _("Delete Preset"),
3621  wxICON_QUESTION | wxYES_NO);
3622  if (res == wxYES)
3623  {
3625  }
3626 
3627  LoadUserPresets();
3628 
3629  return;
3630 }
3631 
3632 void EffectUIHost::OnSaveAs(wxCommandEvent & WXUNUSED(evt))
3633 {
3634  wxTextCtrl *text;
3635  wxString name;
3636  wxDialogWrapper dlg(this, wxID_ANY, wxString(_("Save Preset")));
3637 
3638  ShuttleGui S(&dlg, eIsCreating);
3639 
3640  S.StartPanel();
3641  {
3642  S.StartVerticalLay(1);
3643  {
3644  S.StartHorizontalLay(wxALIGN_LEFT, 0);
3645  {
3646  text = S.AddTextBox(_("Preset name:"), name, 30);
3647  }
3648  S.EndHorizontalLay();
3649  S.SetBorder(10);
3650  S.AddStandardButtons();
3651  }
3652  S.EndVerticalLay();
3653  }
3654  S.EndPanel();
3655 
3656  dlg.SetSize(dlg.GetSizer()->GetMinSize());
3657  dlg.Center();
3658 
3659  while (true)
3660  {
3661  int rc = dlg.ShowModal();
3662 
3663  if (rc != wxID_OK)
3664  {
3665  break;
3666  }
3667 
3668  name = text->GetValue();
3669  if (name.IsEmpty())
3670  {
3671  AudacityMessageDialog md(this,
3672  _("You must specify a name"),
3673  _("Save Preset"));
3674  md.Center();
3675  md.ShowModal();
3676  continue;
3677  }
3678 
3679  if (mUserPresets.Index(name) != wxNOT_FOUND)
3680  {
3681  AudacityMessageDialog md(this,
3682  _("Preset already exists.\n\nReplace?"),
3683  _("Save Preset"),
3684  wxYES_NO | wxCANCEL | wxICON_EXCLAMATION);
3685  md.Center();
3686  int choice = md.ShowModal();
3687  if (choice == wxID_CANCEL)
3688  {
3689  break;
3690  }
3691 
3692  if (choice == wxID_NO)
3693  {
3694  continue;
3695  }
3696  }
3697 
3699  LoadUserPresets();
3700 
3701  break;
3702  }
3703 
3704  return;
3705 }
3706 
3707 void EffectUIHost::OnImport(wxCommandEvent & WXUNUSED(evt))
3708 {
3710 
3711  LoadUserPresets();
3712 
3713  return;
3714 }
3715 
3716 void EffectUIHost::OnExport(wxCommandEvent & WXUNUSED(evt))
3717 {
3718  // may throw
3719  // exceptions are handled in AudacityApp::OnExceptionInMainLoop
3721 
3722  return;
3723 }
3724 
3725 void EffectUIHost::OnOptions(wxCommandEvent & WXUNUSED(evt))
3726 {
3727  mClient->ShowOptions();
3728 
3729  return;
3730 }
3731 
3732 void EffectUIHost::OnDefaults(wxCommandEvent & WXUNUSED(evt))
3733 {
3735 
3736  return;
3737 }
3738 
3739 wxBitmap EffectUIHost::CreateBitmap(const char * const xpm[], bool up, bool pusher)
3740 {
3741  wxMemoryDC dc;
3742  wxBitmap pic(xpm);
3743 
3744  wxBitmap mod(pic.GetWidth() + 6, pic.GetHeight() + 6, 24);
3745  dc.SelectObject(mod);
3746 
3747 #if defined(__WXGTK__)
3748  wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND);
3749 #else
3750  wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
3751 #endif
3752 
3753  dc.SetBackground(wxBrush(newColour));
3754  dc.Clear();
3755 
3756  int offset = 3;
3757  if (pusher)
3758  {
3759  if (!up)
3760  {
3761  offset += 1;
3762  }
3763  }
3764 
3765  dc.DrawBitmap(pic, offset, offset, true);
3766 
3767  dc.SelectObject(wxNullBitmap);
3768 
3769  return mod;
3770 }
3771 
3773 {
3774  if (mIsBatch)
3775  {
3776  return;
3777  }
3778 
3780  {
3781  // Don't allow focus to get trapped
3782  wxWindow *focus = FindFocus();
3783  if (focus == mRewindBtn || focus == mFFwdBtn || focus == mPlayBtn || focus == mEnableCb)
3784  {
3785  mCloseBtn->SetFocus();
3786  }
3787  }
3788 
3789  mApplyBtn->Enable(!mCapturing);
3791  {
3793  }
3794 
3795  if (mSupportsRealtime)
3796  {
3797  mRewindBtn->Enable(!(mCapturing || mDisableTransport));
3798  mFFwdBtn->Enable(!(mCapturing || mDisableTransport));
3799  mEnableCb->Enable(!(mCapturing || mDisableTransport));
3800 
3801  wxBitmapButton *bb;
3802 
3803  if (mPlaying)
3804  {
3805  if (!mIsGUI)
3806  {
3807  /* i18n-hint: The access key "&P" should be the same in
3808  "Stop &Playback" and "Start &Playback" */
3809  mPlayToggleBtn->SetLabel(_("Stop &Playback"));
3810  mPlayToggleBtn->Refresh();
3811  }
3812  else
3813  {
3814  bb = (wxBitmapButton *) mPlayBtn;
3815  bb->SetBitmapLabel(mStopBM);
3816  bb->SetBitmapDisabled(mStopDisabledBM);
3817  bb->SetToolTip(_("Stop"));
3818 #if defined(__WXMAC__)
3819  bb->SetName(_("Stop &Playback"));
3820 #else
3821  bb->SetLabel(_("Stop &Playback"));
3822 #endif
3823  }
3824  }
3825  else
3826  {
3827  if (!mIsGUI)
3828  {
3829  /* i18n-hint: The access key "&P" should be the same in
3830  "Stop &Playback" and "Start &Playback" */
3831  mPlayToggleBtn->SetLabel(_("Start &Playback"));
3832  mPlayToggleBtn->Refresh();
3833  }
3834  else
3835  {
3836  bb = (wxBitmapButton *) mPlayBtn;
3837  bb->SetBitmapLabel(mPlayBM);
3838  bb->SetBitmapDisabled(mPlayDisabledBM);
3839  bb->SetToolTip(_("Play"));
3840 #if defined(__WXMAC__)
3841  bb->SetName(_("Start &Playback"));
3842 #else
3843  bb->SetLabel(_("Start &Playback"));
3844 #endif
3845  }
3846  }
3847  }
3848 }
3849 
3851 {
3852  mUserPresets.Clear();
3853 
3854  if( mEffect )
3856 
3857  mUserPresets.Sort();
3858 
3859  return;
3860 }
3861 
3863 {
3865  {
3867 
3868  wxTheApp->Bind(EVT_AUDIOIO_PLAYBACK,
3870  this);
3871 
3872  wxTheApp->Bind(EVT_AUDIOIO_CAPTURE,
3874  this);
3875 
3876  mInitialized = true;
3877  }
3878 }
3879 
3881 {
3883  {
3885 
3886  mInitialized = false;
3887  }
3888 }
3889 
3891 //
3892 // EffectPresetsDialog
3893 //
3895 
3896 enum
3897 {
3898  ID_Type = 10000
3899 };
3900 
3901 BEGIN_EVENT_TABLE(EffectPresetsDialog, wxDialogWrapper)
3902  EVT_CHOICE(ID_Type, EffectPresetsDialog::OnType)
3903  EVT_LISTBOX_DCLICK(wxID_ANY, EffectPresetsDialog::OnOk)
3904  EVT_BUTTON(wxID_OK, EffectPresetsDialog::OnOk)
3905  EVT_BUTTON(wxID_CANCEL, EffectPresetsDialog::OnCancel)
3907 
3909 : wxDialogWrapper(parent, wxID_ANY, wxString(_("Select Preset")))
3910 {
3911  ShuttleGui S(this, eIsCreating);
3912  S.StartVerticalLay();
3913  {
3914  S.StartTwoColumn();
3915  S.SetStretchyCol(1);
3916  {
3917  wxArrayString empty;
3918 
3919  S.AddPrompt(_("Type:"));
3920  mType = S.Id(ID_Type).AddChoice( {}, wxT(""), &empty);
3921  mType->SetSelection(0);
3922 
3923  S.AddPrompt(_("&Preset:"));
3924  mPresets = S.AddListBox(&empty, wxLB_SINGLE | wxLB_NEEDED_SB );
3925  }
3926  S.EndTwoColumn();
3927 
3928  S.AddStandardButtons();
3929  }
3930  S.EndVerticalLay();
3931 
3932  mUserPresets = effect->GetUserPresets();
3933  mFactoryPresets = effect->GetFactoryPresets();
3934 
3935  if (mUserPresets.GetCount() > 0)
3936  {
3937  mType->Append(_("User Presets"));
3938  }
3939 
3940  if (mFactoryPresets.GetCount() > 0)
3941  {
3942  mType->Append(_("Factory Presets"));
3943  }
3944 
3945  if (effect->HasCurrentSettings())
3946  {
3947  mType->Append(_("Current Settings"));
3948  }
3949 
3950  if (effect->HasFactoryDefaults())
3951  {
3952  mType->Append(_("Factory Defaults"));
3953  }
3954 
3955  UpdateUI();
3956 }
3957 
3959 {
3960 }
3961 
3963 {
3964  return mSelection;
3965 }
3966 
3967 void EffectPresetsDialog::SetSelected(const wxString & parms)
3968 {
3969  wxString preset = parms;
3970  if (preset.StartsWith(Effect::kUserPresetIdent))
3971  {
3972  preset.Replace(Effect::kUserPresetIdent, wxEmptyString, false);
3973  SetPrefix(_("User Presets"), preset);
3974  }
3975  else if (preset.StartsWith(Effect::kFactoryPresetIdent))
3976  {
3977  preset.Replace(Effect::kFactoryPresetIdent, wxEmptyString, false);
3978  SetPrefix(_("Factory Presets"), preset);
3979  }
3980  else if (preset.StartsWith(Effect::kCurrentSettingsIdent))
3981  {
3982  SetPrefix(_("Current Settings"), wxEmptyString);
3983  }
3984  else if (preset.StartsWith(Effect::kFactoryDefaultsIdent))
3985  {
3986  SetPrefix(_("Factory Defaults"), wxEmptyString);
3987  }
3988 }
3989 
3990 void EffectPresetsDialog::SetPrefix(const wxString & type, const wxString & prefix)
3991 {
3992  mType->SetStringSelection(type);
3993 
3994  if (type.IsSameAs(_("User Presets")))
3995  {
3996  mPresets->Clear();
3997  mPresets->Append(mUserPresets);
3998  mPresets->Enable(true);
3999  mPresets->SetStringSelection(prefix);
4000  if (mPresets->GetSelection() == wxNOT_FOUND)
4001  {
4002  mPresets->SetSelection(0);
4003  }
4004  mSelection = Effect::kUserPresetIdent + mPresets->GetStringSelection();
4005  }
4006  else if (type.IsSameAs(_("Factory Presets")))
4007  {
4008  mPresets->Clear();
4009  for (size_t i = 0, cnt = mFactoryPresets.GetCount(); i < cnt; i++)
4010  {
4011  wxString label = mFactoryPresets[i];
4012  if (label.IsEmpty())
4013  {
4014  label = _("None");
4015  }
4016  mPresets->Append(label);
4017  }
4018  mPresets->Enable(true);
4019  mPresets->SetStringSelection(prefix);
4020  if (mPresets->GetSelection() == wxNOT_FOUND)
4021  {
4022  mPresets->SetSelection(0);
4023  }
4024  mSelection = Effect::kFactoryPresetIdent + mPresets->GetStringSelection();
4025  }
4026  else if (type.IsSameAs(_("Current Settings")))
4027  {
4028  mPresets->Clear();
4029  mPresets->Enable(false);
4031  }
4032  else if (type.IsSameAs(_("Factory Defaults")))
4033  {
4034  mPresets->Clear();
4035  mPresets->Enable(false);
4037  }
4038 }
4039 
4041 {
4042  int selected = mType->GetSelection();
4043  if (selected == wxNOT_FOUND)
4044  {
4045  selected = 0;
4046  mType->SetSelection(selected);
4047  }
4048  wxString type = mType->GetString(selected);
4049 
4050  if (type.IsSameAs(_("User Presets")))
4051  {
4052  selected = mPresets->GetSelection();
4053  if (selected == wxNOT_FOUND)
4054  {
4055  selected = 0;
4056  }
4057 
4058  mPresets->Clear();
4059  mPresets->Append(mUserPresets);
4060  mPresets->Enable(true);
4061  mPresets->SetSelection(selected);
4062  mSelection = Effect::kUserPresetIdent + mPresets->GetString(selected);
4063  }
4064  else if (type.IsSameAs(_("Factory Presets")))
4065  {
4066  selected = mPresets->GetSelection();
4067  if (selected == wxNOT_FOUND)
4068  {
4069  selected = 0;
4070  }
4071 
4072  mPresets->Clear();
4073  for (size_t i = 0, cnt = mFactoryPresets.GetCount(); i < cnt; i++)
4074  {
4075  wxString label = mFactoryPresets[i];
4076  if (label.IsEmpty())
4077  {
4078  label = _("None");
4079  }
4080  mPresets->Append(label);
4081  }
4082  mPresets->Enable(true);
4083  mPresets->SetSelection(selected);
4084  mSelection = Effect::kFactoryPresetIdent + mPresets->GetString(selected);
4085  }
4086  else if (type.IsSameAs(_("Current Settings")))
4087  {
4088  mPresets->Clear();
4089  mPresets->Enable(false);
4091  }
4092  else if (type.IsSameAs(_("Factory Defaults")))
4093  {
4094  mPresets->Clear();
4095  mPresets->Enable(false);
4097  }
4098 }
4099 
4100 void EffectPresetsDialog::OnType(wxCommandEvent & WXUNUSED(evt))
4101 {
4102  UpdateUI();
4103 }
4104 
4105 void EffectPresetsDialog::OnOk(wxCommandEvent & WXUNUSED(evt))
4106 {
4107  UpdateUI();
4108 
4109  EndModal(true);
4110 }
4111 
4112 void EffectPresetsDialog::OnCancel(wxCommandEvent & WXUNUSED(evt))
4113 {
4114  mSelection = wxEmptyString;
4115 
4116  EndModal(false);
4117 }
int StartStream(const TransportTracks &tracks, double t0, double t1, const AudioIOStartStreamOptions &options)
Start recording or playing back audio.
Definition: AudioIO.cpp:1718
wxString GetUserPresetsGroup(const wxString &name) override
Definition: Effect.cpp:794
bool ReportIfActionNotAllowed(AudacityProject &project, const wxString &Name, CommandFlag &flags, CommandFlag flagsRqd, CommandFlag mask)
Definition: Project.cpp:2277
std::unordered_map< void *, bool > t2bHash
Definition: Effect.cpp:101
void OnDeletePreset(wxCommandEvent &evt)
Definition: Effect.cpp:3615
IdentInterfaceSymbol GetFamilyId() override
Definition: Effect.cpp:211
Effect()
Definition: Effect.cpp:103
void ReplaceWaveTrack(Track *oldTrack, Track *newTrack)
replace the wavetrack whose wavecache the gui watches for updates
Definition: ODManager.cpp:384
void SetForWriting(CommandParameters *pEap)
Definition: Shuttle.h:114
static bool IsInstanceCreated()
returns whether or not the singleton instance was created yet
Definition: ODManager.cpp:205
wxArrayString mUserPresets
Definition: Effect.h:652
std::unique_ptr< wxSizer > CreateStdButtonSizer(wxWindow *parent, long buttons, wxWindow *extra)
double mT1
Definition: Effect.h:465
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
A list of TrackListNode items.
Definition: Track.h:1115
void StopStream()
Stop recording, playback or input monitoring.
Definition: AudioIO.cpp:2412
#define AUDACITY_VERSION_STRING
Definition: Audacity.h:81
void OnCapture(wxCommandEvent &evt)
Definition: Effect.cpp:3575
static ODManager *(* Instance)()
Definition: ODManager.h:49
unsigned GetAudioInCount() override
Definition: Effect.cpp:285
AudacityCommand * mCommand
Definition: Effect.h:649
#define BUILTIN_EFFECT_PREFIX
Definition: Effect.h:47
std::unique_ptr< LabelTrack > Holder
Definition: LabelTrack.h:160
bool SaveUserPreset(const wxString &name) override
Definition: Effect.cpp:603
#define RTL_WORKAROUND(pWnd)
Definition: Audacity.h:235
void CountWaveTracks()
Definition: Effect.cpp:2254
AudioIOStartStreamOptions GetDefaultPlayOptions()
Definition: Project.cpp:1300
int MessageBox(const wxString &message, long style=DefaultMessageBoxStyle, const wxString &titleStr=wxString{})
Definition: Effect.cpp:2629
virtual void SetBatchProcessing(bool start)
Definition: Effect.cpp:1147
virtual bool IsGraphicalUI()=0
virtual bool PopulateUI(wxWindow *parent)=0
void SetOffset(double dOffset) override
Definition: LabelTrack.cpp:146
void OnInitDialog(wxInitDialogEvent &evt)
Definition: Effect.cpp:3172
Track * AddToOutputTracks(std::unique_ptr< Track > &&t)
Definition: Effect.cpp:2072
EffectUIClientInterface is an abstract base class to populate a UI and validate UI values...
bool TrackProgress(int whichTrack, double frac, const wxString &=wxEmptyString)
Definition: Effect.cpp:1995
double t0() const
wxBitmap CreateBitmap(const char *const xpm[], bool up, bool pusher)
Definition: Effect.cpp:3739
virtual bool TransferDataFromWindow()
Definition: Effect.cpp:1891
std::vector< int > mGroupProcessor
Definition: Effect.h:536
virtual size_t SetBlockSize(size_t maxBlockSize)=0
static const int kMenuID
Definition: Effect.cpp:85
virtual int GetMidiOutCount()=0
static const int kDeletePresetID
Definition: Effect.cpp:93
void UpdateControls()
Definition: Effect.cpp:3772
static PluginID GetID(ModuleInterface *module)
bool isPoint() const
void OnUserPreset(wxCommandEvent &evt)
Definition: Effect.cpp:3599
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
virtual IdentInterfaceSymbol GetFamilyId()=0
double GetDuration() override
Definition: Effect.cpp:725
root of a hierarchy of classes that are thrown and caught by Audacity.
AdornedRulerPanel * mParent
Definition: Ruler.cpp:2081
SelectedRegion selectedRegion
Definition: ViewInfo.h:160
bool RemoveSharedConfig(const PluginID &ID, const wxString &group, const wxString &key) override
ProgressDialog Class.
bool GetSharedConfigSubgroups(const PluginID &ID, const wxString &group, wxArrayString &subgroups) override
ProgressDialog * mProgress
Definition: Effect.h:456
double GetStreamTime()
During playback, the track time most recently played.
Definition: AudioIO.cpp:2903
void InitializeRealtime()
Definition: Effect.cpp:3862
bool DoEffect(const PluginID &ID, const CommandContext &context, int flags)
Definition: Menus.cpp:4850
void SetPreviewFullSelectionFlag(bool previewDurationFlag)
Definition: Effect.cpp:1976
TrackList * mTracks
Definition: Effect.h:506
bool GetPrivateConfig(const wxString &group, const wxString &key, wxString &value, const wxString &defval=wxEmptyString) override
Definition: Effect.cpp:901
bool SetSharedConfig(const wxString &group, const wxString &key, const wxString &value) override
Definition: Effect.cpp:856
int mPass
Definition: Effect.h:472
wxButton * mPlayToggleBtn
Definition: Effect.h:667
wxString GetCurrentSettingsGroup() override
Definition: Effect.cpp:805
virtual bool HasOptions()=0
void OnRewind(wxCommandEvent &evt)
Definition: Effect.cpp:3502
EffectPanel(wxWindow *parent)
Definition: Effect.cpp:2740
bool GetSelected() const
Definition: Track.h:374
wxButton * mCloseBtn
Definition: Effect.h:659
virtual ~EffectPresetsDialog()
Definition: Effect.cpp:3958
void SetLinearEffectFlag(bool linearEffectFlag)
Definition: Effect.cpp:1971
double mPlayPos
Definition: Effect.h:681
int GetMidiInCount() override
Definition: Effect.cpp:305
virtual bool RealtimeFinalize()=0
void GroupChannels(Track &track, size_t groupSize, bool resetChannels=true)
Define a group of channels starting at the given track.
Definition: Track.cpp:728
bool RealtimeProcessEnd() override
Definition: Effect.cpp:507
EffectType
size_t SetBlockSize(size_t maxBlockSize) override
Definition: Effect.cpp:335
EffectUIClientInterface * mClient
Definition: Effect.h:650
bool mPreviewFullSelection
Definition: Effect.h:511
bool AcceptsFocus() const override
Definition: Effect.cpp:2758
auto SelectedLeaders() -> TrackIterRange< TrackType >
Definition: Track.h:1246
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:113
bool SetAutomationParameters(CommandParameters &parms) override
Definition: Effect.cpp:577
bool mAcceptsFocus
Definition: Effect.cpp:2778
virtual bool Init()
Definition: Effect.cpp:1286
virtual bool TransferDataToWindow()
Definition: Effect.cpp:1886
virtual bool CanExportPresets()=0
void OnFactoryPreset(wxCommandEvent &evt)
Definition: Effect.cpp:3608
void OnCancel(wxCommandEvent &evt)
Definition: Effect.cpp:4112
bool IsRealtimeActive()
Definition: Effect.cpp:2448
#define QUANTIZED_TIME(time, rate)
Definition: Audacity.h:214
wxBitmap mPlayDisabledBM
Definition: Effect.h:670
bool RemovePrivateConfigSubgroup(const wxString &group) override
Definition: Effect.cpp:951
virtual PluginID GetID()
Definition: Effect.cpp:963
bool mIsPreview
Definition: Effect.h:517
bool mPlaying
Definition: Effect.h:677
bool mDismissed
Definition: Effect.h:683
Track * Add(std::unique_ptr< TrackKind > &&t)
Add a Track, giving it a fresh id.
Definition: Track.cpp:671
void ReplaceProcessedTracks(const bool bGoodResult)
Definition: Effect.cpp:2167
virtual void ShowOptions()=0
virtual bool IsBatchProcessing()
EffectClientInterface * mClient
Definition: Effect.h:528
wxWindow * mParent
Definition: Effect.h:647
virtual unsigned GetAudioInCount()=0
static const int kPlayID
Definition: Effect.cpp:87
wxButton * mRewindBtn
Definition: Effect.h:662
unsigned GetNumCaptureChannels() const
Definition: AudioIO.h:1027
void Offset(double t)
Definition: Track.h:383
bool HasPrivateConfigGroup(const PluginID &ID, const wxString &group)
bool TransferDataFromWindow() override
Definition: Effect.cpp:2909
virtual void EnableDebug(bool enable=true)
Definition: Effect.cpp:1966
void SetPresetParameters(const wxArrayString *Names, const wxArrayString *Values)
Definition: Effect.h:240
virtual wxString ManualPage()
Definition: Effect.cpp:1132
Shuttle that gets parameter values into a string.
Definition: Shuttle.h:87
wxString label
Definition: Tags.cpp:733
SelectedRegion mRegion
Definition: Effect.h:680
size_t RealtimeProcess(int group, float **inbuf, float **outbuf, size_t numSamples) override
Definition: Effect.cpp:494
void Init()
Definition: Effect.cpp:2654
virtual bool ShowInterface(wxWindow *parent, bool forceModal=false)=0
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1195
void ClearAndPaste(double t0, double t1, const Track *src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=NULL)
Definition: WaveTrack.cpp:798
wxString PluginID
Definition: Types.h:209
wxPanel * StartPanel(int iStyle=0)
Definition: ShuttleGui.cpp:855
virtual bool SupportsRealtime()=0
static const int kCaptureID
Definition: Effect.cpp:91
bool RealtimeSuspend() override
Definition: Effect.cpp:440
virtual bool RealtimeProcessEnd()=0
bool DoEffect(wxWindow *parent, double projectRate, TrackList *list, TrackFactory *factory, SelectedRegion *selectedRegion, bool shouldPrompt=true)
Definition: Effect.cpp:1161
virtual wxString GetPreset(wxWindow *parent, const wxString &parms)
Definition: Effect.cpp:1115
bool HasPrivateConfigGroup(const wxString &group) override
Definition: Effect.cpp:891
Base class for many of the effects in Audacity.
Definition: Effect.h:62
void StopPlaying(bool stopStream=true)
wxListBox * mPresets
Definition: Effect.h:708
static const int kConfigured
Definition: Menus.h:496
#define XO(s)
Definition: Internat.h:33
int AudacityMessageBox(const wxString &message, const wxString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: ErrorDialog.h:92
virtual bool HasCurrentSettings()
Definition: Effect.cpp:1105
virtual void ExportPresets()=0
wxButton * mApplyBtn
Definition: Effect.h:658
bool RemoveSharedConfig(const wxString &group, const wxString &key) override
Definition: Effect.cpp:886
NumericFormatId GetDurationFormat() override
Definition: Effect.cpp:735
virtual bool ProcessPass()
Definition: Effect.cpp:1338
bool IsStreamActive() const
Returns true if the audio i/o is running at all, but not during cleanup.
Definition: AudioIO.cpp:2757
New (Jun-2006) base class for effects dialogs. Likely to get greater use in future.
Definition: Effect.h:561
double GetEndTime() const override
Get the time at which the last clip in the track ends, plus recorded stuff.
Definition: WaveTrack.cpp:1888
#define NYQUIST_EFFECTS_PROMPT_ID
Definition: Nyquist.h:37
void OnErase(wxEraseEvent &evt)
Definition: Effect.cpp:3195
size_t GetTailSize() override
Definition: Effect.cpp:357
virtual bool Process()
Definition: Effect.cpp:1312
double GetStartTime() const override
virtual void PopulateOrExchange(ShuttleGui &S)
Definition: Effect.cpp:2685
CommandContext provides addiitonal information to an 'Apply()' command. It provides the project...
std::shared_ptr< AddedAnalysisTrack > AddAnalysisTrack(const wxString &name=wxString())
Definition: Effect.cpp:2109
static const int kPlaybackID
Definition: Effect.cpp:90
static const int kUserPresetsID
Definition: Effect.cpp:92
AudacityProject * mProject
Definition: Effect.h:646
bool IsBusy() const
Returns true if audio i/o is busy starting, stopping, playing, or recording.
Definition: AudioIO.cpp:2749
static const int kFFwdID
Definition: Effect.cpp:89
bool RealtimeProcessStart() override
Definition: Effect.cpp:484
bool mSupportsRealtime
Definition: Effect.h:654
void ShowOptions() override
Definition: Effect.cpp:714
double t1() const
double GetEndTime() const override
bool SetPrivateConfig(const wxString &group, const wxString &key, const wxString &value) override
Definition: Effect.cpp:926
virtual bool RealtimeProcessStart()=0
void OnMenu(wxCommandEvent &evt)
Definition: Effect.cpp:3337
virtual size_t GetTailSize()=0
virtual IdentInterfaceSymbol GetSymbol()=0
void ShowErrorDialog(wxWindow *parent, const wxString &dlogTitle, const wxString &message, const wxString &helpPage, const bool Close)
Displays an error dialog with a button that offers help.
size_t mBufferSize
Definition: Effect.h:532
Wrap wxMessageDialog so that caption IS translatable.
Definition: ErrorDialog.h:129
double mSampleRate
Definition: Effect.h:459
void SetSampleRate(double rate) override
Definition: Effect.cpp:325
bool CanExportPresets() override
Definition: Effect.cpp:696
void OnClose(wxCloseEvent &evt)
Definition: Effect.cpp:3207
virtual ~EffectPanel()
Definition: Effect.cpp:2750
wxString GetDescription() override
Definition: Effect.cpp:201
bool mIsSelection
Definition: Effect.h:513
bool GetSharedConfig(const wxString &group, const wxString &key, wxString &value, const wxString &defval=wxEmptyString) override
Definition: Effect.cpp:831
static NumericFormatId TimeAndSampleFormat()
int GetWaveColorIndex() const
Definition: WaveTrack.h:147
virtual bool GetAutomationParameters(wxString &parms)
ModifiedAnalysisTrack ModifyAnalysisTrack(const LabelTrack *pOrigTrack, const wxString &name=wxString())
Definition: Effect.cpp:2160
bool LoadUserPreset(const wxString &name) override
Definition: Effect.cpp:587
EffectUIHost(wxWindow *parent, Effect *effect, EffectUIClientInterface *client)
Definition: Effect.cpp:2813
bool SetSharedConfig(const PluginID &ID, const wxString &group, const wxString &key, const wxString &value) override
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1212
#define safenew
Definition: Audacity.h:230
const wxString & Translation() const
void GetSamples(const WaveTrack *track, sampleCount *start, sampleCount *len)
Definition: Effect.cpp:2011
static const int kUserPresetsDummyID
Definition: Effect.cpp:83
size_t mNumAudioIn
Definition: Effect.h:529
wxCriticalSection mRealtimeSuspendLock
Definition: Effect.h:539
LabelTrack * mpTrack
Definition: Effect.h:401
virtual void SetSelected(bool s)
Definition: Track.cpp:94
static std::shared_ptr< TrackList > Create()
Definition: Track.cpp:529
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: Types.h:178
Used to create a WaveTrack, or a LabelTrack.. Implementation of the functions of this class are dispe...
Definition: Track.h:1563
void InsertSilence(double t, double len) override
Definition: WaveTrack.cpp:1400
double mF0
Definition: Effect.h:467
bool mIsBatch
Definition: Effect.h:656
void EndHorizontalLay()
size_t mNumAudioOut
Definition: Effect.h:530
wxBitmap mStopBM
Definition: Effect.h:671
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:113
wxArrayString mFactoryPresets
Definition: Effect.h:710
double f0() const
bool TotalProgress(double frac, const wxString &=wxEmptyString)
Definition: Effect.cpp:1987
virtual bool HasFactoryDefaults()
Definition: Effect.cpp:1110
void AddPrompt(const wxString &Prompt)
Right aligned text string.
Definition: ShuttleGui.cpp:239
virtual wxString GetDescription()=0
virtual void ImportPresets()=0
void OnCancel(wxCommandEvent &evt)
Definition: Effect.cpp:3310
void Preview() override
Definition: Effect.cpp:775
int GetMidiOutCount() override
Definition: Effect.cpp:315
static const int kRewindID
Definition: Effect.cpp:88
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper, LinearInputRateSlideTimeWarper, LinearOutputRateSlideTimeWarper, LinearInputInverseRateTimeWarper, GeometricInputRateTimeWarper, GeometricOutputRateTimeWarper classes.
bool GetPrivateConfigSubgroups(const wxString &group, wxArrayString &subgroups) override
Definition: Effect.cpp:896
bool HasSharedConfigGroup(const wxString &group) override
Definition: Effect.cpp:821
bool SetHost(EffectHostInterface *host) override
Definition: Effect.cpp:275
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:175
wxString GetSelected() const
Definition: Effect.cpp:3962
void EndVerticalLay()
void OnFFwd(wxCommandEvent &evt)
Definition: Effect.cpp:3523
double GetStartTime() const override
Get the time at which the first clip in the track starts.
Definition: WaveTrack.cpp:1868
virtual wxString GetVersion()=0
void SetPrefix(const wxString &type, const wxString &prefix)
Definition: Effect.cpp:3990
bool IsGraphicalUI() override
Definition: Effect.cpp:670
bool HasSharedConfigGroup(const PluginID &ID, const wxString &group)
static const int kDummyID
Definition: Effect.cpp:77
static const int kDeletePresetDummyID
Definition: Effect.cpp:84
virtual bool RealtimeAddProcessor(unsigned numChannels, float sampleRate)=0
virtual bool InitPass2()
Definition: Effect.cpp:1307
EffectType GetType() override
Definition: Effect.cpp:151
wxTextCtrl * AddTextBox(const wxString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:548
std::vector< Track * > mOMap
Definition: Effect.h:522
virtual bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap=NULL)=0
bool IsReady() override
Definition: Effect.cpp:367
bool TransferDataFromWindow() override
Definition: Effect.cpp:2698
wxString GetVersion() override
Definition: Effect.cpp:191
void OnHelp(wxCommandEvent &evt)
Definition: Effect.cpp:3316
virtual bool SaveUserPreset(const wxString &name)=0
void OnPaint(wxPaintEvent &evt)
Definition: Effect.cpp:3200
std::unique_ptr< WaveTrack > Holder
Definition: WaveTrack.h:90
wxArrayString GetFactoryPresets() override
Definition: Effect.cpp:619
void SetSelected(const wxString &parms)
Definition: Effect.cpp:3967
TransportTracks GetAllPlaybackTracks(TrackList &trackList, bool selectedOnly, bool useMidi)
Definition: Track.cpp:1337
Defines a selected portion of a project.
virtual sampleCount GetLatency()=0
wxButton * mMenuBtn
Definition: Effect.h:660
bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap=NULL) override
Definition: Effect.cpp:377
void OnPlayback(wxCommandEvent &evt)
Definition: Effect.cpp:3545
void Set(samplePtr buffer, sampleFormat format, sampleCount start, size_t len)
Definition: WaveTrack.cpp:2067
void StartTwoColumn()
Definition: ShuttleGui.h:136
void ExportPresets() override
Definition: Effect.cpp:701
void DoCancel()
Definition: Effect.cpp:3295
static const int kExportID
Definition: Effect.cpp:80
virtual bool GetAutomationParameters(CommandParameters &parms)=0
bool TransferDataToWindow() override
Definition: Effect.cpp:2900
bool SetPrivateConfig(const PluginID &ID, const wxString &group, const wxString &key, const wxString &value) override
void OnOk(wxCommandEvent &evt)
Definition: Effect.cpp:4105
bool ValidateUI() override
Definition: Effect.cpp:675
static const wxString kUserPresetIdent
Definition: Effect.h:542
struct holding stream options, including a pointer to the TimeTrack and AudioIOListener and whether t...
Definition: AudioIO.h:124
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
size_t mBlockSize
Definition: Effect.h:533
virtual bool InitPass1()
Definition: Effect.cpp:1302
CommandParameters * mpEap
Definition: Shuttle.h:65
virtual void End()
Definition: Effect.cpp:1877
wxChoice * AddChoice(const wxString &Prompt, const wxString &Selected, const wxArrayString *pChoices)
Definition: ShuttleGui.cpp:379
virtual bool IsReady()=0
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the Shuttle cla...
IdentInterfaceSymbol GetSymbol() override
Definition: Effect.cpp:171
ChannelName
Definition: Types.h:215
int mNumTracks
Definition: Effect.h:524
static const int kImportID
Definition: Effect.cpp:79
ListOfTracks::value_type Replace(Track *t, ListOfTracks::value_type &&with)
Definition: Track.cpp:780
virtual bool RealtimeSuspend()=0
bool RealtimeFinalize() override
Definition: Effect.cpp:430
virtual wxArrayString GetFactoryPresets()=0
void OnApply(wxCommandEvent &evt)
Definition: Effect.cpp:3223
char * samplePtr
Definition: Types.h:203
virtual bool RealtimeInitialize()=0
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
ShuttleGui & Id(int id)
bool ProcessFinalize() override
Definition: Effect.cpp:387
void OnOptions(wxCommandEvent &evt)
Definition: Effect.cpp:3725
virtual double CalcPreviewInputLength(double previewLength)
Definition: Effect.cpp:2260
bool mNeedsResume
Definition: Effect.h:684
bool PopulateUI(wxWindow *parent) override
Definition: Effect.cpp:655
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:190
ProgressResult Update(int value, const wxString &message=wxEmptyString)
void RealtimeRemoveEffect(Effect *effect)
bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) override
Definition: Effect.cpp:420
wxChoice * mType
Definition: Effect.h:707
void CleanupRealtime()
Definition: Effect.cpp:3880
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
void LoadUserPresets()
Definition: Effect.cpp:3850
virtual bool LoadFactoryDefaults()=0
ViewInfo mViewInfo
Definition: Project.h:562
bool mIsLinearEffect
Definition: Effect.h:509
void OnEnable(wxCommandEvent &evt)
Definition: Effect.cpp:3439
wxString mSelection
Definition: Effect.h:712
int mRealtimeSuspendCount
Definition: Effect.h:540
bool GetParameters(wxString &parms)
bool RemoveSharedConfigSubgroup(const PluginID &ID, const wxString &group) override
std::vector< Track * > mIMap
Definition: Effect.h:521
static void ShowHelp(wxWindow *parent, const wxString &localFileName, const wxString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:194
bool mCapturing
Definition: Effect.h:678
int min(int a, int b)
bool IsLegacy() override
Definition: Effect.cpp:243
static const int kDefaultsID
Definition: Effect.cpp:81
void SetDuration(double duration) override
Definition: Effect.cpp:745
void OnExport(wxCommandEvent &evt)
Definition: Effect.cpp:3716
double GetDefaultDuration() override
Definition: Effect.cpp:720
void CopyInputTracks(bool allSyncLockSelected=false)
Definition: Effect.cpp:2047
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), const F3 &delayedHandler={})
void IncludeNotSelectedPreviewTracks(bool includeNotSelected)
Definition: Effect.cpp:1982
virtual bool Apply(const CommandContext &WXUNUSED(context))
void OnImport(wxCommandEvent &evt)
Definition: Effect.cpp:3707
void ImportPresets() override
Definition: Effect.cpp:705
bool mPreviewWithNotSelected
Definition: Effect.h:510
#define NYQUISTEFFECTS_FAMILY
Definition: Nyquist.h:35
virtual bool IsDefault()=0
IdentInterfaceSymbol pairs a persistent string identifier used internally with an optional...
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:1640
Base class for command in Audacity.
enum ChannelName * ChannelNames
MenuManager & GetMenuManager(AudacityProject &project)
Definition: Menus.cpp:155
static EffectManager & Get()
static const int kFactoryPresetsID
Definition: Effect.cpp:94
void SetAccept(bool accept)
Definition: Effect.cpp:2772
virtual bool SupportsAutomation()=0
bool RealtimeInitialize() override
Definition: Effect.cpp:407
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
bool IsInteractive() override
Definition: Effect.cpp:223
bool RemovePrivateConfig(const wxString &group, const wxString &key) override
Definition: Effect.cpp:956
void OnDebug(wxCommandEvent &evt)
Definition: Effect.cpp:3330
static int nEffectsDone
Definition: Effect.h:375
void OnPlay(wxCommandEvent &evt)
Definition: Effect.cpp:3456
virtual ~Effect()
Definition: Effect.cpp:141
std::unique_ptr< WaveTrack > NewWaveTrack(sampleFormat format=(sampleFormat) 0, double rate=0)
Definition: WaveTrack.cpp:78
wxWindow * mUIParent
Definition: Effect.h:476
virtual bool ValidateUI()=0
bool LoadFactoryPreset(int id) override
Definition: Effect.cpp:629
virtual int GetMidiInCount()=0
const wxString & GetTranslatedName()
bool GetSharedConfigSubgroups(const wxString &group, wxArrayString &subgroups) override
Definition: Effect.cpp:826
bool Apply() override
Definition: Effect.cpp:764
bool GetAutomationParameters(CommandParameters &parms) override
Definition: Effect.cpp:567
bool RealtimeResume() override
Definition: Effect.cpp:462
double mProjectRate
Definition: Effect.h:457
IdentInterfaceSymbol GetVendor() override
Definition: Effect.cpp:181
bool setTimes(double t0, double t1)
Continuation<> Fallthrough
Definition: Track.h:443
_("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
TrackNodePointer Remove(Track *t)
Definition: Track.cpp:802
unsigned mNumChannels
Definition: Effect.h:534
TrackFactory * mFactory
Definition: Effect.h:461
ValueRestorer< T > valueRestorer(T &var)
Definition: MemoryX.h:413
bool IsDefault() override
Definition: Effect.cpp:233
virtual EffectType GetType()=0
AudioIO * gAudioIO
Definition: AudioIO.cpp:492
int PlayPlayRegion(const SelectedRegion &selectedRegion, const AudioIOStartStreamOptions &options, PlayMode playMode, PlayAppearance appearance=PlayAppearance::Straight, bool backwards=false, bool playWhiteSpace=false)
virtual bool IsHidden()
Definition: Effect.cpp:2453
bool ProcessTrack(int count, ChannelNames map, WaveTrack *left, WaveTrack *right, sampleCount leftStart, sampleCount rightStart, sampleCount len, FloatBuffers &inBuffer, FloatBuffers &outBuffer, ArrayOf< float * > &inBufPos, ArrayOf< float * > &outBufPos)
Definition: Effect.cpp:1494
EffectHostInterface is a decorator of a EffectUIClientInterface. It adds virtual (abstract) functions...
sampleCount GetLatency() override
Definition: Effect.cpp:347
virtual bool SetHost(EffectHostInterface *host)=0
ControlToolBar * GetControlToolBar()
Definition: Project.cpp:4909
wxDialog * mUIDialog
Definition: Effect.h:475
bool mUIDebug
Definition: Effect.h:519
void SetName(const wxString &n)
Definition: Track.h:370
int mCurrentProcessor
Definition: Effect.h:537
static const int kEnableID
Definition: Effect.cpp:86
bool mInitialized
Definition: Effect.h:653
void MixAndRender(TrackList *tracks, TrackFactory *trackFactory, double rate, sampleFormat format, double startTime, double endTime, WaveTrack::Holder &uLeft, WaveTrack::Holder &uRight)
Mixes together all input tracks, applying any envelopes, amplitude gain, panning, and real-time effec...
Definition: Mix.cpp:44
void reinit(Integral count)
Definition: MemoryX.h:162
const wxChar * name
Definition: Distortion.cpp:94
bool Validate() override
Definition: Effect.cpp:2706
wxButton * mFFwdBtn
Definition: Effect.h:663
virtual IdentInterfaceSymbol GetVendor()=0
wxListBox * AddListBox(const wxArrayString *pChoices, long style=0)
Definition: ShuttleGui.cpp:654
int ShowModal() override
Definition: Effect.cpp:2922
static const int kSaveAsID
Definition: Effect.cpp:78
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: WaveTrack.cpp:1858
bool mDisableTransport
Definition: Effect.h:676
virtual bool DefineParams(ShuttleParams &WXUNUSED(S))
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:312
wxArrayString mUserPresets
Definition: Effect.h:711
bool TransferDataToWindow() override
Definition: Effect.cpp:2690
const wxString & Internal() const
virtual bool RealtimeResume()=0
bool ShowInterface(wxWindow *parent, bool forceModal=false) override
Definition: Effect.cpp:517
sampleFormat GetSampleFormat() const
Definition: WaveTrack.h:150
bool RemovePrivateConfigSubgroup(const PluginID &ID, const wxString &group) override
Memory.h template class for making an array of float, bool, etc.
Definition: MemoryX.h:82
bool LoadFactoryDefaults() override
Definition: Effect.cpp:639
virtual int GetPass()
Definition: Effect.cpp:1297
Shuttle that sets parameters to a value (from a string)
Definition: Shuttle.h:105
static const wxString kFactoryPresetIdent
Definition: Effect.h:543
virtual NumericFormatId GetSelectionFormat()
Definition: Effect.cpp:740
bool RemoveSharedConfigSubgroup(const wxString &group) override
Definition: Effect.cpp:881
bool GetPrivateConfigSubgroups(const PluginID &ID, const wxString &group, wxArrayString &subgroups) override
EffectClientInterface provides the ident interface to Effect, and is what makes Effect into a plug-in...
virtual bool TransferDataFromWindow()
wxButton * mPlayBtn
Definition: Effect.h:661
bool SupportsAutomation() override
Definition: Effect.cpp:263
NumericFormatId mDurationFormat
Definition: Effect.h:515
bool mIsGUI
Definition: Effect.h:655
static const wxString kCurrentSettingsIdent
Definition: Effect.h:544
wxDialog * CreateUI(wxWindow *parent, EffectUIClientInterface *client) override
Definition: Effect.cpp:780
SelectedRegion * mpSelectedRegion
Definition: Effect.h:460
const NumericFormatId & GetSelectionFormat() const
Definition: Project.cpp:1691
bool SupportsRealtime() override
Definition: Effect.cpp:253
wxBitmap mPlayBM
Definition: Effect.h:669
bool TrackGroupProgress(int whichGroup, double frac, const wxString &=wxEmptyString)
Definition: Effect.cpp:2003
double f1() const
double mDuration
Definition: Effect.h:514
virtual bool IsBatchProcessing()
Definition: Effect.cpp:1142
bool RemovePrivateConfig(const PluginID &ID, const wxString &group, const wxString &key) override
bool CloseUI() override
Definition: Effect.cpp:685
virtual void SetSampleRate(double rate)=0
bool GetSharedConfig(const PluginID &ID, const wxString &group, const wxString &key, wxString &value, const wxString &defval=_T("")) override
virtual bool LoadFactoryPreset(int id)=0
sampleCount mSampleCnt
Definition: Effect.h:479
virtual unsigned GetAudioOutCount()=0
bool Initialize()
Definition: Effect.cpp:2951
std::unique_ptr< T, Destroyer< T >> Destroy_ptr
Definition: MemoryX.h:352
void OnType(wxCommandEvent &evt)
Definition: Effect.cpp:4100
virtual void OnPreview(wxCommandEvent &evt)
Definition: Effect.cpp:2711
bool HideUI() override
Definition: Effect.cpp:680
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxButton *extra=NULL)
static NumericFormatId DefaultSelectionFormat()
static bool MayCapture(wxDialog *pDlg)
double GetRate() const
Definition: Project.h:199
void RealtimeAddEffect(Effect *effect)
virtual bool IsInteractive()=0
void OnDefaults(wxCommandEvent &evt)
Definition: Effect.cpp:3732
bool IsAvailable(AudacityProject *projecT) const
Function to automatically set an acceptable volume.
Definition: AudioIO.cpp:2367
unsigned GetAudioOutCount() override
Definition: Effect.cpp:295
END_EVENT_TABLE()
double GetRate() const
Definition: WaveTrack.cpp:401
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumCopied=nullptr) const
Definition: WaveTrack.cpp:1986
double mF1
Definition: Effect.h:468
double GetSel1() const
Definition: Project.h:205
bool GetPrivateConfig(const PluginID &ID, const wxString &group, const wxString &key, wxString &value, const wxString &defval=_T("")) override
size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen) override
Definition: Effect.cpp:397
virtual void OnOk(wxCommandEvent &evt)
Definition: Effect.cpp:2716
static const int kOptionsID
Definition: Effect.cpp:82
void GetPlayRegion(double *playRegionStart, double *playRegionEnd)
Definition: Project.cpp:5337
static PluginManager & Get()
std::unique_ptr< LabelTrack > NewLabelTrack()
Definition: LabelTrack.cpp:100
bool mIsBatch
Definition: Effect.h:508
bool IsPlayRegionLocked()
Definition: Project.h:211
virtual bool TransferDataToWindow()
Effect * mEffect
Definition: Effect.h:648
double duration() const
virtual wxString GetPath()=0
std::enable_if< std::is_pointer< T >::value, T >::type track_cast(Track *track)
Definition: Track.h:789
bool Delegate(Effect &delegate, wxWindow *parent, bool shouldPrompt)
Definition: Effect.cpp:1279
wxBitmap mStopDisabledBM
Definition: Effect.h:672
EffectDistortion::Params params
Definition: Distortion.cpp:95
virtual size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen)=0
void SetBorder(int Border)
Definition: ShuttleGui.h:286
virtual bool PromptUser(wxWindow *parent)
Definition: Effect.cpp:1292
virtual bool SetAutomationParameters(CommandParameters &parms)=0
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1305
void SeekStream(double seconds)
Move the playback / recording position of the current stream by the specified amount from where it is...
Definition: AudioIO.h:839
void SetHostUI(EffectUIHostInterface *host) override
Definition: Effect.cpp:651
void EndTwoColumn()
Definition: ShuttleGui.h:137
bool mEnabled
Definition: Effect.h:674
virtual wxString GetSavedStateGroup()
Definition: Effect.cpp:815
virtual void PopulateOrExchange(ShuttleGui &S)
Definition: Effect.cpp:1881
bool AcceptsFocusFromKeyboard() const override
Definition: Effect.cpp:2764
static const int UndefinedFrequency
int mUIResultID
Definition: Effect.h:477
void OnSaveAs(wxCommandEvent &evt)
Definition: Effect.cpp:3632
std::shared_ptr< TrackList > mOutputTracks
Definition: Effect.h:463
virtual bool LoadUserPreset(const wxString &name)=0
virtual bool CheckWhetherSkipEffect()
Definition: Effect.h:299
virtual ~EffectUIHost()
Definition: Effect.cpp:2882
wxCheckBox * mEnableCb
Definition: Effect.h:664
virtual wxArrayString GetUserPresets()
Definition: Effect.cpp:1094
void SetForValidating(CommandParameters *pEap)
Definition: Shuttle.h:113
virtual void SetHostUI(EffectUIHostInterface *host)=0
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:203
virtual bool EnableApply(bool enable=true)
Definition: Effect.cpp:1896
wxString GetFactoryDefaultsGroup() override
Definition: Effect.cpp:810
void Resume()
Definition: Effect.cpp:3424
double mT0
Definition: Effect.h:464
wxString GetPath() override
Definition: Effect.cpp:161
EffectUIHostInterface has nothing in it. It is provided so that an Effect can call SetHostUI passing ...
virtual bool Startup()
Definition: Effect.cpp:1001
virtual bool EnablePreview(bool enable=true)
Definition: Effect.cpp:1927
bool HasOptions() override
Definition: Effect.cpp:709
int mNumGroups
Definition: Effect.h:525
static const wxString kFactoryDefaultsIdent
Definition: Effect.h:545
virtual wxString HelpPage()
Definition: Effect.cpp:1137
virtual bool CloseUI()=0
MenuCommandHandler & GetMenuCommandHandler(AudacityProject &project)
Definition: Menus.cpp:152
virtual size_t RealtimeProcess(int group, float **inBuf, float **outBuf, size_t numSamples)=0
virtual bool ProcessFinalize()=0
void StartVerticalLay(int iProp=1)