Audacity 3.2.0
EffectUI.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 EffectUI.cpp
6
7 Leland Lucius
8
9 Audacity(R) is copyright (c) 1999-2008 Audacity Team.
10 License: GPL v2 or later. See License.txt.
11
12**********************************************************************/
13#include "EffectUI.h"
14#include "Effect.h"
16#include "EffectEditor.h"
17#include "EffectPreview.h"
18
19#include "AllThemeResources.h"
20#include "widgets/BasicMenu.h"
21#include "BasicUI.h"
22#include "ConfigInterface.h"
23#include "EffectManager.h"
24#include "PluginManager.h"
25#include "ProjectAudioIO.h"
26#include "ProjectHistory.h"
27#include "../ProjectWindowBase.h"
28#include "../TrackPanelAx.h"
29#include "RealtimeEffectList.h"
31#include "RealtimeEffectState.h"
32#include "Theme.h"
34
36{
37 return PluginManager::GetID(&effect.GetDefinition());
38}
39
41//
42// EffectPanel
43//
45
46class EffectPanel final : public wxPanelWrapper
47{
48public:
49 EffectPanel(wxWindow *parent)
50 : wxPanelWrapper(parent)
51 {
52 // This fools NVDA into not saying "Panel" when the dialog gets focus
55
56 mAcceptsFocus = true;
57 }
58
59 virtual ~EffectPanel()
60 {
61 }
62
63 // ============================================================================
64 // wxWindow implementation
65 // ============================================================================
66
67 bool AcceptsFocus() const override
68 {
69 return mAcceptsFocus;
70 }
71
72 // So that wxPanel is not included in Tab traversal, when required - see wxWidgets bug 15581
73 bool AcceptsFocusFromKeyboard() const override
74 {
75 return mAcceptsFocus;
76 }
77
78 // ============================================================================
79 // EffectPanel implementation
80 // ============================================================================
81 void SetAccept(bool accept)
82 {
83 mAcceptsFocus = accept;
84 }
85
86private:
88};
89
91//
92// EffectUIHost
93//
95
96#include "../../images/Effect.h"
97#include "AudioIO.h"
98#include "../CommonCommandFlags.h"
99#include "../Menus.h"
100#include "../prefs/GUISettings.h" // for RTL_WORKAROUND
101#include "Project.h"
102#include "../ProjectAudioManager.h"
103#include "ShuttleGui.h"
104#include "ViewInfo.h"
105#include "../commands/AudacityCommand.h"
106#include "../commands/CommandContext.h"
107#include "AudacityMessageBox.h"
108#include "HelpSystem.h"
109#include "../widgets/AButton.h"
110
111#include <wx/button.h>
112#include <wx/checkbox.h>
113#include <wx/dcclient.h>
114#include <wx/dcmemory.h>
115#include <wx/menu.h>
116#include <wx/settings.h>
117#include <wx/sizer.h>
118#include <wx/textctrl.h>
119
120static const int kDummyID = 20000;
121static const int kSaveAsID = 20001;
122static const int kImportID = 20002;
123static const int kExportID = 20003;
124static const int kDefaultsID = 20004;
125static const int kOptionsID = 20005;
126static const int kUserPresetsDummyID = 20006;
127static const int kDeletePresetDummyID = 20007;
128static const int kMenuID = 20100;
129static const int kEnableID = 20101;
131static const int kPlaybackID = 20105;
132static const int kCaptureID = 20106;
133static const int kUserPresetsID = 21000;
134static const int kDeletePresetID = 22000;
135static const int kFactoryPresetsID = 23000;
136
137BEGIN_EVENT_TABLE(EffectUIHost, wxDialogWrapper)
138EVT_INIT_DIALOG(EffectUIHost::OnInitDialog)
139EVT_ERASE_BACKGROUND(EffectUIHost::OnErase)
140EVT_PAINT(EffectUIHost::OnPaint)
141EVT_CLOSE(EffectUIHost::OnClose)
156EVT_IDLE(EffectUIHost::OnIdle)
157EVT_CHAR_HOOK(EffectUIHost::OnCharHook)
159
160namespace {
163
165public:
167 const std::shared_ptr<EffectSettingsAccess> &pSide = {});
168 const EffectSettings &Get() override;
170 std::unique_ptr<Message> pMessage) override;
171 void Set(std::unique_ptr<Message> pMessage) override;
172 void Flush() override;
173 bool IsSameAs(const EffectSettingsAccess &other) const override;
174private:
176 const std::shared_ptr<EffectSettingsAccess> mpMain;
177 const std::weak_ptr<EffectSettingsAccess> mwSide;
178};
179}
180
181EffectSettingsAccessTee::EffectSettingsAccessTee(
183 const std::shared_ptr<EffectSettingsAccess> &pSide
184) : mpMain{ main.shared_from_this() }
185 , mwSide{ pSide }
186{
187}
188
190 return mpMain->Get();
191}
192
194 std::unique_ptr<Message> pMessage)
195{
196 // Move copies of the given settings and message into the side
197 if (auto pSide = mwSide.lock())
198 pSide->Set(EffectSettings{ settings },
199 pMessage ? pMessage->Clone() : nullptr);
200 // Move the given settings and message through
201 mpMain->Set(std::move(settings), std::move(pMessage));
202}
203
204void EffectSettingsAccessTee::Set(std::unique_ptr<Message> pMessage)
205{
206 // Move copies of the given message into the side
207 if (auto pSide = mwSide.lock())
208 pSide->Set(pMessage ? pMessage->Clone() : nullptr);
209 // Move the given message through
210 mpMain->Set(std::move(pMessage));
211}
212
214{
215 mpMain->Flush();
216 if (auto pSide = mwSide.lock())
217 pSide->Flush();
218}
219
221 const EffectSettingsAccess &other) const
222{
223 return mpMain->IsSameAs(other);
224}
225
228 EffectUIServices &client, std::shared_ptr<EffectInstance> &pInstance,
229 EffectSettingsAccess &access,
230 const std::shared_ptr<RealtimeEffectState> &pPriorState)
231: wxDialogWrapper(parent, wxID_ANY, effect.GetDefinition().GetName(),
232 wxDefaultPosition, wxDefaultSize,
233 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX)
234, mEffectUIHost{ effect }
235, mClient{ client }
236// Grab a pointer to the access object,
237// extending its lifetime while this remains:
238, mpGivenAccess{ access.shared_from_this() }
239, mpAccess{ mpGivenAccess }
240, mwState{ pPriorState }
241, mProject{ project }
242, mParent{ parent }
243, mSupportsRealtime{ mEffectUIHost.GetDefinition().SupportsRealtime() }
244, mHadPriorState{ (pPriorState != nullptr) }
245, mpInstance{ InitializeInstance() }
246, mpOutputs{ pPriorState ? pPriorState->GetOutputs() : nullptr }
247{
248 // Assign the out parameter
249 pInstance = mpInstance;
250#if defined(__WXMAC__)
251 MacMakeWindowFloating(GetHandle());
252#endif
253
254 SetName( effect.GetDefinition().GetName() );
255
256 // This style causes Validate() and TransferDataFromWindow() to visit
257 // sub-windows recursively, applying any wxValidators
258 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
259}
260
262{
263 if (mpEditor)
264 mpEditor->Disconnect();
265 DestroyChildren();
266 wxASSERT(mClosed);
267}
268
269// ============================================================================
270// wxWindow implementation
271// ============================================================================
272
274{
275 // Transfer-to takes const reference to settings
276 const auto pServices =
278 return (!pServices || pServices->TransferDataToWindow(mpAccess->Get())) &&
280 mpEditor->UpdateUI() &&
282 wxDialogWrapper::TransferDataToWindow();
283}
284
286{
288 if (!wxDialogWrapper::Validate())
289 return false;
290
292 if (!wxDialogWrapper::TransferDataFromWindow())
293 return false;
294
296 if (!mpEditor->ValidateUI())
297 return false;
298
299 // Transfer-from takes non-const reference to settings
300 bool result = true;
301 mpAccess->ModifySettings([&](EffectSettings &settings){
302 const auto pServices =
304 // Allow other transfers, and reassignment of settings
305 result = (!pServices || pServices->TransferDataFromWindow(settings));
306 if (result) {
307 auto &definition = mEffectUIHost.GetDefinition();
308 if (definition.GetType() == EffectTypeGenerate) {
309 const auto seconds = settings.extra.GetDuration();
310 // Updating of the last-used generator duration in the config
313 seconds);
314 }
315 }
316 return nullptr;
317 });
318 mpAccess->Flush();
319 return result;
320}
321
322// ============================================================================
323// wxDialog implementation
324// ============================================================================
325
327{
329 {
330 mApplyBtn->SetLabel(XXO("&Generate").Translation());
331 }
332
333 Layout();
334
335 return wxDialogWrapper::ShowModal();
336}
337
338// ============================================================================
339// EffectUIHost implementation
340// ============================================================================
341
342namespace {
344 const wxImage& ImageOn, const wxImage& ImageOff)
345{
346 auto pBtn = safenew AButton(parent, kEnableID,
347 wxDefaultPosition, wxDefaultSize, true);
348 pBtn->SetImages(ImageOff, ImageOff, ImageOn, ImageOn, ImageOff);
349 return pBtn;
350}
351}
352
354{
355 mIsGUI = graphicalUI;
357
358 constexpr int margin = 3;
359
360 S.StartPanel();
361 {
362 S.SetBorder( margin );
363
364 S.StartHorizontalLay(wxEXPAND, 0);
365 {
367 {
368 mEnableBtn = MakeBitmapToggleButton(S.GetParent(),
369 theTheme.Image(bmpEffectOn), theTheme.Image(bmpEffectOff));
370 S
371 .Position(wxALIGN_CENTER | wxTOP | wxBOTTOM)
372 .Name(XO("Power"))
373 .AddWindow(mEnableBtn);
374 }
375
376 mMenuBtn = S.Id( kMenuID )
377 .ToolTip(XO("Manage presets and options"))
378 .AddButton( XO("Presets && settings"), wxALIGN_CENTER | wxTOP | wxBOTTOM );
379
380 S.AddSpace(1, 0, 1);
381
382 if (!mIsBatch)
383 {
387 {
389 .ToolTip(XO("Preview effect"))
390 .AddButton( { },
391 wxALIGN_CENTER | wxTOP | wxBOTTOM );
392 }
393 if(mPlayToggleBtn != nullptr)
394 {
395 //wxButton does not implement GetSizeFromText
396 //set button minimum size so that largest text fits
397 mPlayToggleBtn->SetLabel(_("Stop &Preview"));
398 auto a = mPlayToggleBtn->GetBestSize();
399 mPlayToggleBtn->SetLabel(_("&Preview"));
400 auto b = mPlayToggleBtn->GetBestSize();
401 mPlayToggleBtn->SetMinSize(a.x > b.x ? a : b);
402 }
403 }
404
406 {
407 mApplyBtn = S.Id(wxID_APPLY)
408 .AddButton( XXO("&Apply"),
409 wxALIGN_CENTER | wxTOP | wxBOTTOM );
410 mApplyBtn->SetDefault();
411 }
412
414 {
415 mDebugBtn = S.Id(eDebugID)
416 .AddButton( XXO("Debu&g"),
417 wxALIGN_CENTER | wxTOP | wxBOTTOM );
418 }
419 }
420 S.EndHorizontalLay();
421 }
422 S.EndPanel();
423}
424
426{
427 mEnabled = mpAccess->Get().extra.GetActive();
428
429 // Build a "host" dialog, framing a panel that the client fills in.
430 // The frame includes buttons to preview, apply, load and save presets, etc.
431 EffectPanel *w {};
432 ShuttleGui S{ this, eIsCreating };
433 {
434 // Make the panel for the client
435 Destroy_ptr<EffectPanel> uw{ safenew EffectPanel( S.GetParent() ) };
436 RTL_WORKAROUND(uw.get());
437
438 // Try to give the window a sensible default/minimum size
439 uw->SetMinSize(wxSize(wxMax(600, mParent->GetSize().GetWidth() * 2 / 3),
440 mParent->GetSize().GetHeight() / 2));
441
442 // Let the client add things to the panel
443 ShuttleGui S1{ uw.get(), eIsCreating };
446 if (!mpEditor)
447 return false;
448
449 BuildButtonBar(S, mpEditor->IsGraphicalUI());
450
451 S.StartHorizontalLay( wxEXPAND );
452 {
453 S.Prop( 1 )
454 .Position(wxEXPAND)
455 .AddWindow((w = uw.release()));
456 }
457 S.EndHorizontalLay();
458 }
459
460 Layout();
461 Fit();
462 Center();
463
465
466 w->SetAccept(!mIsGUI);
467
468 if (!mIsGUI)
469 {
470 w->SetFocus();
471 }
472 else if (!IsOpenedFromEffectPanel())
473 {
474 mApplyBtn->SetFocus();
475 }
476
478
479 SetMinSize(GetSize());
480 return true;
481}
482
484{
485 return !IsModal();
486}
487
488
489void EffectUIHost::OnInitDialog(wxInitDialogEvent & evt)
490{
491 // Do default handling
492 wxDialogWrapper::OnInitDialog(evt);
493
494#if wxCHECK_VERSION(3, 0, 0)
495 //#warning "check to see if this still needed in wx3"
496#endif
497
498 // Pure hackage coming down the pike...
499 //
500 // I have no idea why, but if a wxTextCtrl is the first control in the
501 // panel, then its contents will not be automatically selected when the
502 // dialog is displayed.
503 //
504 // So, we do the selection manually.
505 wxTextCtrl *focused = wxDynamicCast(FindFocus(), wxTextCtrl);
506 if (focused)
507 {
508 focused->SelectAll();
509 }
510}
511
512void EffectUIHost::OnErase(wxEraseEvent & WXUNUSED(evt))
513{
514 // Ignore it
515}
516
517void EffectUIHost::OnPaint(wxPaintEvent & WXUNUSED(evt))
518{
519 wxPaintDC dc(this);
520
521 dc.Clear();
522}
523
524void EffectUIHost::OnClose(wxCloseEvent & WXUNUSED(evt))
525{
526 DoCancel();
528
529 if (mpEditor)
530 mpEditor->OnClose();
531
532 Hide();
533 Destroy();
534
535#if wxDEBUG_LEVEL
536 mClosed = true;
537#endif
538}
539
540void EffectUIHost::OnApply(wxCommandEvent & evt)
541{
542 auto &project = mProject;
543
544 // On wxGTK (wx2.8.12), the default action is still executed even if
545 // the button is disabled. This appears to affect all wxDialogs, not
546 // just our Effects dialogs. So, this is a only temporary workaround
547 // for legacy effects that disable the OK button. Hopefully this has
548 // been corrected in wx3.
549 if (!mApplyBtn->IsEnabled())
550 {
551 return;
552 }
553
554 // Honor the "select all if none" preference...a little hackish, but whatcha gonna do...
555 if (!mIsBatch &&
559 {
560 auto flags = AlwaysEnabledFlag;
561 bool allowed =
564 flags,
566 if (!allowed)
567 return;
568 }
569
570 if (!TransferDataFromWindow() ||
571 // This is the main place where there is a side-effect on the config
572 // file to remember the last-used settings of an effect, just before
573 // applying the effect destructively.
576 return;
577
578 if (IsModal())
579 {
580 mDismissed = true;
581
582 EndModal(evt.GetId());
583
584 Close();
585
586 return;
587 }
588
589 // Progress dialog no longer yields, so this "shouldn't" be necessary (yet to be proven
590 // for sure), but it is a nice visual cue that something is going on.
591 mApplyBtn->Disable();
592 auto cleanup = finally( [&] { mApplyBtn->Enable(); } );
593
594 CommandContext context( project );
595 // This is absolute hackage...but easy and I can't think of another way just now.
596 //
597 // It should callback to the EffectManager to kick off the processing
600}
601
603{
604 if (!mDismissed) {
605 if (!mHadPriorState) {
606 // For the destructive effect dialog only
607 // Restore effect state from last updated preferences
608 mpAccess->ModifySettings([&](EffectSettings &settings) {
609 // ignore failure
610 return mEffectUIHost.GetDefinition().LoadUserPreset(
611 CurrentSettingsGroup(), settings).value_or(nullptr);
612 });
613 }
614 if (IsModal())
615 EndModal(0);
616 else
617 Hide();
618
619 mDismissed = true;
620 }
621}
622
623void EffectUIHost::OnCancel(wxCommandEvent & WXUNUSED(evt))
624{
625 DoCancel();
626 Close();
627}
628
629void EffectUIHost::OnDebug(wxCommandEvent & evt)
630{
631 OnApply(evt);
632}
633
634namespace {
636{
637 static const auto specialVersion = XO("n/a");
638 auto result = definition.GetVersion();
639 if (result == specialVersion.MSGID())
640 result = specialVersion.Translation();
641 return result;
642}
643}
644
645void EffectUIHost::OnMenu(wxCommandEvent & WXUNUSED(evt))
646{
647 wxMenu menu;
648 menu.Bind(wxEVT_MENU, [](auto&){}, kUserPresetsDummyID);
649 menu.Bind(wxEVT_MENU, [](auto&){}, kDeletePresetDummyID);
651
652 if (mUserPresets.size() == 0)
653 {
654 menu.Append(kUserPresetsDummyID, _("User Presets"))->Enable(false);
655 }
656 else
657 {
658 auto sub = std::make_unique<wxMenu>();
659 for (size_t i = 0, cnt = mUserPresets.size(); i < cnt; i++)
660 {
661 sub->Append(kUserPresetsID + i, mUserPresets[i]);
662 }
663 menu.Append(0, _("User Presets"), sub.release());
664 }
665
666 menu.Append(kSaveAsID, _("Save Preset..."));
667
668 if (mUserPresets.size() == 0)
669 {
670 menu.Append(kDeletePresetDummyID, _("Delete Preset"))->Enable(false);
671 }
672 else
673 {
674 auto sub = std::make_unique<wxMenu>();
675 for (size_t i = 0, cnt = mUserPresets.size(); i < cnt; i++)
676 {
677 sub->Append(kDeletePresetID + i, mUserPresets[i]);
678 }
679 menu.Append(0, _("Delete Preset"), sub.release());
680 }
681
682 menu.AppendSeparator();
683
685
686 {
687 auto sub = std::make_unique<wxMenu>();
688 sub->Append(kDefaultsID, _("Defaults"));
689 if (factory.size() > 0)
690 {
691 sub->AppendSeparator();
692 for (size_t i = 0, cnt = factory.size(); i < cnt; i++)
693 {
694 auto label = factory[i];
695 if (label.empty())
696 {
697 label = _("None");
698 }
699
700 sub->Append(kFactoryPresetsID + i, label);
701 }
702 }
703 menu.Append(0, _("Factory Presets"), sub.release());
704 }
705
706 menu.AppendSeparator();
707 menu.Append(kImportID, _("Import..."))
709 menu.Append(kExportID, _("Export..."))
711 menu.AppendSeparator();
712 menu.Append(kOptionsID, _("Options..."))
713 ->Enable(mEffectUIHost.HasOptions());
714 menu.AppendSeparator();
715
716 {
717 auto sub = std::make_unique<wxMenu>();
718
719 auto &definition = mEffectUIHost.GetDefinition();
720 sub->Append(kDummyID, wxString::Format(_("Type: %s"),
721 ::wxGetTranslation( definition.GetFamily().Translation() )));
722 sub->Append(kDummyID, wxString::Format(_("Name: %s"), definition.GetName().Translation()));
723 sub->Append(kDummyID, wxString::Format(_("Version: %s"),
724 GetVersionForDisplay(definition)));
725 sub->Append(kDummyID, wxString::Format(_("Vendor: %s"), definition.GetVendor().Translation()));
726 sub->Append(kDummyID, wxString::Format(_("Description: %s"), definition.GetDescription().Translation()));
727 sub->Bind(wxEVT_MENU, [](auto&){}, kDummyID);
728
729 menu.Append(0, _("About"), sub.release());
730 }
731
732 wxWindow *btn = FindWindow(kMenuID);
733 wxRect r = btn->GetRect();
734 BasicMenu::Handle{ &menu }.Popup(
736 { r.GetLeft(), r.GetBottom() }
737 );
738}
739
740void EffectUIHost::OnEnable(wxCommandEvent & WXUNUSED(evt))
741{
743
744 auto mpState = mwState.lock();
745 if (mpState)
746 mpState->SetActive(mEnabled);
747
749}
750
751void EffectUIHost::OnPlay(wxCommandEvent & WXUNUSED(evt))
752{
754 return;
755
756 auto updater = [this]{ TransferDataToWindow(); };
758 // After restoration of settings and effect state:
759 // In case any dialog control depends on mT1 or mDuration:
760 updater();
761
762 return;
763}
764
766{
767 if (evt.on) {
768 if (evt.pProject == &mProject)
769 mCapturing = true;
770 }
771 else {
772 mCapturing = false;
773 }
775}
776
777void EffectUIHost::OnUserPreset(wxCommandEvent & evt)
778{
779 int preset = evt.GetId() - kUserPresetsID;
780
781 mpAccess->ModifySettings([&](EffectSettings &settings){
782 // ignore failure
783 return mEffectUIHost.GetDefinition().LoadUserPreset(
784 UserPresetsGroup(mUserPresets[preset]), settings).value_or(nullptr);
785 });
787 return;
788}
789
790void EffectUIHost::OnFactoryPreset(wxCommandEvent & evt)
791{
792 mpAccess->ModifySettings([&](EffectSettings &settings){
794 return mEffectUIHost.GetDefinition().LoadFactoryPreset(
795 evt.GetId() - kFactoryPresetsID, settings).value_or(nullptr);
796 });
798 return;
799}
800
801void EffectUIHost::OnDeletePreset(wxCommandEvent & evt)
802{
803 auto preset = mUserPresets[evt.GetId() - kDeletePresetID];
804
805 int res = AudacityMessageBox(
806 XO("Are you sure you want to delete \"%s\"?").Format( preset ),
807 XO("Delete Preset"),
808 wxICON_QUESTION | wxYES_NO);
809 if (res == wxYES)
810 {
813 }
814
816
817 return;
818}
819
820void EffectUIHost::OnSaveAs(wxCommandEvent & WXUNUSED(evt))
821{
822 wxTextCtrl *text;
823 wxString name;
824 wxDialogWrapper dlg(this, wxID_ANY, XO("Save Preset"));
825
826 ShuttleGui S(&dlg, eIsCreating);
827
828 S.StartPanel();
829 {
830 S.StartVerticalLay(1);
831 {
832 S.StartHorizontalLay(wxALIGN_LEFT, 0);
833 {
834 text = S.AddTextBox(XXO("Preset name:"), name, 30);
835 }
836 S.EndHorizontalLay();
837 S.SetBorder(10);
838 S.AddStandardButtons();
839 }
840 S.EndVerticalLay();
841 }
842 S.EndPanel();
843
844 dlg.SetSize(dlg.GetSizer()->GetMinSize());
845 dlg.Center();
846 dlg.Fit();
847
848 while (true)
849 {
850 int rc = dlg.ShowModal();
851
852 if (rc != wxID_OK)
853 {
854 break;
855 }
856
857 name = text->GetValue();
858 if (name.empty())
859 {
861 this,
862 XO("You must specify a name"),
863 XO("Save Preset") );
864 md.Center();
865 md.ShowModal();
866 continue;
867 }
868
869 if ( make_iterator_range( mUserPresets ).contains( name ) )
870 {
872 this,
873 XO("Preset already exists.\n\nReplace?"),
874 XO("Save Preset"),
875 wxYES_NO | wxCANCEL | wxICON_EXCLAMATION );
876 md.Center();
877 int choice = md.ShowModal();
878 if (choice == wxID_CANCEL)
879 {
880 break;
881 }
882
883 if (choice == wxID_NO)
884 {
885 continue;
886 }
887 }
888
893
894 break;
895 }
896
897 return;
898}
899
900void EffectUIHost::OnImport(wxCommandEvent & WXUNUSED(evt))
901{
902 mpAccess->ModifySettings([&](EffectSettings &settings){
903 // ignore failure
904 return mClient.ImportPresets(mEffectUIHost, settings).value_or(nullptr);
905 });
908
909 return;
910}
911
912void EffectUIHost::OnExport(wxCommandEvent & WXUNUSED(evt))
913{
914 // may throw
915 // exceptions are handled in AudacityApp::OnExceptionInMainLoop
918
919 return;
920}
921
922void EffectUIHost::OnOptions(wxCommandEvent & WXUNUSED(evt))
923{
925
926 return;
927}
928
929void EffectUIHost::OnDefaults(wxCommandEvent & WXUNUSED(evt))
930{
931 mpAccess->ModifySettings([&](EffectSettings &settings){
932 // ignore failure
933 return mEffectUIHost.GetDefinition().LoadFactoryDefaults(settings)
934 .value_or(nullptr);
935 });
937 return;
938}
939
940void EffectUIHost::OnIdle(wxIdleEvent &evt)
941{
942 evt.Skip();
943 if (mpAccess)
944 mpAccess->Flush();
945}
946
947void EffectUIHost::OnCharHook(wxKeyEvent& evt)
948{
949 if (!IsEscapeKey(evt))
950 {
951 evt.Skip();
952 return;
953 }
954
956 Close();
957 else
958 {
959 wxCommandEvent cancelEvt { wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL };
960
961 OnCancel(cancelEvt);
962 }
963}
964
966{
967 return (mpTempProjectState == nullptr && mSupportsRealtime);
968}
969
970wxBitmap EffectUIHost::CreateBitmap(const char * const xpm[], bool up, bool pusher)
971{
972 wxMemoryDC dc;
973 wxBitmap pic(xpm);
974
975 wxBitmap mod(pic.GetWidth() + 6, pic.GetHeight() + 6, 24);
976 dc.SelectObject(mod);
977
978#if defined(__WXGTK__)
979 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND);
980#else
981 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
982#endif
983
984 dc.SetBackground(wxBrush(newColour));
985 dc.Clear();
986
987 int offset = 3;
988 if (pusher)
989 {
990 if (!up)
991 {
992 offset += 1;
993 }
994 }
995
996 dc.DrawBitmap(pic, offset, offset, true);
997
998 dc.SelectObject(wxNullBitmap);
999
1000 return mod;
1001}
1002
1004{
1005 if (mIsBatch)
1006 {
1007 return;
1008 }
1009
1011 {
1013 return;
1014 }
1015
1016 mApplyBtn->Enable(!mCapturing);
1017}
1018
1020{
1021 mUserPresets.clear();
1022
1025
1026 std::sort( mUserPresets.begin(), mUserPresets.end() );
1027
1028 return;
1029}
1030
1031std::shared_ptr<EffectInstance> EffectUIHost::InitializeInstance()
1032{
1033 // We are still constructing and the return initializes a const member
1034 std::shared_ptr<EffectInstance> result;
1035
1036 auto mpState = mwState.lock();
1037
1038 bool priorState = (mpState != nullptr);
1039 if (!priorState) {
1040 auto gAudioIO = AudioIO::Get();
1041 mCapturing = gAudioIO->IsStreamActive() && gAudioIO->GetNumCaptureChannels() > 0 && !gAudioIO->IsMonitoring();
1042 }
1043
1045 if (!priorState)
1046 mwState = mpState = mpTempProjectState =
1048 if (mpState) {
1049 // Find the right instance to connect to the dialog
1050 if (!result)
1051 result = mpState->GetInstance();
1052
1053 mpAccess2 = mpState->GetAccess();
1054 if (!(mpAccess2->IsSameAs(*mpAccess)))
1055 // Decorate the given access object
1056 mpAccess = std::make_shared<EffectSettingsAccessTee>(
1058
1059 mEffectStateSubscription = mpState->Subscribe([this](RealtimeEffectStateChange state) {
1062 });
1063 }
1064
1065 if (!priorState) {
1067 switch (event.type) {
1068 case AudioIOEvent::CAPTURE:
1069 OnCapture(event); break;
1070 default:
1071 break;
1072 }
1073 });
1074 }
1075
1076 mInitialized = true;
1077 }
1078 else
1079 result = EffectBase::FindInstance(mEffectUIHost).value_or(nullptr);
1080
1081 return result;
1082}
1083
1085{
1087
1089 if (!IsOpenedFromEffectPanel()) {
1092 mpTempProjectState.reset();
1093 /*
1094 ProjectHistory::Get(mProject).PushState(
1095 XO("Removed %s effect").Format(mpState->GetEffect()->GetName()),
1096 XO("Removed Effect"),
1097 UndoPush::NONE
1098 );
1099 */
1100 }
1101 mInitialized = false;
1102 }
1103}
1104
1106 EffectBase &host, EffectUIServices &client,
1107 EffectSettingsAccess &access)
1108{
1109 // Make sure there is an associated project, whose lifetime will
1110 // govern the lifetime of the dialog, even when the dialog is
1111 // non-modal, as for realtime effects
1112 auto project = FindProjectFromWindow(&parent);
1113 if ( !project )
1114 return {};
1115 std::shared_ptr<EffectInstance> pInstance;
1117 *project, host, client, pInstance, access } };
1118 if (!pInstance) {
1119 dlg->SetClosed();
1120 return {};
1121 }
1122 if (dlg->Initialize()) {
1123 auto pEditor = dlg->GetEditor();
1124 // release() is safe because parent will own it
1125 return { dlg.release(), pInstance, pEditor };
1126 }
1127 return {};
1128}
1129
1130#include "PluginManager.h"
1131#include "ProjectRate.h"
1132#include "../ProjectWindow.h"
1133#include "../SelectUtilities.h"
1134#include "../TrackPanel.h"
1135#include "WaveTrack.h"
1136#include "../commands/CommandManager.h"
1137
1141// parameters, whether to save the state to history and whether to allow
1143
1144/* static */ bool EffectUI::DoEffect(
1145 const PluginID & ID, const CommandContext &context, unsigned flags )
1146{
1147 AudacityProject &project = context.project;
1148 auto &tracks = TrackList::Get( project );
1149 auto &trackPanel = TrackPanel::Get( project );
1150 auto &trackFactory = WaveTrackFactory::Get( project );
1151 auto rate = ProjectRate::Get(project).GetRate();
1152 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
1153 auto &commandManager = CommandManager::Get( project );
1154 auto &window = ProjectWindow::Get( project );
1155
1156 const PluginDescriptor *plug = PluginManager::Get().GetPlugin(ID);
1157
1158 if (!plug || !PluginManager::IsPluginAvailable(*plug))
1159 {
1161 XO("This plugin could not be loaded.\nIt may have been deleted."),
1163 .Caption(XO("Plugin Error")));
1164
1165 return false;
1166 }
1167
1168 EffectType type = plug->GetEffectType();
1169
1170 // Make sure there's no activity since the effect is about to be applied
1171 // to the project's tracks. Mainly for Apply during RTP, but also used
1172 // for batch commands
1173 if (flags & EffectManager::kConfigured)
1174 {
1176 //Don't Select All if repeating Generator Effect
1177 if (!(flags & EffectManager::kConfigured)) {
1179 }
1180 }
1181
1182 auto nTracksOriginally = tracks.Size();
1183 wxWindow *focus = wxWindow::FindFocus();
1184 wxWindow *parent = nullptr;
1185 if (focus != nullptr) {
1186 parent = focus->GetParent();
1187 }
1188
1189 bool success = false;
1190 auto cleanup = finally( [&] {
1191
1192 if (!success) {
1193 // For now, we're limiting realtime preview to a single effect, so
1194 // make sure the menus reflect that fact that one may have just been
1195 // opened.
1197 }
1198
1199 } );
1200
1201 const auto range = tracks.Selected<const WaveTrack>();
1202 bool anyTracks = !range.empty();
1203 bool clean = std::all_of(range.begin(), range.end(),
1204 [](const WaveTrack *t){ return t->GetEndTime() == 0; });
1205
1207
1208 em.SetSkipStateFlag( false );
1209 success = false;
1210 if (auto effect = dynamic_cast<Effect*>(em.GetEffect(ID))) {
1211 if (const auto pSettings = em.GetDefaultSettings(ID)) {
1212 const auto pAccess =
1213 std::make_shared<SimpleEffectSettingsAccess>(*pSettings);
1214 const auto finder =
1215 [effect, &window, pAccess, flags] (EffectSettings &settings)
1216 -> std::optional<std::shared_ptr<EffectInstanceEx>>
1217 {
1218 // Prompting will be bypassed when applying an effect that has
1219 // already been configured, e.g. repeating the last effect on a
1220 // different selection. Prompting may call EffectPreview
1221 std::shared_ptr<EffectInstance> pInstance;
1222 std::shared_ptr<EffectInstanceEx> pInstanceEx;
1223 if ((flags & EffectManager::kConfigured) == 0 && pAccess) {
1224 const auto pServices = dynamic_cast<EffectUIServices *>(effect);
1225 if (!pServices ||
1226 !pServices->ShowHostInterface(*effect,
1227 window, DialogFactory, pInstance, *pAccess, true)
1228 )
1229 return {};
1230 else if (!(pInstanceEx =
1231 std::dynamic_pointer_cast<EffectInstanceEx>(pInstance)
1232 ))
1233 return {};
1234 else
1235 // Retrieve again after the dialog modified settings
1236 settings = pAccess->Get();
1237 }
1238 return { pInstanceEx };
1239 };
1240 pAccess->ModifySettings([&](EffectSettings &settings){
1241 success = effect->DoEffect(settings, finder,
1242 rate,
1243 &tracks,
1244 &trackFactory,
1245 selectedRegion,
1246 flags,
1247 pAccess);
1248 return nullptr;
1249 });
1250 }
1251 }
1252
1253 if (!success)
1254 return false;
1255
1256 if (em.GetSkipStateFlag())
1257 flags = flags | EffectManager::kSkipState;
1258
1259 if (!(flags & EffectManager::kSkipState))
1260 {
1261 auto shortDesc = em.GetCommandName(ID);
1262 auto longDesc = em.GetCommandDescription(ID);
1263 ProjectHistory::Get( project ).PushState(longDesc, shortDesc);
1264 }
1265
1266 if (!(flags & EffectManager::kDontRepeatLast))
1267 {
1268 // Remember a successful generator, effect, analyzer, or tool Process
1269 auto shortDesc = em.GetCommandName(ID);
1270 /* i18n-hint: %s will be the name of the effect which will be
1271 * repeated if this menu item is chosen */
1272 auto lastEffectDesc = XO("Repeat %s").Format(shortDesc);
1273 auto& menuManager = MenuManager::Get(project);
1274 switch ( type ) {
1275 case EffectTypeGenerate:
1276 commandManager.Modify(wxT("RepeatLastGenerator"), lastEffectDesc);
1277 menuManager.mLastGenerator = ID;
1278 menuManager.mRepeatGeneratorFlags = EffectManager::kConfigured;
1279 break;
1280 case EffectTypeProcess:
1281 commandManager.Modify(wxT("RepeatLastEffect"), lastEffectDesc);
1282 menuManager.mLastEffect = ID;
1283 menuManager.mRepeatEffectFlags = EffectManager::kConfigured;
1284 break;
1285 case EffectTypeAnalyze:
1286 commandManager.Modify(wxT("RepeatLastAnalyzer"), lastEffectDesc);
1287 menuManager.mLastAnalyzer = ID;
1288 menuManager.mLastAnalyzerRegistration = MenuCreator::repeattypeplugin;
1289 menuManager.mRepeatAnalyzerFlags = EffectManager::kConfigured;
1290 break;
1291 case EffectTypeTool:
1292 commandManager.Modify(wxT("RepeatLastTool"), lastEffectDesc);
1293 menuManager.mLastTool = ID;
1294 menuManager.mLastToolRegistration = MenuCreator::repeattypeplugin;
1295 menuManager.mRepeatToolFlags = EffectManager::kConfigured;
1296 if (shortDesc == NYQUIST_PROMPT_NAME) {
1297 menuManager.mRepeatToolFlags = EffectManager::kRepeatNyquistPrompt; //Nyquist Prompt is not configured
1298 }
1299 break;
1300 }
1301 }
1302
1303 //STM:
1304 //The following automatically re-zooms after sound was generated.
1305 // IMO, it was disorienting, removing to try out without re-fitting
1306 //mchinen:12/14/08 reapplying for generate effects
1307 if (type == EffectTypeGenerate)
1308 {
1309 if (!anyTracks || (clean && selectedRegion.t0() == 0.0))
1310 window.DoZoomFit();
1311 // trackPanel->Refresh(false);
1312 }
1313
1314 // PRL: RedrawProject explicitly because sometimes history push is skipped
1315 window.RedrawProject();
1316
1317 if (focus != nullptr && focus->GetParent()==parent) {
1318 focus->SetFocus();
1319 }
1320
1321 // A fix for Bug 63
1322 // New tracks added? Scroll them into view so that user sees them.
1323 // Don't care what track type. An analyser might just have added a
1324 // Label track and we want to see it.
1325 if (tracks.Size() > nTracksOriginally) {
1326 // 0.0 is min scroll position, 1.0 is max scroll position.
1327 trackPanel.VerticalScroll( 1.0 );
1328 }
1329 else {
1330 auto pTrack = *tracks.Selected().begin();
1331 if (!pTrack)
1332 pTrack = *tracks.begin();
1333 if (pTrack) {
1334 TrackFocus::Get(project).Set(pTrack);
1335 pTrack->EnsureVisible();
1336 }
1337 }
1338
1339 return true;
1340}
1341
1343BEGIN_EVENT_TABLE(EffectDialog, wxDialogWrapper)
1346
1347EffectDialog::EffectDialog(wxWindow * parent,
1348 const TranslatableString & title,
1349 int type,
1350 int flags,
1351 int additionalButtons)
1352: wxDialogWrapper(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, flags)
1353{
1354 mType = type;
1355 mAdditionalButtons = additionalButtons;
1356}
1357
1359{
1360 long buttons = eOkButton;
1362 {
1363 buttons |= eCancelButton;
1364 if (mType == EffectTypeProcess)
1365 {
1366 buttons |= ePreviewButton;
1367 }
1368 }
1369
1370 ShuttleGui S(this, eIsCreating);
1371
1372 S.SetBorder(5);
1373 S.StartVerticalLay(true);
1374 {
1376 S.AddStandardButtons(buttons|mAdditionalButtons);
1377 }
1378 S.EndVerticalLay();
1379
1380 Layout();
1381 Fit();
1382 SetMinSize(GetSize());
1383 Center();
1384}
1385
1390{
1391 return;
1392}
1393
1395{
1398
1399 return true;
1400}
1401
1403{
1406
1407 return true;
1408}
1409
1411{
1412 return true;
1413}
1414
1415void EffectDialog::OnPreview(wxCommandEvent & WXUNUSED(evt))
1416{
1417 return;
1418}
1419
1420void EffectDialog::OnOk(wxCommandEvent & WXUNUSED(evt))
1421{
1422 // On wxGTK (wx2.8.12), the default action is still executed even if
1423 // the button is disabled. This appears to affect all wxDialogs, not
1424 // just our Effects dialogs. So, this is a only temporary workaround
1425 // for legacy effects that disable the OK button. Hopefully this has
1426 // been corrected in wx3.
1427 if (FindWindow(wxID_OK)->IsEnabled() && Validate() && TransferDataFromWindow())
1428 {
1429 EndModal(wxID_OK);
1430 }
1431
1432 return;
1433}
1434
1436#include "RealtimeEffectState.h"
EVT_MENU(OnSetPlayRegionToSelectionID, AdornedRulerPanel::OnSetPlayRegionToSelection) EVT_COMMAND(OnTogglePinnedStateID
wxEVT_COMMAND_BUTTON_CLICKED
wxImage(22, 22)
wxT("CloseDown"))
int main(int argc, char *argv[])
EVT_MENU_RANGE(FileHistory::ID_RECENT_FIRST, FileHistory::ID_RECENT_LAST, AudacityApp::OnMRUFile) bool AudacityApp
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Abstractions of menus and their items.
Toolkit-neutral facade for basic user interface services.
END_EVENT_TABLE()
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:34
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
Definition: Distortion.cpp:76
RegistryPath UserPresetsGroup(const RegistryPath &name)
Compute part of a registry path, given a name which may be empty.
const RegistryPath & CurrentSettingsGroup()
Component of a configuration key path, for last-used destructive settings.
EffectType
@ EffectTypeAnalyze
@ EffectTypeGenerate
@ EffectTypeTool
@ EffectTypeProcess
wxString PluginID
Definition: EffectManager.h:30
void EffectPreview(EffectBase &effect, EffectSettingsAccess &access, std::function< void()> updateUI, bool dryOnly)
Calculate temporary tracks of limited length with effect applied and play.
static PluginID GetID(EffectPlugin &effect)
Definition: EffectUI.cpp:35
static const int kImportID
Definition: EffectUI.cpp:122
static const int kExportID
Definition: EffectUI.cpp:123
static const int kOptionsID
Definition: EffectUI.cpp:125
static const int kCaptureID
Definition: EffectUI.cpp:132
static RealtimeEffectState::EffectFactory::Scope scope
Inject a factory for realtime effects.
Definition: EffectUI.cpp:1438
static const int kDefaultsID
Definition: EffectUI.cpp:124
static const int kDummyID
Definition: EffectUI.cpp:120
static const int kPlaybackID
Definition: EffectUI.cpp:131
static const int kPlayID
Definition: EffectUI.cpp:130
static const int kSaveAsID
Definition: EffectUI.cpp:121
static const int kUserPresetsDummyID
Definition: EffectUI.cpp:126
static const int kFactoryPresetsID
Definition: EffectUI.cpp:135
static const int kEnableID
Definition: EffectUI.cpp:129
static const int kMenuID
Definition: EffectUI.cpp:128
static const int kDeletePresetDummyID
Definition: EffectUI.cpp:127
static const int kUserPresetsID
Definition: EffectUI.cpp:133
static const int kDeletePresetID
Definition: EffectUI.cpp:134
void MacMakeWindowFloating(NSView *handle)
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define RTL_WORKAROUND(pWnd)
Definition: GUISettings.h:20
#define _(s)
Definition: Internat.h:73
#define safenew
Definition: MemoryX.h:10
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:448
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:162
static const auto title
#define NYQUIST_PROMPT_NAME
an object holding per-project preferred sample rate
AudacityProject * FindProjectFromWindow(wxWindow *pWindow)
RealtimeEffectStateChange
EffectReverbSettings preset
Definition: Reverb.cpp:44
@ eIsSettingToDialog
Definition: ShuttleGui.h:39
@ eIsCreating
Definition: ShuttleGui.h:37
@ eIsGettingFromDialog
Definition: ShuttleGui.h:38
@ eDebugID
Definition: ShuttleGui.h:613
@ eOkButton
Definition: ShuttleGui.h:594
@ eCancelButton
Definition: ShuttleGui.h:595
@ ePreviewButton
Definition: ShuttleGui.h:599
TranslatableString label
Definition: TagsEditor.cpp:165
const auto tracks
const auto project
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:83
static CustomUpdaterValue updater
A wxButton with mouse-over behaviour.
Definition: AButton.h:104
void PushDown()
Definition: AButton.cpp:577
bool IsDown()
Definition: AButton.h:208
void PopUp()
Definition: AButton.cpp:585
Wrap wxMessageDialog so that caption IS translatable.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static AudioIO * Get()
Definition: AudioIO.cpp:123
void RemoveState(AudacityProject &project, ChannelGroup *pGroup, std::shared_ptr< RealtimeEffectState > pState)
Forwards to RealtimeEffectManager::RemoveState with proper init scope.
Definition: AudioIO.cpp:368
std::shared_ptr< RealtimeEffectState > AddState(AudacityProject &project, ChannelGroup *pGroup, const PluginID &id)
Forwards to RealtimeEffectManager::AddState with proper init scope.
Definition: AudioIO.cpp:344
void Popup(const BasicUI::WindowPlacement &window, const Point &pos={})
Display the menu at pos, invoke at most one action, then hide it.
Definition: BasicMenu.cpp:209
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
static CommandManager & Get(AudacityProject &project)
virtual wxString GetVersion() const =0
TranslatableString GetName() const
Base class for many of the effects in Audacity.
Definition: EffectBase.h:28
static std::optional< InstancePointer > FindInstance(EffectPlugin &plugin)
Definition: EffectBase.cpp:243
EffectDefinitionInterface is a ComponentInterface that adds some basic read-only information about ef...
virtual EffectType GetType() const =0
Type determines how it behaves.
virtual bool EnablesDebug() const
Whether the effect dialog should have a Debug button; default, always false.
bool Validate() override
Definition: EffectUI.cpp:1410
bool TransferDataToWindow() override
Definition: EffectUI.cpp:1394
bool TransferDataFromWindow() override
Definition: EffectUI.cpp:1402
virtual void OnPreview(wxCommandEvent &evt)
Definition: EffectUI.cpp:1415
virtual void OnOk(wxCommandEvent &evt)
Definition: EffectUI.cpp:1420
virtual void PopulateOrExchange(ShuttleGui &S)
Definition: EffectUI.cpp:1389
int mAdditionalButtons
Definition: EffectUI.h:207
static constexpr int kPlayID
Definition: EffectEditor.h:76
Base class for many of the effects in Audacity.
Definition: Effect.h:26
EffectManager is the class that handles effects and effect categories.
Definition: EffectManager.h:48
bool GetSkipStateFlag()
void SetSkipStateFlag(bool flag)
EffectPlugin * GetEffect(const PluginID &ID)
static const EffectInstanceFactory * GetInstanceFactory(const PluginID &ID)
static EffectManager & Get()
EffectSettings * GetDefaultSettings(const PluginID &ID)
TranslatableString GetCommandName(const PluginID &ID)
TranslatableString GetCommandDescription(const PluginID &ID)
virtual ~EffectPanel()
Definition: EffectUI.cpp:59
void SetAccept(bool accept)
Definition: EffectUI.cpp:81
bool AcceptsFocus() const override
Definition: EffectUI.cpp:67
bool AcceptsFocusFromKeyboard() const override
Definition: EffectUI.cpp:73
EffectPanel(wxWindow *parent)
Definition: EffectUI.cpp:49
bool mAcceptsFocus
Definition: EffectUI.cpp:87
Factory of instances of an effect.
Definition: EffectPlugin.h:36
virtual bool HasOptions() const =0
virtual bool CanExportPresets() const =0
Whether the effect supports export of presets to files, and importing too.
virtual const EffectSettingsManager & GetDefinition() const =0
virtual bool IsBatchProcessing() const =0
static const RegistryPath & DurationKey()
virtual RegistryPaths GetFactoryPresets() const =0
Report names of factory presets.
virtual bool SaveUserPreset(const RegistryPath &name, const EffectSettings &settings) const =0
Save settings in the configuration file as a user-named preset.
void OnEnable(wxCommandEvent &evt)
Definition: EffectUI.cpp:740
void OnFactoryPreset(wxCommandEvent &evt)
Definition: EffectUI.cpp:790
RegistryPaths mUserPresets
Definition: EffectUI.h:129
void OnDefaults(wxCommandEvent &evt)
Definition: EffectUI.cpp:929
Observer::Subscription mAudioIOSubscription
Definition: EffectUI.h:115
bool HandleCommandKeystrokes() override
Definition: EffectUI.cpp:483
void UpdateControls()
Definition: EffectUI.cpp:1003
wxPanel * BuildButtonBar(wxWindow *parent, bool graphicalUI)
bool mIsBatch
Definition: EffectUI.h:133
bool mCapturing
Definition: EffectUI.h:143
wxButton * mMenuBtn
Definition: EffectUI.h:136
virtual ~EffectUIHost()
Definition: EffectUI.cpp:261
void OnErase(wxEraseEvent &evt)
Definition: EffectUI.cpp:512
void CleanupRealtime()
Definition: EffectUI.cpp:1084
AudacityProject & mProject
Definition: EffectUI.h:117
std::shared_ptr< RealtimeEffectState > mpTempProjectState
Definition: EffectUI.h:127
bool mIsGUI
Definition: EffectUI.h:132
EffectBase & mEffectUIHost
Definition: EffectUI.h:119
bool TransferDataToWindow() override
Definition: EffectUI.cpp:273
EffectPlugin::EffectSettingsAccessPtr mpAccess
Definition: EffectUI.h:123
const EffectOutputs *const mpOutputs
Definition: EffectUI.h:157
void OnUserPreset(wxCommandEvent &evt)
Definition: EffectUI.cpp:777
void OnDeletePreset(wxCommandEvent &evt)
Definition: EffectUI.cpp:801
void OnIdle(wxIdleEvent &evt)
Definition: EffectUI.cpp:940
wxButton * mPlayToggleBtn
Definition: EffectUI.h:139
int ShowModal() override
Definition: EffectUI.cpp:326
Observer::Subscription mEffectStateSubscription
Definition: EffectUI.h:115
void DoCancel()
Definition: EffectUI.cpp:602
void OnCapture(AudioIOEvent)
Definition: EffectUI.cpp:765
EffectUIHost(wxWindow *parent, AudacityProject &project, EffectBase &effect, EffectUIServices &client, std::shared_ptr< EffectInstance > &pInstance, EffectSettingsAccess &access, const std::shared_ptr< RealtimeEffectState > &pPriorState={})
Definition: EffectUI.cpp:226
EffectUIServices & mClient
Definition: EffectUI.h:120
void OnClose(wxCloseEvent &evt)
Definition: EffectUI.cpp:524
void OnExport(wxCommandEvent &evt)
Definition: EffectUI.cpp:912
AButton * mEnableBtn
Definition: EffectUI.h:137
void OnSaveAs(wxCommandEvent &evt)
Definition: EffectUI.cpp:820
wxButton * mApplyBtn
Definition: EffectUI.h:135
const bool mHadPriorState
Definition: EffectUI.h:149
void OnOptions(wxCommandEvent &evt)
Definition: EffectUI.cpp:922
void LoadUserPresets()
Definition: EffectUI.cpp:1019
void OnInitDialog(wxInitDialogEvent &evt)
Definition: EffectUI.cpp:489
void OnMenu(wxCommandEvent &evt)
Definition: EffectUI.cpp:645
void OnDebug(wxCommandEvent &evt)
Definition: EffectUI.cpp:629
void OnCharHook(wxKeyEvent &evt)
Definition: EffectUI.cpp:947
bool mEnabled
Definition: EffectUI.h:141
EffectPlugin::EffectSettingsAccessPtr mpAccess2
Definition: EffectUI.h:124
void OnImport(wxCommandEvent &evt)
Definition: EffectUI.cpp:900
std::unique_ptr< EffectEditor > mpEditor
Definition: EffectUI.h:159
std::shared_ptr< EffectInstance > InitializeInstance()
Definition: EffectUI.cpp:1031
void OnApply(wxCommandEvent &evt)
Definition: EffectUI.cpp:540
const bool mSupportsRealtime
Definition: EffectUI.h:131
bool Initialize()
Definition: EffectUI.cpp:425
void OnPlay(wxCommandEvent &evt)
Definition: EffectUI.cpp:751
const std::shared_ptr< EffectInstance > mpInstance
Definition: EffectUI.h:156
void OnCancel(wxCommandEvent &evt)
Definition: EffectUI.cpp:623
bool mInitialized
Definition: EffectUI.h:130
std::weak_ptr< RealtimeEffectState > mwState
Definition: EffectUI.h:125
wxWindow *const mParent
Definition: EffectUI.h:118
wxButton * mDebugBtn
Definition: EffectUI.h:138
wxBitmap CreateBitmap(const char *const xpm[], bool up, bool pusher)
Definition: EffectUI.cpp:970
bool IsOpenedFromEffectPanel() const
Definition: EffectUI.cpp:965
bool TransferDataFromWindow() override
Definition: EffectUI.cpp:285
void OnPaint(wxPaintEvent &evt)
Definition: EffectUI.cpp:517
bool mDismissed
Definition: EffectUI.h:148
virtual void ShowOptions(const EffectPlugin &plugin) const =0
virtual std::unique_ptr< EffectEditor > PopulateUI(const EffectPlugin &plugin, ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) const =0
Adds controls to a panel that is given as the parent window of S
virtual OptionalMessage ImportPresets(const EffectPlugin &plugin, EffectSettings &settings) const =0
virtual void ExportPresets(const EffectPlugin &plugin, const EffectSettings &settings) const =0
Abstract base class used in importing a file.
typename GlobalVariable< EffectFactory, const std::function< const EffectInstanceFactory * >, nullptr, Options... >::Scope Scope
@ repeattypeplugin
Definition: Menus.h:61
static MenuManager & Get(AudacityProject &project)
Definition: Menus.cpp:69
bool ReportIfActionNotAllowed(const TranslatableString &Name, CommandFlag &flags, CommandFlag flagsRqd)
Definition: Menus.cpp:632
void UpdateMenus(bool checkActive=true)
Definition: Menus.cpp:570
bool isPoint() const
Definition: ViewInfo.h:40
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
Definition: Observer.h:199
void Reset() noexcept
Breaks the connection (constant time)
Definition: Observer.cpp:101
EffectType GetEffectType() const
static PluginID GetID(PluginProvider *provider)
static bool IsPluginAvailable(const PluginDescriptor &plug)
const PluginDescriptor * GetPlugin(const PluginID &ID) const
static PluginManager & Get()
void Stop(bool stopStream=true)
static ProjectAudioManager & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
static ProjectWindow & Get(AudacityProject &project)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:625
wxImage & Image(int iIndex)
Track * Get()
void EnsureVisible(bool modifyState=false)
Definition: Track.cpp:86
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:354
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:232
Holds a msgid for the translation catalog; may also bind format arguments.
static const TranslatableString Inaudible
A special string value that will have no screen reader pronunciation.
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:219
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:3771
A Track that contains audio waveform data.
Definition: WaveTrack.h:221
void Set(EffectSettings &&settings, std::unique_ptr< Message > pMessage) override
const std::weak_ptr< EffectSettingsAccess > mwSide
Definition: EffectUI.cpp:177
void Set(std::unique_ptr< Message > pMessage) override
Message-only overload of Set(). In future, this should be the only one.
const std::shared_ptr< EffectSettingsAccess > mpMain
Definition: EffectUI.cpp:176
void Flush() override
Make the last Set changes "persistent" in underlying storage.
Definition: EffectUI.cpp:213
bool IsSameAs(const EffectSettingsAccess &other) const override
Definition: EffectUI.cpp:220
void SetLabel(const TranslatableString &label)
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:196
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
Definition: BasicUI.h:274
std::unique_ptr< WindowPlacement > FindFocus()
Find the window that is accepting keyboard input, if any.
Definition: BasicUI.h:343
AUDACITY_DLL_API bool DoEffect(const PluginID &ID, const CommandContext &context, unsigned flags)
'Repeat Last Effect'.
Definition: EffectUI.cpp:1144
AUDACITY_DLL_API DialogFactoryResults DialogFactory(wxWindow &parent, EffectBase &host, EffectUIServices &client, EffectSettingsAccess &access)
Definition: EffectUI.cpp:1105
bool RemoveConfigSubgroup(const EffectDefinitionInterface &ident, PluginSettings::ConfigurationType type, const RegistryPath &group)
bool GetConfigSubgroups(const EffectDefinitionInterface &ident, PluginSettings::ConfigurationType type, const RegistryPath &group, RegistryPaths &subgroups)
bool SetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, const Value &value)
void SelectAllIfNone(AudacityProject &project)
AButton * MakeBitmapToggleButton(wxWindow *parent, const wxImage &ImageOn, const wxImage &ImageOff)
Definition: EffectUI.cpp:343
wxString GetVersionForDisplay(const EffectDefinitionInterface &definition)
Definition: EffectUI.cpp:635
static RegisteredToolbarFactory factory
bool on
Definition: AudioIO.h:66
enum AudioIOEvent::Type type
AudacityProject * pProject
Definition: AudioIO.h:60
Externalized state of a plug-in.
Window placement information for wxWidgetsBasicUI can be constructed from a wxWindow pointer.