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