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