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