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 mEnableBtn->SetBackgroundColour(GetBackgroundColour());
369 S
370 .Position(wxALIGN_CENTER | wxTOP | wxBOTTOM)
371 .Name(XO("Power"))
372 .AddWindow(mEnableBtn);
373 }
374
375 mMenuBtn = S.Id( kMenuID )
376 .ToolTip(XO("Manage presets and options"))
377 .AddButton( XO("Presets && settings"), wxALIGN_CENTER | wxTOP | wxBOTTOM );
378
379 S.AddSpace(1, 0, 1);
380
381
382
384 {
385 mDebugBtn = S.Id(eDebugID)
386 .AddButton( XXO("Debu&g"),
387 wxALIGN_CENTER | wxTOP | wxBOTTOM );
388 }
389 }
390 S.EndHorizontalLay();
391 }
392 S.EndPanel();
393}
394
396{
397 mEnabled = mpAccess->Get().extra.GetActive();
398
399 // Build a "host" dialog, framing a panel that the client fills in.
400 // The frame includes buttons to preview, apply, load and save presets, etc.
401 EffectPanel *w {};
402 ShuttleGui S{ this, eIsCreating };
403 {
404 BuildTopBar(S);
405
406 // Make the panel for the client
407 Destroy_ptr<EffectPanel> uw{ safenew EffectPanel( S.GetParent() ) };
408 RTL_WORKAROUND(uw.get());
409
410 // Try to give the window a sensible default/minimum size
411 uw->SetMinSize(wxSize(wxMax(600, mParent->GetSize().GetWidth() * 2 / 3),
412 mParent->GetSize().GetHeight() / 2));
413
414 // Let the client add things to the panel
415 ShuttleGui S1{ uw.get(), eIsCreating };
418 if (!mpEditor)
419 return false;
420
421 mIsGUI = mpEditor->IsGraphicalUI();
423
424 S.StartHorizontalLay( wxEXPAND );
425 {
426 S.Prop( 1 )
427 .Position(wxEXPAND)
428 .AddWindow((w = uw.release()));
429 }
430 S.EndHorizontalLay();
431
433 {
434 S.StartPanel();
435 {
436 S.SetBorder( InnerMargin );
437 S.StartHorizontalLay(wxEXPAND, 0);
438 {
439 if (!mIsBatch)
440 {
443 {
444 S.Id(kPlayID)
445 .ToolTip(XO("Preview effect"))
446 .AddButton( XXO("&Preview"),
447 wxALIGN_CENTER | wxTOP | wxBOTTOM );
448 }
449 }
450
451 S.AddSpace(1, 1, 1);
452 S.Id(wxID_CANCEL)
453 .AddButton(XXO("&Cancel"));
454
455 mApplyBtn = S.Id(wxID_APPLY)
456 .AddButton( XXO("&Apply"));
457 mApplyBtn->SetDefault();
458 }
459 S.EndHorizontalLay();
460 }
461 S.EndPanel();
462 }
463 }
464
465 Layout();
466 Fit();
467 Center();
468
470
471 w->SetAccept(!mIsGUI);
472
473 if (!mIsGUI)
474 {
475 w->SetFocus();
476 }
477 else if (!IsOpenedFromEffectPanel())
478 {
479 mApplyBtn->SetFocus();
480 }
481
483
484 SetMinSize(GetSize());
485 return true;
486}
487
489{
490 return !IsModal();
491}
492
493
494void EffectUIHost::OnInitDialog(wxInitDialogEvent & evt)
495{
496 // Do default handling
497 wxDialogWrapper::OnInitDialog(evt);
498
499#if wxCHECK_VERSION(3, 0, 0)
500 //#warning "check to see if this still needed in wx3"
501#endif
502
503 // Pure hackage coming down the pike...
504 //
505 // I have no idea why, but if a wxTextCtrl is the first control in the
506 // panel, then its contents will not be automatically selected when the
507 // dialog is displayed.
508 //
509 // So, we do the selection manually.
510 wxTextCtrl *focused = wxDynamicCast(FindFocus(), wxTextCtrl);
511 if (focused)
512 {
513 focused->SelectAll();
514 }
515}
516
517void EffectUIHost::OnErase(wxEraseEvent & WXUNUSED(evt))
518{
519 // Ignore it
520}
521
522void EffectUIHost::OnPaint(wxPaintEvent & WXUNUSED(evt))
523{
524 wxPaintDC dc(this);
525
526 dc.Clear();
527}
528
529void EffectUIHost::OnClose(wxCloseEvent & WXUNUSED(evt))
530{
531 DoCancel();
533
534 if (mpEditor)
535 mpEditor->OnClose();
536
537 Hide();
538 Destroy();
539
540#if wxDEBUG_LEVEL
541 mClosed = true;
542#endif
543}
544
545void EffectUIHost::OnApply(wxCommandEvent & evt)
546{
547 auto &project = mProject;
548
549 // On wxGTK (wx2.8.12), the default action is still executed even if
550 // the button is disabled. This appears to affect all wxDialogs, not
551 // just our Effects dialogs. So, this is a only temporary workaround
552 // for legacy effects that disable the OK button. Hopefully this has
553 // been corrected in wx3.
554 if (!mApplyBtn->IsEnabled())
555 {
556 return;
557 }
558
559 // Honor the "select all if none" preference...a little hackish, but whatcha gonna do...
560 if (!mIsBatch &&
564 {
565 auto flags = AlwaysEnabledFlag;
566 bool allowed =
569 flags,
571 if (!allowed)
572 return;
573 }
574
575 if (!TransferDataFromWindow() ||
576 // This is the main place where there is a side-effect on the config
577 // file to remember the last-used settings of an effect, just before
578 // applying the effect destructively.
581 return;
582
583 if (IsModal())
584 {
585 mDismissed = true;
586
587 EndModal(evt.GetId());
588
589 Close();
590
591 return;
592 }
593
594 // Progress dialog no longer yields, so this "shouldn't" be necessary (yet to be proven
595 // for sure), but it is a nice visual cue that something is going on.
596 mApplyBtn->Disable();
597 auto cleanup = finally( [&] { mApplyBtn->Enable(); } );
598
599 CommandContext context( project );
600 // This is absolute hackage...but easy and I can't think of another way just now.
601 //
602 // It should callback to the EffectManager to kick off the processing
605}
606
608{
609 if (!mDismissed) {
610 if (!mHadPriorState) {
611 // For the destructive effect dialog only
612 // Restore effect state from last updated preferences
613 mpAccess->ModifySettings([&](EffectSettings &settings) {
614 // ignore failure
615 return mEffectUIHost.GetDefinition().LoadUserPreset(
616 CurrentSettingsGroup(), settings).value_or(nullptr);
617 });
618 }
619 if (IsModal())
620 EndModal(0);
621 else
622 Hide();
623
624 mDismissed = true;
625 }
626}
627
628void EffectUIHost::OnCancel(wxCommandEvent & WXUNUSED(evt))
629{
630 DoCancel();
631 Close();
632}
633
634void EffectUIHost::OnDebug(wxCommandEvent & evt)
635{
636 OnApply(evt);
637}
638
639namespace {
641{
642 static const auto specialVersion = XO("n/a");
643 auto result = definition.GetVersion();
644 if (result == specialVersion.MSGID())
645 result = specialVersion.Translation();
646 return result;
647}
648}
649
650void EffectUIHost::OnMenu(wxCommandEvent & WXUNUSED(evt))
651{
652 wxMenu menu;
653 menu.Bind(wxEVT_MENU, [](auto&){}, kUserPresetsDummyID);
654 menu.Bind(wxEVT_MENU, [](auto&){}, kDeletePresetDummyID);
656
657 if (mUserPresets.size() == 0)
658 {
659 menu.Append(kUserPresetsDummyID, _("User Presets"))->Enable(false);
660 }
661 else
662 {
663 auto sub = std::make_unique<wxMenu>();
664 for (size_t i = 0, cnt = mUserPresets.size(); i < cnt; i++)
665 {
666 sub->Append(kUserPresetsID + i, mUserPresets[i]);
667 }
668 menu.Append(0, _("User Presets"), sub.release());
669 }
670
671 menu.Append(kSaveAsID, _("Save Preset..."));
672
673 if (mUserPresets.size() == 0)
674 {
675 menu.Append(kDeletePresetDummyID, _("Delete Preset"))->Enable(false);
676 }
677 else
678 {
679 auto sub = std::make_unique<wxMenu>();
680 for (size_t i = 0, cnt = mUserPresets.size(); i < cnt; i++)
681 {
682 sub->Append(kDeletePresetID + i, mUserPresets[i]);
683 }
684 menu.Append(0, _("Delete Preset"), sub.release());
685 }
686
687 menu.AppendSeparator();
688
690
691 {
692 auto sub = std::make_unique<wxMenu>();
693 sub->Append(kDefaultsID, _("Defaults"));
694 if (factory.size() > 0)
695 {
696 sub->AppendSeparator();
697 for (size_t i = 0, cnt = factory.size(); i < cnt; i++)
698 {
699 auto label = factory[i];
700 if (label.empty())
701 {
702 label = _("None");
703 }
704
705 sub->Append(kFactoryPresetsID + i, label);
706 }
707 }
708 menu.Append(0, _("Factory Presets"), sub.release());
709 }
710
711 menu.AppendSeparator();
712 menu.Append(kImportID, _("Import..."))
714 menu.Append(kExportID, _("Export..."))
716 menu.AppendSeparator();
717 menu.Append(kOptionsID, _("Options..."))
718 ->Enable(mEffectUIHost.HasOptions());
719 menu.AppendSeparator();
720
721 {
722 auto sub = std::make_unique<wxMenu>();
723
724 auto &definition = mEffectUIHost.GetDefinition();
725 sub->Append(kDummyID, wxString::Format(_("Type: %s"),
726 ::wxGetTranslation( definition.GetFamily().Translation() )));
727 sub->Append(kDummyID, wxString::Format(_("Name: %s"), definition.GetName().Translation()));
728 sub->Append(kDummyID, wxString::Format(_("Version: %s"),
729 GetVersionForDisplay(definition)));
730 sub->Append(kDummyID, wxString::Format(_("Vendor: %s"), definition.GetVendor().Translation()));
731 sub->Append(kDummyID, wxString::Format(_("Description: %s"), definition.GetDescription().Translation()));
732 sub->Bind(wxEVT_MENU, [](auto&){}, kDummyID);
733
734 menu.Append(0, _("About"), sub.release());
735 }
736
737 wxWindow *btn = FindWindow(kMenuID);
738 wxRect r = btn->GetRect();
739 BasicMenu::Handle{ &menu }.Popup(
741 { r.GetLeft(), r.GetBottom() }
742 );
743}
744
745void EffectUIHost::OnEnable(wxCommandEvent & WXUNUSED(evt))
746{
748
749 auto mpState = mwState.lock();
750 if (mpState) {
751 mpState->SetActive(mEnabled);
753 }
754
756}
757
758void EffectUIHost::OnPlay(wxCommandEvent & WXUNUSED(evt))
759{
761 return;
762
763 auto updater = [this]{ TransferDataToWindow(); };
765 // After restoration of settings and effect state:
766 // In case any dialog control depends on mT1 or mDuration:
767 updater();
768
769 return;
770}
771
773{
774 if (evt.on) {
775 if (evt.pProject == &mProject)
776 mCapturing = true;
777 }
778 else {
779 mCapturing = false;
780 }
782}
783
784void EffectUIHost::OnUserPreset(wxCommandEvent & evt)
785{
786 int preset = evt.GetId() - kUserPresetsID;
787
788 mpAccess->ModifySettings([&](EffectSettings &settings){
789 // ignore failure
790 return mEffectUIHost.GetDefinition().LoadUserPreset(
791 UserPresetsGroup(mUserPresets[preset]), settings).value_or(nullptr);
792 });
794 return;
795}
796
797void EffectUIHost::OnFactoryPreset(wxCommandEvent & evt)
798{
799 mpAccess->ModifySettings([&](EffectSettings &settings){
801 return mEffectUIHost.GetDefinition().LoadFactoryPreset(
802 evt.GetId() - kFactoryPresetsID, settings).value_or(nullptr);
803 });
805 return;
806}
807
808void EffectUIHost::OnDeletePreset(wxCommandEvent & evt)
809{
810 auto preset = mUserPresets[evt.GetId() - kDeletePresetID];
811
812 int res = AudacityMessageBox(
813 XO("Are you sure you want to delete \"%s\"?").Format( preset ),
814 XO("Delete Preset"),
815 wxICON_QUESTION | wxYES_NO);
816 if (res == wxYES)
817 {
820 }
821
823
824 return;
825}
826
827void EffectUIHost::OnSaveAs(wxCommandEvent & WXUNUSED(evt))
828{
829 wxTextCtrl *text;
830 wxString name;
831 wxDialogWrapper dlg(this, wxID_ANY, XO("Save Preset"));
832
833 ShuttleGui S(&dlg, eIsCreating);
834
835 S.StartPanel();
836 {
837 S.StartVerticalLay(1);
838 {
839 S.StartHorizontalLay(wxALIGN_LEFT, 0);
840 {
841 text = S.AddTextBox(XXO("Preset name:"), name, 30);
842 }
843 S.EndHorizontalLay();
844 S.SetBorder(10);
845 S.AddStandardButtons();
846 }
847 S.EndVerticalLay();
848 }
849 S.EndPanel();
850
851 dlg.SetSize(dlg.GetSizer()->GetMinSize());
852 dlg.Center();
853 dlg.Fit();
854
855 while (true)
856 {
857 int rc = dlg.ShowModal();
858
859 if (rc != wxID_OK)
860 {
861 break;
862 }
863
864 name = text->GetValue();
865 if (name.empty())
866 {
868 this,
869 XO("You must specify a name"),
870 XO("Save Preset") );
871 md.Center();
872 md.ShowModal();
873 continue;
874 }
875
876 if ( make_iterator_range( mUserPresets ).contains( name ) )
877 {
879 this,
880 XO("Preset already exists.\n\nReplace?"),
881 XO("Save Preset"),
882 wxYES_NO | wxCANCEL | wxICON_EXCLAMATION );
883 md.Center();
884 int choice = md.ShowModal();
885 if (choice == wxID_CANCEL)
886 {
887 break;
888 }
889
890 if (choice == wxID_NO)
891 {
892 continue;
893 }
894 }
895
900
901 break;
902 }
903
904 return;
905}
906
907void EffectUIHost::OnImport(wxCommandEvent & WXUNUSED(evt))
908{
909 mpAccess->ModifySettings([&](EffectSettings &settings){
910 // ignore failure
911 return mClient.ImportPresets(mEffectUIHost, settings).value_or(nullptr);
912 });
915
916 return;
917}
918
919void EffectUIHost::OnExport(wxCommandEvent & WXUNUSED(evt))
920{
921 // may throw
922 // exceptions are handled in AudacityApp::OnExceptionInMainLoop
925
926 return;
927}
928
929void EffectUIHost::OnOptions(wxCommandEvent & WXUNUSED(evt))
930{
932
933 return;
934}
935
936void EffectUIHost::OnDefaults(wxCommandEvent & WXUNUSED(evt))
937{
938 mpAccess->ModifySettings([&](EffectSettings &settings){
939 // ignore failure
940 return mEffectUIHost.GetDefinition().LoadFactoryDefaults(settings)
941 .value_or(nullptr);
942 });
944 return;
945}
946
947void EffectUIHost::OnIdle(wxIdleEvent &evt)
948{
949 evt.Skip();
950 if (mpAccess)
951 mpAccess->Flush();
952}
953
954void EffectUIHost::OnCharHook(wxKeyEvent& evt)
955{
956 if (!IsEscapeKey(evt))
957 {
958 evt.Skip();
959 return;
960 }
961
963 Close();
964 else
965 {
966 wxCommandEvent cancelEvt { wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL };
967
968 OnCancel(cancelEvt);
969 }
970}
971
973{
974 return (mpTempProjectState == nullptr && mSupportsRealtime);
975}
976
977wxBitmap EffectUIHost::CreateBitmap(const char * const xpm[], bool up, bool pusher)
978{
979 wxMemoryDC dc;
980 wxBitmap pic(xpm);
981
982 wxBitmap mod(pic.GetWidth() + 6, pic.GetHeight() + 6, 24);
983 dc.SelectObject(mod);
984
985#if defined(__WXGTK__)
986 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND);
987#else
988 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
989#endif
990
991 dc.SetBackground(wxBrush(newColour));
992 dc.Clear();
993
994 int offset = 3;
995 if (pusher)
996 {
997 if (!up)
998 {
999 offset += 1;
1000 }
1001 }
1002
1003 dc.DrawBitmap(pic, offset, offset, true);
1004
1005 dc.SelectObject(wxNullBitmap);
1006
1007 return mod;
1008}
1009
1011{
1012 if (mIsBatch)
1013 {
1014 return;
1015 }
1016
1018 {
1020 return;
1021 }
1022
1023 mApplyBtn->Enable(!mCapturing);
1024}
1025
1027{
1028 mUserPresets.clear();
1029
1032
1033 std::sort( mUserPresets.begin(), mUserPresets.end() );
1034
1035 return;
1036}
1037
1038std::shared_ptr<EffectInstance> EffectUIHost::InitializeInstance()
1039{
1040 // We are still constructing and the return initializes a const member
1041 std::shared_ptr<EffectInstance> result;
1042
1043 auto mpState = mwState.lock();
1044
1045 bool priorState = (mpState != nullptr);
1046 if (!priorState) {
1047 auto gAudioIO = AudioIO::Get();
1048 mCapturing = gAudioIO->IsStreamActive() && gAudioIO->GetNumCaptureChannels() > 0 && !gAudioIO->IsMonitoring();
1049 }
1050
1052 if (!priorState)
1053 mwState = mpState = mpTempProjectState =
1055 if (mpState) {
1056 // Find the right instance to connect to the dialog
1057 if (!result)
1058 result = mpState->GetInstance();
1059
1060 mpAccess2 = mpState->GetAccess();
1061 if (!(mpAccess2->IsSameAs(*mpAccess)))
1062 // Decorate the given access object
1063 mpAccess = std::make_shared<EffectSettingsAccessTee>(
1065
1066 mEffectStateSubscription = mpState->Subscribe([this](RealtimeEffectStateChange state) {
1069 });
1070 }
1071
1072 if (!priorState) {
1074 switch (event.type) {
1075 case AudioIOEvent::CAPTURE:
1076 OnCapture(event); break;
1077 default:
1078 break;
1079 }
1080 });
1081 }
1082
1083 mInitialized = true;
1084 }
1085 else
1086 result = EffectBase::FindInstance(mEffectUIHost).value_or(nullptr);
1087
1088 return result;
1089}
1090
1092{
1094
1096 if (!IsOpenedFromEffectPanel()) {
1099 mpTempProjectState.reset();
1100 /*
1101 ProjectHistory::Get(mProject).PushState(
1102 XO("Removed %s effect").Format(mpState->GetEffect()->GetName()),
1103 XO("Removed Effect"),
1104 UndoPush::NONE
1105 );
1106 */
1107 }
1108 mInitialized = false;
1109 }
1110}
1111
1113 EffectBase &host, EffectUIServices &client,
1114 EffectSettingsAccess &access)
1115{
1116 // Make sure there is an associated project, whose lifetime will
1117 // govern the lifetime of the dialog, even when the dialog is
1118 // non-modal, as for realtime effects
1119 auto project = FindProjectFromWindow(&parent);
1120 if ( !project )
1121 return {};
1122 std::shared_ptr<EffectInstance> pInstance;
1124 *project, host, client, pInstance, access } };
1125 if (!pInstance) {
1126 dlg->SetClosed();
1127 return {};
1128 }
1129 if (dlg->Initialize()) {
1130 auto pEditor = dlg->GetEditor();
1131 // release() is safe because parent will own it
1132 return { dlg.release(), pInstance, pEditor };
1133 }
1134 return {};
1135}
1136
1137#include "PluginManager.h"
1138#include "ProjectRate.h"
1139#include "../SelectUtilities.h"
1140#include "WaveTrack.h"
1141#include "CommandManager.h"
1142
1146// parameters, whether to save the state to history and whether to allow
1148
1149/* static */ bool EffectUI::DoEffect(
1150 const PluginID & ID, const CommandContext &context, unsigned flags )
1151{
1152 AudacityProject &project = context.project;
1153 auto &tracks = TrackList::Get( project );
1154 auto &trackFactory = WaveTrackFactory::Get( project );
1155 auto rate = ProjectRate::Get(project).GetRate();
1156 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
1157 auto &commandManager = CommandManager::Get( project );
1158 auto &viewport = Viewport::Get(project);
1159 auto &window = GetProjectFrame(project);
1160
1161 const PluginDescriptor *plug = PluginManager::Get().GetPlugin(ID);
1162
1163 if (!plug || !PluginManager::IsPluginAvailable(*plug))
1164 {
1166 XO("This plugin could not be loaded.\nIt may have been deleted."),
1168 .Caption(XO("Plugin Error")));
1169
1170 return false;
1171 }
1172
1173 EffectType type = plug->GetEffectType();
1174
1175 // Make sure there's no activity since the effect is about to be applied
1176 // to the project's tracks. Mainly for Apply during RTP, but also used
1177 // for batch commands
1178 if (flags & EffectManager::kConfigured)
1179 {
1181 //Don't Select All if repeating Generator Effect
1182 if (!(flags & EffectManager::kConfigured)) {
1184 }
1185 }
1186
1187 auto nTracksOriginally = tracks.Size();
1188 wxWindow *focus = wxWindow::FindFocus();
1189 wxWindow *parent = nullptr;
1190 if (focus != nullptr) {
1191 parent = focus->GetParent();
1192 }
1193
1194 bool success = false;
1195 auto cleanup = finally( [&] {
1196
1197 if (!success) {
1198 // For now, we're limiting realtime preview to a single effect, so
1199 // make sure the menus reflect that fact that one may have just been
1200 // opened.
1202 }
1203
1204 } );
1205
1206 const auto range = tracks.Selected<const WaveTrack>();
1207 bool anyTracks = !range.empty();
1208 bool clean = std::all_of(range.begin(), range.end(),
1209 [](const WaveTrack *t){ return t->GetEndTime() == 0; });
1210
1212
1213 em.SetSkipStateFlag( false );
1214 success = false;
1215 if (auto effect = dynamic_cast<Effect*>(em.GetEffect(ID))) {
1216 if (const auto pSettings = em.GetDefaultSettings(ID)) {
1217 const auto pAccess =
1218 std::make_shared<SimpleEffectSettingsAccess>(*pSettings);
1219 const auto finder =
1220 [effect, &window, pAccess, flags] (EffectSettings &settings)
1221 -> std::optional<std::shared_ptr<EffectInstanceEx>>
1222 {
1223 // Prompting will be bypassed when applying an effect that has
1224 // already been configured, e.g. repeating the last effect on a
1225 // different selection. Prompting may call EffectPreview
1226 std::shared_ptr<EffectInstance> pInstance;
1227 std::shared_ptr<EffectInstanceEx> pInstanceEx;
1228 if ((flags & EffectManager::kConfigured) == 0 && pAccess) {
1229 const auto pServices = dynamic_cast<EffectUIServices *>(effect);
1230 if (!pServices ||
1231 !pServices->ShowHostInterface(*effect,
1232 window, DialogFactory, pInstance, *pAccess, true)
1233 )
1234 return {};
1235 else if (!(pInstanceEx =
1236 std::dynamic_pointer_cast<EffectInstanceEx>(pInstance)
1237 ))
1238 return {};
1239 else
1240 // Retrieve again after the dialog modified settings
1241 settings = pAccess->Get();
1242 }
1243 return { pInstanceEx };
1244 };
1245 pAccess->ModifySettings([&](EffectSettings &settings){
1246 success = effect->DoEffect(settings, finder,
1247 rate,
1248 &tracks,
1249 &trackFactory,
1250 selectedRegion,
1251 flags,
1252 pAccess);
1253 return nullptr;
1254 });
1255 }
1256 }
1257
1258 if (!success)
1259 return false;
1260
1261 if (em.GetSkipStateFlag())
1262 flags = flags | EffectManager::kSkipState;
1263
1264 if (!(flags & EffectManager::kSkipState))
1265 {
1266 auto shortDesc = em.GetCommandName(ID);
1267 auto longDesc = em.GetCommandDescription(ID);
1268 ProjectHistory::Get( project ).PushState(longDesc, shortDesc);
1269 }
1270
1271 if (!(flags & EffectManager::kDontRepeatLast))
1272 {
1273 // Remember a successful generator, effect, analyzer, or tool Process
1274 auto shortDesc = em.GetCommandName(ID);
1275 /* i18n-hint: %s will be the name of the effect which will be
1276 * repeated if this menu item is chosen */
1277 auto lastEffectDesc = XO("Repeat %s").Format(shortDesc);
1278 switch ( type ) {
1279 case EffectTypeGenerate:
1280 commandManager.Modify(wxT("RepeatLastGenerator"), lastEffectDesc);
1281 commandManager.mLastGenerator = ID;
1282 commandManager.mRepeatGeneratorFlags = EffectManager::kConfigured;
1283 break;
1284 case EffectTypeProcess:
1285 commandManager.Modify(wxT("RepeatLastEffect"), lastEffectDesc);
1286 commandManager.mLastEffect = ID;
1287 commandManager.mRepeatEffectFlags = EffectManager::kConfigured;
1288 break;
1289 case EffectTypeAnalyze:
1290 commandManager.Modify(wxT("RepeatLastAnalyzer"), lastEffectDesc);
1291 commandManager.mLastAnalyzer = ID;
1292 commandManager.mLastAnalyzerRegistration =
1294 commandManager.mRepeatAnalyzerFlags = EffectManager::kConfigured;
1295 break;
1296 case EffectTypeTool:
1297 commandManager.Modify(wxT("RepeatLastTool"), lastEffectDesc);
1298 commandManager.mLastTool = ID;
1299 commandManager.mLastToolRegistration =
1301 commandManager.mRepeatToolFlags = EffectManager::kConfigured;
1302 if (shortDesc == NYQUIST_PROMPT_NAME) {
1303 commandManager.mRepeatToolFlags = EffectManager::kRepeatNyquistPrompt; //Nyquist Prompt is not configured
1304 }
1305 break;
1306 }
1307 }
1308
1309 //STM:
1310 //The following automatically re-zooms after sound was generated.
1311 // IMO, it was disorienting, removing to try out without re-fitting
1312 //mchinen:12/14/08 reapplying for generate effects
1313 if (type == EffectTypeGenerate)
1314 {
1315 if (!anyTracks || (clean && selectedRegion.t0() == 0.0))
1316 viewport.ZoomFitHorizontally();
1317 }
1318
1319 // PRL: Redraw explicitly because sometimes history push is skipped
1320 viewport.Redraw();
1321
1322 if (focus != nullptr && focus->GetParent()==parent) {
1323 focus->SetFocus();
1324 }
1325
1326 // A fix for Bug 63
1327 // New tracks added? Scroll them into view so that user sees them.
1328 // Don't care what track type. An analyser might just have added a
1329 // Label track and we want to see it.
1330 if (tracks.Size() > nTracksOriginally) {
1331 viewport.ScrollToBottom();
1332 }
1333 else {
1334 auto pTrack = *tracks.Selected().begin();
1335 if (!pTrack)
1336 pTrack = *tracks.begin();
1337 if (pTrack) {
1338 TrackFocus::Get(project).Set(pTrack);
1340 }
1341 }
1342
1343 return true;
1344}
1345
1347BEGIN_EVENT_TABLE(EffectDialog, wxDialogWrapper)
1350
1351EffectDialog::EffectDialog(wxWindow * parent,
1352 const TranslatableString & title,
1353 int type,
1354 int flags,
1355 int additionalButtons)
1356: wxDialogWrapper(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, flags)
1357{
1358 mType = type;
1359 mAdditionalButtons = additionalButtons;
1360}
1361
1363{
1364 long buttons = eOkButton;
1366 {
1367 buttons |= eCancelButton;
1368 if (mType == EffectTypeProcess)
1369 {
1370 buttons |= ePreviewButton;
1371 }
1372 }
1373
1374 ShuttleGui S(this, eIsCreating);
1375
1376 S.SetBorder(5);
1377 S.StartVerticalLay(true);
1378 {
1380 S.AddStandardButtons(buttons|mAdditionalButtons);
1381 }
1382 S.EndVerticalLay();
1383
1384 Layout();
1385 Fit();
1386 SetMinSize(GetSize());
1387 Center();
1388}
1389
1394{
1395 return;
1396}
1397
1399{
1402
1403 return true;
1404}
1405
1407{
1410
1411 return true;
1412}
1413
1415{
1416 return true;
1417}
1418
1419void EffectDialog::OnPreview(wxCommandEvent & WXUNUSED(evt))
1420{
1421 return;
1422}
1423
1424void EffectDialog::OnOk(wxCommandEvent & WXUNUSED(evt))
1425{
1426 // On wxGTK (wx2.8.12), the default action is still executed even if
1427 // the button is disabled. This appears to affect all wxDialogs, not
1428 // just our Effects dialogs. So, this is a only temporary workaround
1429 // for legacy effects that disable the OK button. Hopefully this has
1430 // been corrected in wx3.
1431 if (FindWindow(wxID_OK)->IsEnabled() && Validate() && TransferDataFromWindow())
1432 {
1433 EndModal(wxID_OK);
1434 }
1435
1436 return;
1437}
1438
1440#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)
static RegisteredToolbarFactory factory
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:1442
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:10
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:164
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:628
@ eOkButton
Definition: ShuttleGui.h:609
@ eCancelButton
Definition: ShuttleGui.h:610
@ ePreviewButton
Definition: ShuttleGui.h:614
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:51
static CustomUpdaterValue updater
A wxButton with mouse-over behaviour.
Definition: AButton.h:104
void PushDown()
Definition: AButton.cpp:644
bool IsDown()
Definition: AButton.h:226
void PopUp()
Definition: AButton.cpp:652
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:369
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:239
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:1414
bool TransferDataToWindow() override
Definition: EffectUI.cpp:1398
bool TransferDataFromWindow() override
Definition: EffectUI.cpp:1406
virtual void OnPreview(wxCommandEvent &evt)
Definition: EffectUI.cpp:1419
virtual void OnOk(wxCommandEvent &evt)
Definition: EffectUI.cpp:1424
virtual void PopulateOrExchange(ShuttleGui &S)
Definition: EffectUI.cpp:1393
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:745
void OnFactoryPreset(wxCommandEvent &evt)
Definition: EffectUI.cpp:797
RegistryPaths mUserPresets
Definition: EffectUI.h:128
void OnDefaults(wxCommandEvent &evt)
Definition: EffectUI.cpp:936
Observer::Subscription mAudioIOSubscription
Definition: EffectUI.h:114
bool HandleCommandKeystrokes() override
Definition: EffectUI.cpp:488
void UpdateControls()
Definition: EffectUI.cpp:1010
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:517
void CleanupRealtime()
Definition: EffectUI.cpp:1091
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:784
void OnDeletePreset(wxCommandEvent &evt)
Definition: EffectUI.cpp:808
void OnIdle(wxIdleEvent &evt)
Definition: EffectUI.cpp:947
int ShowModal() override
Definition: EffectUI.cpp:328
Observer::Subscription mEffectStateSubscription
Definition: EffectUI.h:114
void DoCancel()
Definition: EffectUI.cpp:607
void OnCapture(AudioIOEvent)
Definition: EffectUI.cpp:772
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:529
void OnExport(wxCommandEvent &evt)
Definition: EffectUI.cpp:919
AButton * mEnableBtn
Definition: EffectUI.h:136
void BuildTopBar(ShuttleGui &S)
Definition: EffectUI.cpp:356
void OnSaveAs(wxCommandEvent &evt)
Definition: EffectUI.cpp:827
wxButton * mApplyBtn
Definition: EffectUI.h:134
const bool mHadPriorState
Definition: EffectUI.h:147
void OnOptions(wxCommandEvent &evt)
Definition: EffectUI.cpp:929
void LoadUserPresets()
Definition: EffectUI.cpp:1026
void OnInitDialog(wxInitDialogEvent &evt)
Definition: EffectUI.cpp:494
void OnMenu(wxCommandEvent &evt)
Definition: EffectUI.cpp:650
void OnDebug(wxCommandEvent &evt)
Definition: EffectUI.cpp:634
void OnCharHook(wxKeyEvent &evt)
Definition: EffectUI.cpp:954
bool mEnabled
Definition: EffectUI.h:139
EffectPlugin::EffectSettingsAccessPtr mpAccess2
Definition: EffectUI.h:123
void OnImport(wxCommandEvent &evt)
Definition: EffectUI.cpp:907
std::unique_ptr< EffectEditor > mpEditor
Definition: EffectUI.h:157
std::shared_ptr< EffectInstance > InitializeInstance()
Definition: EffectUI.cpp:1038
void OnApply(wxCommandEvent &evt)
Definition: EffectUI.cpp:545
const bool mSupportsRealtime
Definition: EffectUI.h:130
bool Initialize()
Definition: EffectUI.cpp:395
void OnPlay(wxCommandEvent &evt)
Definition: EffectUI.cpp:758
const std::shared_ptr< EffectInstance > mpInstance
Definition: EffectUI.h:154
void OnCancel(wxCommandEvent &evt)
Definition: EffectUI.cpp:628
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:977
bool IsOpenedFromEffectPanel() const
Definition: EffectUI.cpp:972
bool TransferDataFromWindow() override
Definition: EffectUI.cpp:287
void OnPaint(wxPaintEvent &evt)
Definition: EffectUI.cpp:522
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(const 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:640
wxImage & Image(int iIndex)
Track * Get()
Definition: TrackFocus.cpp:156
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
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:216
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
void ShowTrack(const Track &track)
Definition: Viewport.cpp:460
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:3358
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
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:202
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:287
std::unique_ptr< WindowPlacement > FindFocus()
Find the window that is accepting keyboard input, if any.
Definition: BasicUI.h:383
AUDACITY_DLL_API bool DoEffect(const PluginID &ID, const CommandContext &context, unsigned flags)
'Repeat Last Effect'.
Definition: EffectUI.cpp:1149
AUDACITY_DLL_API DialogFactoryResults DialogFactory(wxWindow &parent, EffectBase &host, EffectUIServices &client, EffectSettingsAccess &access)
Definition: EffectUI.cpp:1112
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:640
bool on
Definition: AudioIO.h:67
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.