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
14
15#include "EffectUI.h"
16
17#include "AllThemeResources.h"
18#include "widgets/BasicMenu.h"
19#include "ConfigInterface.h"
20#include "EffectManager.h"
21#include "PluginManager.h"
22#include "ProjectHistory.h"
23#include "../ProjectWindowBase.h"
24#include "../TrackPanelAx.h"
25#include "RealtimeEffectList.h"
27#include "RealtimeEffectState.h"
28#include "Theme.h"
30
32{
33 return PluginManager::GetID(&effect.GetDefinition());
34}
35
37//
38// EffectPanel
39//
41
42class EffectPanel final : public wxPanelWrapper
43{
44public:
45 EffectPanel(wxWindow *parent)
46 : wxPanelWrapper(parent)
47 {
48 // This fools NVDA into not saying "Panel" when the dialog gets focus
51
52 mAcceptsFocus = true;
53 }
54
55 virtual ~EffectPanel()
56 {
57 }
58
59 // ============================================================================
60 // wxWindow implementation
61 // ============================================================================
62
63 bool AcceptsFocus() const override
64 {
65 return mAcceptsFocus;
66 }
67
68 // So that wxPanel is not included in Tab traversal, when required - see wxWidgets bug 15581
69 bool AcceptsFocusFromKeyboard() const override
70 {
71 return mAcceptsFocus;
72 }
73
74 // ============================================================================
75 // EffectPanel implementation
76 // ============================================================================
77 void SetAccept(bool accept)
78 {
79 mAcceptsFocus = accept;
80 }
81
82private:
84};
85
87//
88// EffectUIHost
89//
91
92#include "../../images/Effect.h"
93#include "../AudioIO.h"
94#include "../CommonCommandFlags.h"
95#include "../Menus.h"
96#include "../prefs/GUISettings.h" // for RTL_WORKAROUND
97#include "Project.h"
98#include "../ProjectAudioManager.h"
99#include "../ShuttleGui.h"
100#include "ViewInfo.h"
101#include "../commands/AudacityCommand.h"
102#include "../commands/CommandContext.h"
103#include "../widgets/AudacityMessageBox.h"
104#include "../widgets/HelpSystem.h"
105
106#include <wx/bmpbuttn.h>
107#include <wx/checkbox.h>
108#include <wx/dcclient.h>
109#include <wx/dcmemory.h>
110#include <wx/menu.h>
111#include <wx/settings.h>
112#include <wx/sizer.h>
113#include <wx/textctrl.h>
114
115#if defined(__WXMAC__)
116#include <Cocoa/Cocoa.h>
117#endif
118
119static const int kDummyID = 20000;
120static const int kSaveAsID = 20001;
121static const int kImportID = 20002;
122static const int kExportID = 20003;
123static const int kDefaultsID = 20004;
124static const int kOptionsID = 20005;
125static const int kUserPresetsDummyID = 20006;
126static const int kDeletePresetDummyID = 20007;
127static const int kMenuID = 20100;
128static const int kEnableID = 20101;
129static const int kPlayID = 20102;
130static const int kPlaybackID = 20105;
131static const int kCaptureID = 20106;
132static const int kUserPresetsID = 21000;
133static const int kDeletePresetID = 22000;
134static const int kFactoryPresetsID = 23000;
135
136BEGIN_EVENT_TABLE(EffectUIHost, wxDialogWrapper)
137EVT_INIT_DIALOG(EffectUIHost::OnInitDialog)
138EVT_ERASE_BACKGROUND(EffectUIHost::OnErase)
139EVT_PAINT(EffectUIHost::OnPaint)
140EVT_CLOSE(EffectUIHost::OnClose)
155EVT_IDLE(EffectUIHost::OnIdle)
156EVT_CHAR_HOOK(EffectUIHost::OnCharHook)
158
159namespace {
162
164public:
166 const std::shared_ptr<EffectSettingsAccess> &pSide = {});
167 const EffectSettings &Get() override;
169 std::unique_ptr<Message> pMessage) override;
170 void Set(std::unique_ptr<Message> pMessage) override;
171 void Flush() override;
172 bool IsSameAs(const EffectSettingsAccess &other) const override;
173private:
175 const std::shared_ptr<EffectSettingsAccess> mpMain;
176 const std::weak_ptr<EffectSettingsAccess> mwSide;
177};
178}
179
180EffectSettingsAccessTee::EffectSettingsAccessTee(
182 const std::shared_ptr<EffectSettingsAccess> &pSide
183) : mpMain{ main.shared_from_this() }
184 , mwSide{ pSide }
185{
186}
187
189 return mpMain->Get();
190}
191
193 std::unique_ptr<Message> pMessage)
194{
195 // Move copies of the given settings and message into the side
196 if (auto pSide = mwSide.lock())
197 pSide->Set(EffectSettings{ settings },
198 pMessage ? pMessage->Clone() : nullptr);
199 // Move the given settings and message through
200 mpMain->Set(std::move(settings), std::move(pMessage));
201}
202
203void EffectSettingsAccessTee::Set(std::unique_ptr<Message> pMessage)
204{
205 // Move copies of the given message into the side
206 if (auto pSide = mwSide.lock())
207 pSide->Set(pMessage ? pMessage->Clone() : nullptr);
208 // Move the given message through
209 mpMain->Set(std::move(pMessage));
210}
211
213{
214 mpMain->Flush();
215 if (auto pSide = mwSide.lock())
216 pSide->Flush();
217}
218
220 const EffectSettingsAccess &other) const
221{
222 return mpMain->IsSameAs(other);
223}
224
226 AudacityProject &project, EffectPlugin &effect,
227 EffectUIClientInterface &client, std::shared_ptr<EffectInstance> &pInstance,
228 EffectSettingsAccess &access,
229 const std::shared_ptr<RealtimeEffectState> &pPriorState)
230: wxDialogWrapper(parent, wxID_ANY, effect.GetDefinition().GetName(),
231 wxDefaultPosition, wxDefaultSize,
232 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX)
233, mEffectUIHost{ effect }
234, mClient{ client }
235// Grab a pointer to the access object,
236// extending its lifetime while this remains:
237, mpGivenAccess{ access.shared_from_this() }
238, mpAccess{ mpGivenAccess }
239, mwState{ pPriorState }
240, mProject{ project }
241, mParent{ parent }
242, mSupportsRealtime{ mEffectUIHost.GetDefinition().SupportsRealtime() }
243, mHadPriorState{ (pPriorState != nullptr) }
244, mpInstance{ InitializeInstance() }
245, mpOutputs{ pPriorState ? pPriorState->GetOutputs() : nullptr }
246{
247 // Assign the out parameter
248 pInstance = mpInstance;
249#if defined(__WXMAC__)
250 // Make sure the effect window actually floats above the main window
251 [ [((NSView *)GetHandle()) window] setLevel:NSFloatingWindowLevel];
252#endif
253
254 SetName( effect.GetDefinition().GetName() );
255
256 // This style causes Validate() and TransferDataFromWindow() to visit
257 // sub-windows recursively, applying any wxValidators
258 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
259}
260
262{
263 if (mpValidator)
264 mpValidator->Disconnect();
265 DestroyChildren();
266 wxASSERT(mClosed);
267}
268
269// ============================================================================
270// wxWindow implementation
271// ============================================================================
272
274{
275 // Transfer-to takes const reference to settings
278 mpValidator->UpdateUI() &&
280 wxDialogWrapper::TransferDataToWindow();
281}
282
284{
286 if (!wxDialogWrapper::Validate())
287 return false;
288
290 if (!wxDialogWrapper::TransferDataFromWindow())
291 return false;
292
294 if (!mpValidator->ValidateUI())
295 return false;
296
297 // Transfer-from takes non-const reference to settings
298 bool result = true;
299 mpAccess->ModifySettings([&](EffectSettings &settings){
300 // Allow other transfers, and reassignment of settings
302 if (result) {
303 auto &definition = mEffectUIHost.GetDefinition();
304 if (definition.GetType() == EffectTypeGenerate) {
305 const auto seconds = settings.extra.GetDuration();
306 // Updating of the last-used generator duration in the config
307 SetConfig(definition, PluginSettings::Private,
308 CurrentSettingsGroup(), EffectSettingsExtra::DurationKey(),
309 seconds);
310 }
311 }
312 return nullptr;
313 });
314 mpAccess->Flush();
315 return result;
316}
317
318// ============================================================================
319// wxDialog implementation
320// ============================================================================
321
323{
325 {
326 mApplyBtn->SetLabel(XXO("&Generate").Translation());
327 }
328
329 Layout();
330
331 return wxDialogWrapper::ShowModal();
332}
333
334// ============================================================================
335// EffectUIHost implementation
336// ============================================================================
337
339{
340 mIsGUI = graphicalUI;
342
343 constexpr int margin = 3;
344
345 S.StartPanel();
346 {
347 S.SetBorder( margin );
348
349 S.StartHorizontalLay(wxEXPAND, 0);
350 {
352 {
354 .Position(wxALIGN_CENTER | wxTOP | wxBOTTOM)
355 .Name(XO("Enable"))
356 .AddBitmapButton(mEnabled ? mRealtimeEnabledBM : mRealtimeDisabledBM);
357 }
358
359 mMenuBtn = S.Id( kMenuID )
360 .ToolTip(XO("Manage presets and options"))
361 .AddButton( XO("Presets && settings"), wxALIGN_CENTER | wxTOP | wxBOTTOM );
362
363 S.AddSpace(1, 0, 1);
364
365 if (!mIsBatch)
366 {
368 {
370 {
372 .ToolTip(XO("Start and stop preview"))
373 .AddButton( { },
374 wxALIGN_CENTER | wxTOP | wxBOTTOM );
375 }
376 }
377 else if (
380 {
382 .ToolTip(XO("Preview effect"))
383 .AddButton( { },
384 wxALIGN_CENTER | wxTOP | wxBOTTOM );
385 }
386 if(mPlayToggleBtn != nullptr)
387 {
388 //wxButton does not implement GetSizeFromText
389 //set button minimum size so that largest text fits
390 mPlayToggleBtn->SetLabel(_("Stop &Preview"));
391 auto a = mPlayToggleBtn->GetBestSize();
392 mPlayToggleBtn->SetLabel(_("&Preview"));
393 auto b = mPlayToggleBtn->GetBestSize();
394 mPlayToggleBtn->SetMinSize(a.x > b.x ? a : b);
395 }
396 }
397
399 {
400 mApplyBtn = S.Id(wxID_APPLY)
401 .AddButton( XXO("&Apply"),
402 wxALIGN_CENTER | wxTOP | wxBOTTOM );
403 mApplyBtn->SetDefault();
404 }
405
407 {
408 mDebugBtn = S.Id(eDebugID)
409 .AddButton( XXO("Debu&g"),
410 wxALIGN_CENTER | wxTOP | wxBOTTOM );
411 }
412 }
413 S.EndHorizontalLay();
414 }
415 S.EndPanel();
416}
417
419{
420 mEnabled = mpAccess->Get().extra.GetActive();
421
422 mRealtimeEnabledBM = theTheme.Bitmap(bmpEffectOn);
423 mRealtimeDisabledBM = theTheme.Bitmap(bmpEffectOff);
424
425 // Build a "host" dialog, framing a panel that the client fills in.
426 // The frame includes buttons to preview, apply, load and save presets, etc.
427 EffectPanel *w {};
428 ShuttleGui S{ this, eIsCreating };
429 {
430 // Make the panel for the client
431 Destroy_ptr<EffectPanel> uw{ safenew EffectPanel( S.GetParent() ) };
432 RTL_WORKAROUND(uw.get());
433
434 // Try to give the window a sensible default/minimum size
435 uw->SetMinSize(wxSize(wxMax(600, mParent->GetSize().GetWidth() * 2 / 3),
436 mParent->GetSize().GetHeight() / 2));
437
438 // Let the client add things to the panel
439 ShuttleGui S1{ uw.get(), eIsCreating };
441 if (!mpValidator)
442 return false;
443
444 BuildButtonBar(S, mpValidator->IsGraphicalUI());
445
446 S.StartHorizontalLay( wxEXPAND );
447 {
448 S.Prop( 1 )
449 .Position(wxEXPAND)
450 .AddWindow((w = uw.release()));
451 }
452 S.EndHorizontalLay();
453 }
454
455 Layout();
456 Fit();
457 Center();
458
460
461 w->SetAccept(!mIsGUI);
462
463 if (!mIsGUI)
464 {
465 w->SetFocus();
466 }
467 else if (!IsOpenedFromEffectPanel())
468 {
469 mApplyBtn->SetFocus();
470 }
471
473
474 SetMinSize(GetSize());
475 return true;
476}
477
479{
480 return !IsModal();
481}
482
483
484void EffectUIHost::OnInitDialog(wxInitDialogEvent & evt)
485{
486 // Do default handling
487 wxDialogWrapper::OnInitDialog(evt);
488
489#if wxCHECK_VERSION(3, 0, 0)
490 //#warning "check to see if this still needed in wx3"
491#endif
492
493 // Pure hackage coming down the pike...
494 //
495 // I have no idea why, but if a wxTextCtrl is the first control in the
496 // panel, then its contents will not be automatically selected when the
497 // dialog is displayed.
498 //
499 // So, we do the selection manually.
500 wxTextCtrl *focused = wxDynamicCast(FindFocus(), wxTextCtrl);
501 if (focused)
502 {
503 focused->SelectAll();
504 }
505}
506
507void EffectUIHost::OnErase(wxEraseEvent & WXUNUSED(evt))
508{
509 // Ignore it
510}
511
512void EffectUIHost::OnPaint(wxPaintEvent & WXUNUSED(evt))
513{
514 wxPaintDC dc(this);
515
516 dc.Clear();
517}
518
519void EffectUIHost::OnClose(wxCloseEvent & WXUNUSED(evt))
520{
521 if (mPlaying)
522 StopPlayback();
523
524 DoCancel();
526
527 if (mpValidator)
528 mpValidator->OnClose();
529
530 Hide();
531 Destroy();
532
533#if wxDEBUG_LEVEL
534 mClosed = true;
535#endif
536}
537
538void EffectUIHost::OnApply(wxCommandEvent & evt)
539{
540 auto &project = mProject;
541
542 // On wxGTK (wx2.8.12), the default action is still executed even if
543 // the button is disabled. This appears to affect all wxDialogs, not
544 // just our Effects dialogs. So, this is a only temporary workaround
545 // for legacy effects that disable the OK button. Hopefully this has
546 // been corrected in wx3.
547 if (!mApplyBtn->IsEnabled())
548 {
549 return;
550 }
551
552 if (mPlaying)
553 StopPlayback();
554
555 // Honor the "select all if none" preference...a little hackish, but whatcha gonna do...
556 if (!mIsBatch &&
560 {
561 auto flags = AlwaysEnabledFlag;
562 bool allowed =
565 flags,
567 if (!allowed)
568 return;
569 }
570
571 if (!TransferDataFromWindow() ||
572 // This is the main place where there is a side-effect on the config
573 // file to remember the last-used settings of an effect, just before
574 // applying the effect destructively.
577 return;
578
579 if (IsModal())
580 {
581 mDismissed = true;
582
583 EndModal(evt.GetId());
584
585 Close();
586
587 return;
588 }
589
590 // Progress dialog no longer yields, so this "shouldn't" be necessary (yet to be proven
591 // for sure), but it is a nice visual cue that something is going on.
592 mApplyBtn->Disable();
593 auto cleanup = finally( [&] { mApplyBtn->Enable(); } );
594
595 CommandContext context( project );
596 // This is absolute hackage...but easy and I can't think of another way just now.
597 //
598 // It should callback to the EffectManager to kick off the processing
601}
602
604{
605 if (!mDismissed) {
606 if (!mHadPriorState) {
607 // For the destructive effect dialog only
608 // Restore effect state from last updated preferences
609 mpAccess->ModifySettings([&](EffectSettings &settings) {
610 // ignore failure
611 return mEffectUIHost.GetDefinition().LoadUserPreset(
612 CurrentSettingsGroup(), settings).value_or(nullptr);
613 });
614 }
615 if (IsModal())
616 EndModal(0);
617 else
618 Hide();
619
620 mDismissed = true;
621 }
622}
623
624void EffectUIHost::OnCancel(wxCommandEvent & WXUNUSED(evt))
625{
626 DoCancel();
627 Close();
628}
629
630void EffectUIHost::OnDebug(wxCommandEvent & evt)
631{
632 OnApply(evt);
633}
634
635namespace {
637{
638 static const auto specialVersion = XO("n/a");
639 auto result = definition.GetVersion();
640 if (result == specialVersion.MSGID())
641 result = specialVersion.Translation();
642 return result;
643}
644}
645
646void EffectUIHost::OnMenu(wxCommandEvent & WXUNUSED(evt))
647{
648 wxMenu menu;
649 menu.Bind(wxEVT_MENU, [](auto&){}, kUserPresetsDummyID);
650 menu.Bind(wxEVT_MENU, [](auto&){}, kDeletePresetDummyID);
652
653 if (mUserPresets.size() == 0)
654 {
655 menu.Append(kUserPresetsDummyID, _("User Presets"))->Enable(false);
656 }
657 else
658 {
659 auto sub = std::make_unique<wxMenu>();
660 for (size_t i = 0, cnt = mUserPresets.size(); i < cnt; i++)
661 {
662 sub->Append(kUserPresetsID + i, mUserPresets[i]);
663 }
664 menu.Append(0, _("User Presets"), sub.release());
665 }
666
667 menu.Append(kSaveAsID, _("Save Preset..."));
668
669 if (mUserPresets.size() == 0)
670 {
671 menu.Append(kDeletePresetDummyID, _("Delete Preset"))->Enable(false);
672 }
673 else
674 {
675 auto sub = std::make_unique<wxMenu>();
676 for (size_t i = 0, cnt = mUserPresets.size(); i < cnt; i++)
677 {
678 sub->Append(kDeletePresetID + i, mUserPresets[i]);
679 }
680 menu.Append(0, _("Delete Preset"), sub.release());
681 }
682
683 menu.AppendSeparator();
684
686
687 {
688 auto sub = std::make_unique<wxMenu>();
689 sub->Append(kDefaultsID, _("Defaults"));
690 if (factory.size() > 0)
691 {
692 sub->AppendSeparator();
693 for (size_t i = 0, cnt = factory.size(); i < cnt; i++)
694 {
695 auto label = factory[i];
696 if (label.empty())
697 {
698 label = _("None");
699 }
700
701 sub->Append(kFactoryPresetsID + i, label);
702 }
703 }
704 menu.Append(0, _("Factory Presets"), sub.release());
705 }
706
707 menu.AppendSeparator();
708 menu.Append(kImportID, _("Import..."))->Enable(mClient.CanExportPresets());
709 menu.Append(kExportID, _("Export..."))->Enable(mClient.CanExportPresets());
710 menu.AppendSeparator();
711 menu.Append(kOptionsID, _("Options..."))->Enable(mClient.HasOptions());
712 menu.AppendSeparator();
713
714 {
715 auto sub = std::make_unique<wxMenu>();
716
717 auto &definition = mEffectUIHost.GetDefinition();
718 sub->Append(kDummyID, wxString::Format(_("Type: %s"),
719 ::wxGetTranslation( definition.GetFamily().Translation() )));
720 sub->Append(kDummyID, wxString::Format(_("Name: %s"), definition.GetName().Translation()));
721 sub->Append(kDummyID, wxString::Format(_("Version: %s"),
722 GetVersionForDisplay(definition)));
723 sub->Append(kDummyID, wxString::Format(_("Vendor: %s"), definition.GetVendor().Translation()));
724 sub->Append(kDummyID, wxString::Format(_("Description: %s"), definition.GetDescription().Translation()));
725 sub->Bind(wxEVT_MENU, [](auto&){}, kDummyID);
726
727 menu.Append(0, _("About"), sub.release());
728 }
729
730 wxWindow *btn = FindWindow(kMenuID);
731 wxRect r = btn->GetRect();
732 BasicMenu::Handle{ &menu }.Popup(
734 { r.GetLeft(), r.GetBottom() }
735 );
736}
737
738void EffectUIHost::OnEnable(wxCommandEvent & WXUNUSED(evt))
739{
741
742 auto mpState = mwState.lock();
743 if (mpState)
744 mpState->SetActive(mEnabled);
745
747}
748
749void EffectUIHost::OnPlay(wxCommandEvent & WXUNUSED(evt))
750{
752 {
754 return;
755
757
758 return;
759 }
760
761 if (mPlaying)
762 {
763 StopPlayback();
764 }
765 else
766 {
767 auto &viewInfo = ViewInfo::Get( mProject );
768 const auto &selectedRegion = viewInfo.selectedRegion;
769 const auto &playRegion = viewInfo.playRegion;
770 if ( playRegion.Active() )
771 {
772 mRegion.setTimes(playRegion.GetStart(), playRegion.GetEnd());
773 mPlayPos = mRegion.t0();
774 }
775 else if (selectedRegion.t0() != mRegion.t0() ||
776 selectedRegion.t1() != mRegion.t1())
777 {
778 mRegion = selectedRegion;
779 mPlayPos = mRegion.t0();
780 }
781
782 if (mPlayPos > mRegion.t1())
783 {
784 mPlayPos = mRegion.t1();
785 }
786
787 auto &projectAudioManager = ProjectAudioManager::Get( mProject );
788 projectAudioManager.PlayPlayRegion(
792 }
793}
794
796{
797 if (evt.on) {
798 if (evt.pProject != &mProject)
799 mDisableTransport = true;
800 else
801 mPlaying = true;
802 }
803 else {
804 mDisableTransport = false;
805 mPlaying = false;
806 }
807
808 if (mPlaying) {
810 mPlayPos = mRegion.t0();
811 }
813}
814
816{
817 if (evt.on) {
818 if (evt.pProject != &mProject)
819 mDisableTransport = true;
820 else
821 mCapturing = true;
822 }
823 else {
824 mDisableTransport = false;
825 mCapturing = false;
826 }
828}
829
830void EffectUIHost::OnUserPreset(wxCommandEvent & evt)
831{
832 int preset = evt.GetId() - kUserPresetsID;
833
834 mpAccess->ModifySettings([&](EffectSettings &settings){
835 // ignore failure
836 return mEffectUIHost.GetDefinition().LoadUserPreset(
837 UserPresetsGroup(mUserPresets[preset]), settings).value_or(nullptr);
838 });
840 return;
841}
842
843void EffectUIHost::OnFactoryPreset(wxCommandEvent & evt)
844{
845 mpAccess->ModifySettings([&](EffectSettings &settings){
847 return mEffectUIHost.GetDefinition().LoadFactoryPreset(
848 evt.GetId() - kFactoryPresetsID, settings).value_or(nullptr);
849 });
851 return;
852}
853
854void EffectUIHost::OnDeletePreset(wxCommandEvent & evt)
855{
856 auto preset = mUserPresets[evt.GetId() - kDeletePresetID];
857
858 int res = AudacityMessageBox(
859 XO("Are you sure you want to delete \"%s\"?").Format( preset ),
860 XO("Delete Preset"),
861 wxICON_QUESTION | wxYES_NO);
862 if (res == wxYES)
863 {
866 }
867
869
870 return;
871}
872
873void EffectUIHost::OnSaveAs(wxCommandEvent & WXUNUSED(evt))
874{
875 wxTextCtrl *text;
876 wxString name;
877 wxDialogWrapper dlg(this, wxID_ANY, XO("Save Preset"));
878
879 ShuttleGui S(&dlg, eIsCreating);
880
881 S.StartPanel();
882 {
883 S.StartVerticalLay(1);
884 {
885 S.StartHorizontalLay(wxALIGN_LEFT, 0);
886 {
887 text = S.AddTextBox(XXO("Preset name:"), name, 30);
888 }
889 S.EndHorizontalLay();
890 S.SetBorder(10);
891 S.AddStandardButtons();
892 }
893 S.EndVerticalLay();
894 }
895 S.EndPanel();
896
897 dlg.SetSize(dlg.GetSizer()->GetMinSize());
898 dlg.Center();
899 dlg.Fit();
900
901 while (true)
902 {
903 int rc = dlg.ShowModal();
904
905 if (rc != wxID_OK)
906 {
907 break;
908 }
909
910 name = text->GetValue();
911 if (name.empty())
912 {
914 this,
915 XO("You must specify a name"),
916 XO("Save Preset") );
917 md.Center();
918 md.ShowModal();
919 continue;
920 }
921
922 if ( make_iterator_range( mUserPresets ).contains( name ) )
923 {
925 this,
926 XO("Preset already exists.\n\nReplace?"),
927 XO("Save Preset"),
928 wxYES_NO | wxCANCEL | wxICON_EXCLAMATION );
929 md.Center();
930 int choice = md.ShowModal();
931 if (choice == wxID_CANCEL)
932 {
933 break;
934 }
935
936 if (choice == wxID_NO)
937 {
938 continue;
939 }
940 }
941
946
947 break;
948 }
949
950 return;
951}
952
953void EffectUIHost::OnImport(wxCommandEvent & WXUNUSED(evt))
954{
955 mpAccess->ModifySettings([&](EffectSettings &settings){
956 // ignore failure
957 return mClient.ImportPresets(settings).value_or(nullptr);
958 });
961
962 return;
963}
964
965void EffectUIHost::OnExport(wxCommandEvent & WXUNUSED(evt))
966{
967 // may throw
968 // exceptions are handled in AudacityApp::OnExceptionInMainLoop
971
972 return;
973}
974
975void EffectUIHost::OnOptions(wxCommandEvent & WXUNUSED(evt))
976{
978
979 return;
980}
981
982void EffectUIHost::OnDefaults(wxCommandEvent & WXUNUSED(evt))
983{
984 mpAccess->ModifySettings([&](EffectSettings &settings){
985 // ignore failure
986 return mEffectUIHost.GetDefinition().LoadFactoryDefaults(settings)
987 .value_or(nullptr);
988 });
990 return;
991}
992
993void EffectUIHost::OnIdle(wxIdleEvent &evt)
994{
995 evt.Skip();
996 if (mpAccess)
997 mpAccess->Flush();
998}
999
1000void EffectUIHost::OnCharHook(wxKeyEvent& evt)
1001{
1002 if (!IsEscapeKey(evt))
1003 {
1004 evt.Skip();
1005 return;
1006 }
1007
1009 Close();
1010 else
1011 {
1012 wxCommandEvent cancelEvt { wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL };
1013
1014 OnCancel(cancelEvt);
1015 }
1016}
1017
1019{
1020 return (mpTempProjectState == nullptr && mSupportsRealtime);
1021}
1022
1023wxBitmap EffectUIHost::CreateBitmap(const char * const xpm[], bool up, bool pusher)
1024{
1025 wxMemoryDC dc;
1026 wxBitmap pic(xpm);
1027
1028 wxBitmap mod(pic.GetWidth() + 6, pic.GetHeight() + 6, 24);
1029 dc.SelectObject(mod);
1030
1031#if defined(__WXGTK__)
1032 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND);
1033#else
1034 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
1035#endif
1036
1037 dc.SetBackground(wxBrush(newColour));
1038 dc.Clear();
1039
1040 int offset = 3;
1041 if (pusher)
1042 {
1043 if (!up)
1044 {
1045 offset += 1;
1046 }
1047 }
1048
1049 dc.DrawBitmap(pic, offset, offset, true);
1050
1051 dc.SelectObject(wxNullBitmap);
1052
1053 return mod;
1054}
1055
1057{
1058 if (mIsBatch)
1059 {
1060 return;
1061 }
1062
1064 {
1066 return;
1067 }
1068
1069 mApplyBtn->Enable(!mCapturing);
1070
1072 {
1074
1075 if (mPlaying)
1076 {
1077 /* i18n-hint: The access key "&P" should be the same in
1078 "Stop &Preview" and "Start &Preview" */
1079 mPlayToggleBtn->SetLabel(_("Stop &Preview"));
1080 mPlayToggleBtn->Refresh();
1081 }
1082 else
1083 {
1084 /* i18n-hint: The access key "&P" should be the same in
1085 "Stop &Preview" and "Start &Preview" */
1086 mPlayToggleBtn->SetLabel(_("&Preview"));
1087 mPlayToggleBtn->Refresh();
1088 }
1089 }
1090}
1091
1093{
1094 mUserPresets.clear();
1095
1098
1099 std::sort( mUserPresets.begin(), mUserPresets.end() );
1100
1101 return;
1102}
1103
1104std::shared_ptr<EffectInstance> EffectUIHost::InitializeInstance()
1105{
1106 // We are still constructing and the return initializes a const member
1107 std::shared_ptr<EffectInstance> result;
1108
1109 auto mpState = mwState.lock();
1110
1111 bool priorState = (mpState != nullptr);
1112 if (!priorState) {
1113 auto gAudioIO = AudioIO::Get();
1114 mDisableTransport = !gAudioIO->IsAvailable(mProject);
1115 mPlaying = gAudioIO->IsStreamActive(); // not exactly right, but will suffice
1116 mCapturing = gAudioIO->IsStreamActive() && gAudioIO->GetNumCaptureChannels() > 0 && !gAudioIO->IsMonitoring();
1117 }
1118
1120 if (!priorState)
1121 mwState = mpState = mpTempProjectState =
1123 if (mpState) {
1124 // Find the right instance to connect to the dialog
1125 if (!result) {
1126 result = mpState->GetInstance();
1127 if (result && !result->Init())
1128 result.reset();
1129 }
1130
1131 mpAccess2 = mpState->GetAccess();
1132 if (!(mpAccess2->IsSameAs(*mpAccess)))
1133 // Decorate the given access object
1134 mpAccess = std::make_shared<EffectSettingsAccessTee>(
1136
1137 mEffectStateSubscription = mpState->Subscribe([this](RealtimeEffectStateChange state) {
1140
1142 });
1143 }
1144
1145 if (!priorState) {
1147 switch (event.type) {
1148 case AudioIOEvent::PLAYBACK:
1149 OnPlayback(event); break;
1150 case AudioIOEvent::CAPTURE:
1151 OnCapture(event); break;
1152 default:
1153 break;
1154 }
1155 });
1156 }
1157
1158 mInitialized = true;
1159 }
1160 else {
1161 result = mEffectUIHost.MakeInstance();
1162 if (result && !result->Init())
1163 result.reset();
1164 }
1165
1166 return result;
1167}
1168
1170{
1172
1174 if (!IsOpenedFromEffectPanel()) {
1177 mpTempProjectState.reset();
1178 /*
1179 ProjectHistory::Get(mProject).PushState(
1180 XO("Removed %s effect").Format(mpState->GetEffect()->GetName()),
1181 XO("Removed Effect"),
1182 UndoPush::NONE
1183 );
1184 */
1185 }
1186 mInitialized = false;
1187 }
1188}
1189
1191{
1192 if (!mPlaying)
1193 return;
1194
1195 auto gAudioIO = AudioIO::Get();
1196 mPlayPos = gAudioIO->GetStreamTime();
1197 auto& projectAudioManager = ProjectAudioManager::Get(mProject);
1198 projectAudioManager.Stop();
1199}
1200
1203 EffectSettingsAccess &access)
1204{
1205 // Make sure there is an associated project, whose lifetime will
1206 // govern the lifetime of the dialog, even when the dialog is
1207 // non-modal, as for realtime effects
1208 auto project = FindProjectFromWindow(&parent);
1209 if ( !project )
1210 return {};
1211 std::shared_ptr<EffectInstance> pInstance;
1213 *project, host, client, pInstance, access } };
1214 if (!pInstance) {
1215 dlg->SetClosed();
1216 return {};
1217 }
1218 if (dlg->Initialize()) {
1219 auto pValidator = dlg->GetValidator();
1220 // release() is safe because parent will own it
1221 return { dlg.release(), pInstance, pValidator };
1222 }
1223 return {};
1224}
1225
1226#include "PluginManager.h"
1227#include "ProjectRate.h"
1228#include "../ProjectWindow.h"
1229#include "../SelectUtilities.h"
1230#include "../TrackPanel.h"
1231#include "../WaveTrack.h"
1232#include "../commands/CommandManager.h"
1233
1237// parameters, whether to save the state to history and whether to allow
1239
1240/* static */ bool EffectUI::DoEffect(
1241 const PluginID & ID, const CommandContext &context, unsigned flags )
1242{
1243 AudacityProject &project = context.project;
1244 auto &tracks = TrackList::Get( project );
1245 auto &trackPanel = TrackPanel::Get( project );
1246 auto &trackFactory = WaveTrackFactory::Get( project );
1247 auto rate = ProjectRate::Get(project).GetRate();
1248 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
1249 auto &commandManager = CommandManager::Get( project );
1250 auto &window = ProjectWindow::Get( project );
1251
1252 const PluginDescriptor *plug = PluginManager::Get().GetPlugin(ID);
1253 if (!plug)
1254 return false;
1255
1256 EffectType type = plug->GetEffectType();
1257
1258 // Make sure there's no activity since the effect is about to be applied
1259 // to the project's tracks. Mainly for Apply during RTP, but also used
1260 // for batch commands
1261 if (flags & EffectManager::kConfigured)
1262 {
1263 ProjectAudioManager::Get( project ).Stop();
1264 //Don't Select All if repeating Generator Effect
1265 if (!(flags & EffectManager::kConfigured)) {
1267 }
1268 }
1269
1270 auto nTracksOriginally = tracks.size();
1271 wxWindow *focus = wxWindow::FindFocus();
1272 wxWindow *parent = nullptr;
1273 if (focus != nullptr) {
1274 parent = focus->GetParent();
1275 }
1276
1277 bool success = false;
1278 auto cleanup = finally( [&] {
1279
1280 if (!success) {
1281 // For now, we're limiting realtime preview to a single effect, so
1282 // make sure the menus reflect that fact that one may have just been
1283 // opened.
1284 MenuManager::Get(project).UpdateMenus( false );
1285 }
1286
1287 } );
1288
1289 int count = 0;
1290 bool clean = true;
1291 for (auto t : tracks.Selected< const WaveTrack >()) {
1292 if (t->GetEndTime() != 0.0)
1293 clean = false;
1294 count++;
1295 }
1296
1298
1299 em.SetSkipStateFlag( false );
1300 success = false;
1301 if (auto effect = em.GetEffect(ID)) {
1302 if (const auto pSettings = em.GetDefaultSettings(ID)) {
1303 const auto pAccess =
1304 std::make_shared<SimpleEffectSettingsAccess>(*pSettings);
1305 pAccess->ModifySettings([&](EffectSettings &settings){
1306 success = effect->DoEffect(settings,
1307 rate,
1308 &tracks,
1309 &trackFactory,
1310 selectedRegion,
1311 flags,
1312 &window,
1313 (flags & EffectManager::kConfigured) == 0
1315 : nullptr,
1316 pAccess);
1317 return nullptr;
1318 });
1319 }
1320 }
1321
1322 if (!success)
1323 return false;
1324
1325 if (em.GetSkipStateFlag())
1326 flags = flags | EffectManager::kSkipState;
1327
1328 if (!(flags & EffectManager::kSkipState))
1329 {
1330 auto shortDesc = em.GetCommandName(ID);
1331 auto longDesc = em.GetCommandDescription(ID);
1332 ProjectHistory::Get( project ).PushState(longDesc, shortDesc);
1333 }
1334
1335 if (!(flags & EffectManager::kDontRepeatLast))
1336 {
1337 // Remember a successful generator, effect, analyzer, or tool Process
1338 auto shortDesc = em.GetCommandName(ID);
1339 /* i18n-hint: %s will be the name of the effect which will be
1340 * repeated if this menu item is chosen */
1341 auto lastEffectDesc = XO("Repeat %s").Format(shortDesc);
1342 auto& menuManager = MenuManager::Get(project);
1343 switch ( type ) {
1344 case EffectTypeGenerate:
1345 commandManager.Modify(wxT("RepeatLastGenerator"), lastEffectDesc);
1346 menuManager.mLastGenerator = ID;
1347 menuManager.mRepeatGeneratorFlags = EffectManager::kConfigured;
1348 break;
1349 case EffectTypeProcess:
1350 commandManager.Modify(wxT("RepeatLastEffect"), lastEffectDesc);
1351 menuManager.mLastEffect = ID;
1352 menuManager.mRepeatEffectFlags = EffectManager::kConfigured;
1353 break;
1354 case EffectTypeAnalyze:
1355 commandManager.Modify(wxT("RepeatLastAnalyzer"), lastEffectDesc);
1356 menuManager.mLastAnalyzer = ID;
1357 menuManager.mLastAnalyzerRegistration = MenuCreator::repeattypeplugin;
1358 menuManager.mRepeatAnalyzerFlags = EffectManager::kConfigured;
1359 break;
1360 case EffectTypeTool:
1361 commandManager.Modify(wxT("RepeatLastTool"), lastEffectDesc);
1362 menuManager.mLastTool = ID;
1363 menuManager.mLastToolRegistration = MenuCreator::repeattypeplugin;
1364 menuManager.mRepeatToolFlags = EffectManager::kConfigured;
1365 if (shortDesc == NYQUIST_PROMPT_NAME) {
1366 menuManager.mRepeatToolFlags = EffectManager::kRepeatNyquistPrompt; //Nyquist Prompt is not configured
1367 }
1368 break;
1369 }
1370 }
1371
1372 //STM:
1373 //The following automatically re-zooms after sound was generated.
1374 // IMO, it was disorienting, removing to try out without re-fitting
1375 //mchinen:12/14/08 reapplying for generate effects
1376 if (type == EffectTypeGenerate)
1377 {
1378 if (count == 0 || (clean && selectedRegion.t0() == 0.0))
1379 window.DoZoomFit();
1380 // trackPanel->Refresh(false);
1381 }
1382
1383 // PRL: RedrawProject explicitly because sometimes history push is skipped
1384 window.RedrawProject();
1385
1386 if (focus != nullptr && focus->GetParent()==parent) {
1387 focus->SetFocus();
1388 }
1389
1390 // A fix for Bug 63
1391 // New tracks added? Scroll them into view so that user sees them.
1392 // Don't care what track type. An analyser might just have added a
1393 // Label track and we want to see it.
1394 if( tracks.size() > nTracksOriginally ){
1395 // 0.0 is min scroll position, 1.0 is max scroll position.
1396 trackPanel.VerticalScroll( 1.0 );
1397 }
1398 else {
1399 auto pTrack = *tracks.Selected().begin();
1400 if (!pTrack)
1401 pTrack = *tracks.Any().begin();
1402 if (pTrack) {
1403 TrackFocus::Get(project).Set(pTrack);
1404 pTrack->EnsureVisible();
1405 }
1406 }
1407
1408 return true;
1409}
1410
1412BEGIN_EVENT_TABLE(EffectDialog, wxDialogWrapper)
1415
1416EffectDialog::EffectDialog(wxWindow * parent,
1417 const TranslatableString & title,
1418 int type,
1419 int flags,
1420 int additionalButtons)
1421: wxDialogWrapper(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, flags)
1422{
1423 mType = type;
1424 mAdditionalButtons = additionalButtons;
1425}
1426
1428{
1429 long buttons = eOkButton;
1431 {
1432 buttons |= eCancelButton;
1433 if (mType == EffectTypeProcess)
1434 {
1435 buttons |= ePreviewButton;
1436 }
1437 }
1438
1439 ShuttleGui S(this, eIsCreating);
1440
1441 S.SetBorder(5);
1442 S.StartVerticalLay(true);
1443 {
1445 S.AddStandardButtons(buttons|mAdditionalButtons);
1446 }
1447 S.EndVerticalLay();
1448
1449 Layout();
1450 Fit();
1451 SetMinSize(GetSize());
1452 Center();
1453}
1454
1459{
1460 return;
1461}
1462
1464{
1467
1468 return true;
1469}
1470
1472{
1475
1476 return true;
1477}
1478
1480{
1481 return true;
1482}
1483
1484void EffectDialog::OnPreview(wxCommandEvent & WXUNUSED(evt))
1485{
1486 return;
1487}
1488
1489void EffectDialog::OnOk(wxCommandEvent & WXUNUSED(evt))
1490{
1491 // On wxGTK (wx2.8.12), the default action is still executed even if
1492 // the button is disabled. This appears to affect all wxDialogs, not
1493 // just our Effects dialogs. So, this is a only temporary workaround
1494 // for legacy effects that disable the OK button. Hopefully this has
1495 // been corrected in wx3.
1496 if (FindWindow(wxID_OK)->IsEnabled() && Validate() && TransferDataFromWindow())
1497 {
1498 EndModal(wxID_OK);
1499 }
1500
1501 return;
1502}
1503
1505#include "RealtimeEffectState.h"
1506static RealtimeEffectState::EffectFactory::Scope
1508
1509/* The following registration objects need a home at a higher level to avoid
1510 dependency either way between WaveTrack or RealtimeEffectList, which need to
1511 be in different libraries that do not depend either on the other.
1512
1513 WaveTrack, like AudacityProject, has a registry for attachment of serializable
1514 data. RealtimeEffectList exposes an interface for serialization. This is
1515 where we connect them.
1516 */
1517#include "RealtimeEffectList.h"
1520 [](AudacityProject &project) { return &RealtimeEffectList::Get(project); }
1521};
1522
1524[](const AudacityProject &project, XMLWriter &xmlFile){
1525 RealtimeEffectList::Get(project).WriteXML(xmlFile);
1526} };
1527
1530 [](WaveTrack &track) { return &RealtimeEffectList::Get(track); }
1531};
1532
1534[](const WaveTrack &track, auto &xmlFile) {
1535 if (track.IsLeader())
1536 RealtimeEffectList::Get(track).WriteXML(xmlFile);
1537} };
EVT_MENU(OnSetPlayRegionToSelectionID, AdornedRulerPanel::OnSetPlayRegionToSelection) EVT_COMMAND(OnTogglePinnedStateID
wxEVT_COMMAND_BUTTON_CLICKED
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.
END_EVENT_TABLE()
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:35
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
Definition: Distortion.cpp:82
RegistryPath UserPresetsGroup(const RegistryPath &name)
Compute part of a registry path, given a name which may be empty.
const RegistryPath & CurrentSettingsGroup()
Component of a configuration key path, for last-used destructive settings.
EffectType
@ EffectTypeAnalyze
@ EffectTypeGenerate
@ EffectTypeTool
@ EffectTypeProcess
wxString PluginID
Definition: EffectManager.h:30
static PluginID GetID(EffectPlugin &effect)
Definition: EffectUI.cpp:31
static ProjectFileIORegistry::ObjectReaderEntry projectAccessor
Definition: EffectUI.cpp:1518
static ProjectFileIORegistry::ObjectWriterEntry projectWriter
Definition: EffectUI.cpp:1523
static const int kImportID
Definition: EffectUI.cpp:121
static const int kExportID
Definition: EffectUI.cpp:122
static WaveTrackIORegistry::ObjectWriterEntry waveTrackWriter
Definition: EffectUI.cpp:1533
static const int kOptionsID
Definition: EffectUI.cpp:124
static const int kCaptureID
Definition: EffectUI.cpp:131
static RealtimeEffectState::EffectFactory::Scope scope
Inject a factory for realtime effects.
Definition: EffectUI.cpp:1507
static const int kDefaultsID
Definition: EffectUI.cpp:123
static const int kDummyID
Definition: EffectUI.cpp:119
static const int kPlaybackID
Definition: EffectUI.cpp:130
static WaveTrackIORegistry::ObjectReaderEntry waveTrackAccessor
Definition: EffectUI.cpp:1528
static const int kPlayID
Definition: EffectUI.cpp:129
static const int kSaveAsID
Definition: EffectUI.cpp:120
static const int kUserPresetsDummyID
Definition: EffectUI.cpp:125
static const int kFactoryPresetsID
Definition: EffectUI.cpp:134
static const int kEnableID
Definition: EffectUI.cpp:128
static const int kMenuID
Definition: EffectUI.cpp:127
static const int kDeletePresetDummyID
Definition: EffectUI.cpp:126
static const int kUserPresetsID
Definition: EffectUI.cpp:132
static const int kDeletePresetID
Definition: EffectUI.cpp:133
#define RTL_WORKAROUND(pWnd)
Definition: GUISettings.h:20
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define _(s)
Definition: Internat.h:75
#define safenew
Definition: MemoryX.h:10
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:431
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:162
static const auto title
#define NYQUIST_PROMPT_NAME
AudioIOStartStreamOptions DefaultPlayOptions(AudacityProject &project, bool newDefault)
an object holding per-project preferred sample rate
AudacityProject * FindProjectFromWindow(wxWindow *pWindow)
RealtimeEffectStateChange
EffectReverbSettings preset
Definition: Reverb.cpp:46
@ eIsSettingToDialog
Definition: ShuttleGui.h:41
@ eIsCreating
Definition: ShuttleGui.h:39
@ eIsGettingFromDialog
Definition: ShuttleGui.h:40
@ eOkButton
Definition: ShuttleGui.h:597
@ eCancelButton
Definition: ShuttleGui.h:598
@ ePreviewButton
Definition: ShuttleGui.h:602
@ eDebugID
Definition: ShuttleGui.h:616
TranslatableString label
Definition: TagsEditor.cpp:163
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:87
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:89
static AudioIO * Get()
Definition: AudioIO.cpp:133
std::shared_ptr< RealtimeEffectState > AddState(AudacityProject &project, Track *pTrack, const PluginID &id)
Forwards to RealtimeEffectManager::AddState with proper init scope.
Definition: AudioIO.cpp:352
void RemoveState(AudacityProject &project, Track *pTrack, std::shared_ptr< RealtimeEffectState > pState)
Forwards to RealtimeEffectManager::RemoveState with proper init scope.
Definition: AudioIO.cpp:373
void Popup(const BasicUI::WindowPlacement &window, const Point &pos={})
Display the menu at pos, invoke at most one action, then hide it.
Definition: BasicMenu.cpp:209
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
static CommandManager & Get(AudacityProject &project)
virtual wxString GetVersion() const =0
TranslatableString GetName() const
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:1479
bool TransferDataToWindow() override
Definition: EffectUI.cpp:1463
bool TransferDataFromWindow() override
Definition: EffectUI.cpp:1471
virtual void OnPreview(wxCommandEvent &evt)
Definition: EffectUI.cpp:1484
virtual void OnOk(wxCommandEvent &evt)
Definition: EffectUI.cpp:1489
virtual void PopulateOrExchange(ShuttleGui &S)
Definition: EffectUI.cpp:1458
int mAdditionalButtons
Definition: EffectUI.h:213
virtual std::shared_ptr< EffectInstance > MakeInstance() const =0
Make an object maintaining short-term state of an Effect.
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:55
void SetAccept(bool accept)
Definition: EffectUI.cpp:77
bool AcceptsFocus() const override
Definition: EffectUI.cpp:63
bool AcceptsFocusFromKeyboard() const override
Definition: EffectUI.cpp:69
EffectPanel(wxWindow *parent)
Definition: EffectUI.cpp:45
bool mAcceptsFocus
Definition: EffectUI.cpp:83
Factory of instances of an effect and of dialogs to control them.
Definition: EffectPlugin.h:54
virtual bool TransferDataToWindow(const EffectSettings &settings)=0
Update controls for the settings.
virtual bool TransferDataFromWindow(EffectSettings &settings)=0
Update the given settings from controls.
virtual const EffectSettingsManager & GetDefinition() const =0
virtual bool IsBatchProcessing() const =0
virtual void Preview(EffectSettingsAccess &access, bool dryOnly)=0
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.
EffectUIClientInterface is an abstract base class to populate a UI and validate UI values....
virtual std::unique_ptr< EffectUIValidator > PopulateUI(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs)=0
Adds controls to a panel that is given as the parent window of S
virtual OptionalMessage ImportPresets(EffectSettings &settings)=0
virtual void ShowOptions()=0
virtual void ExportPresets(const EffectSettings &settings) const =0
virtual bool CanExportPresets()=0
virtual bool HasOptions()=0
EffectPlugin & mEffectUIHost
Definition: EffectUI.h:120
void OnEnable(wxCommandEvent &evt)
Definition: EffectUI.cpp:738
void OnFactoryPreset(wxCommandEvent &evt)
Definition: EffectUI.cpp:843
RegistryPaths mUserPresets
Definition: EffectUI.h:130
void OnDefaults(wxCommandEvent &evt)
Definition: EffectUI.cpp:982
Observer::Subscription mAudioIOSubscription
Definition: EffectUI.h:116
bool HandleCommandKeystrokes() override
Definition: EffectUI.cpp:478
void UpdateControls()
Definition: EffectUI.cpp:1056
wxButton * mEnableBtn
Definition: EffectUI.h:138
wxPanel * BuildButtonBar(wxWindow *parent, bool graphicalUI)
bool mIsBatch
Definition: EffectUI.h:134
bool mCapturing
Definition: EffectUI.h:149
wxButton * mMenuBtn
Definition: EffectUI.h:137
virtual ~EffectUIHost()
Definition: EffectUI.cpp:261
std::unique_ptr< EffectUIValidator > mpValidator
Definition: EffectUI.h:165
void OnErase(wxEraseEvent &evt)
Definition: EffectUI.cpp:507
void OnPlayback(AudioIOEvent)
Definition: EffectUI.cpp:795
void CleanupRealtime()
Definition: EffectUI.cpp:1169
AudacityProject & mProject
Definition: EffectUI.h:118
std::shared_ptr< RealtimeEffectState > mpTempProjectState
Definition: EffectUI.h:128
bool mIsGUI
Definition: EffectUI.h:133
bool TransferDataToWindow() override
Definition: EffectUI.cpp:273
EffectPlugin::EffectSettingsAccessPtr mpAccess
Definition: EffectUI.h:124
const EffectOutputs *const mpOutputs
Definition: EffectUI.h:163
void OnUserPreset(wxCommandEvent &evt)
Definition: EffectUI.cpp:830
void OnDeletePreset(wxCommandEvent &evt)
Definition: EffectUI.cpp:854
bool mPlaying
Definition: EffectUI.h:148
void OnIdle(wxIdleEvent &evt)
Definition: EffectUI.cpp:993
wxButton * mPlayToggleBtn
Definition: EffectUI.h:140
void StopPlayback()
Definition: EffectUI.cpp:1190
int ShowModal() override
Definition: EffectUI.cpp:322
bool mDisableTransport
Definition: EffectUI.h:147
Observer::Subscription mEffectStateSubscription
Definition: EffectUI.h:116
EffectUIClientInterface & mClient
Definition: EffectUI.h:121
SelectedRegion mRegion
Definition: EffectUI.h:151
void DoCancel()
Definition: EffectUI.cpp:603
void OnCapture(AudioIOEvent)
Definition: EffectUI.cpp:815
double mPlayPos
Definition: EffectUI.h:152
void OnClose(wxCloseEvent &evt)
Definition: EffectUI.cpp:519
void OnExport(wxCommandEvent &evt)
Definition: EffectUI.cpp:965
void OnSaveAs(wxCommandEvent &evt)
Definition: EffectUI.cpp:873
wxButton * mApplyBtn
Definition: EffectUI.h:136
const bool mHadPriorState
Definition: EffectUI.h:155
void OnOptions(wxCommandEvent &evt)
Definition: EffectUI.cpp:975
void LoadUserPresets()
Definition: EffectUI.cpp:1092
void OnInitDialog(wxInitDialogEvent &evt)
Definition: EffectUI.cpp:484
EffectUIHost(wxWindow *parent, AudacityProject &project, EffectPlugin &effect, EffectUIClientInterface &client, std::shared_ptr< EffectInstance > &pInstance, EffectSettingsAccess &access, const std::shared_ptr< RealtimeEffectState > &pPriorState={})
Definition: EffectUI.cpp:225
void OnMenu(wxCommandEvent &evt)
Definition: EffectUI.cpp:646
void OnDebug(wxCommandEvent &evt)
Definition: EffectUI.cpp:630
void OnCharHook(wxKeyEvent &evt)
Definition: EffectUI.cpp:1000
bool mEnabled
Definition: EffectUI.h:145
EffectPlugin::EffectSettingsAccessPtr mpAccess2
Definition: EffectUI.h:125
void OnImport(wxCommandEvent &evt)
Definition: EffectUI.cpp:953
std::shared_ptr< EffectInstance > InitializeInstance()
Definition: EffectUI.cpp:1104
void OnApply(wxCommandEvent &evt)
Definition: EffectUI.cpp:538
const bool mSupportsRealtime
Definition: EffectUI.h:132
bool Initialize()
Definition: EffectUI.cpp:418
void OnPlay(wxCommandEvent &evt)
Definition: EffectUI.cpp:749
const std::shared_ptr< EffectInstance > mpInstance
Definition: EffectUI.h:162
void OnCancel(wxCommandEvent &evt)
Definition: EffectUI.cpp:624
bool mInitialized
Definition: EffectUI.h:131
std::weak_ptr< RealtimeEffectState > mwState
Definition: EffectUI.h:126
wxWindow *const mParent
Definition: EffectUI.h:119
wxButton * mDebugBtn
Definition: EffectUI.h:139
wxBitmap CreateBitmap(const char *const xpm[], bool up, bool pusher)
Definition: EffectUI.cpp:1023
bool IsOpenedFromEffectPanel() const
Definition: EffectUI.cpp:1018
bool TransferDataFromWindow() override
Definition: EffectUI.cpp:283
wxBitmap mRealtimeDisabledBM
Definition: EffectUI.h:143
void OnPaint(wxPaintEvent &evt)
Definition: EffectUI.cpp:512
bool mDismissed
Definition: EffectUI.h:154
wxBitmap mRealtimeEnabledBM
Definition: EffectUI.h:142
Abstract base class used in importing a file.
@ repeattypeplugin
Definition: Menus.h:62
static MenuManager & Get(AudacityProject &project)
Definition: Menus.cpp:71
bool ReportIfActionNotAllowed(const TranslatableString &Name, CommandFlag &flags, CommandFlag flagsRqd)
Definition: Menus.cpp:705
void UpdateMenus(bool checkActive=true)
Definition: Menus.cpp:643
bool isPoint() const
Definition: ViewInfo.h:39
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)
const PluginDescriptor * GetPlugin(const PluginID &ID) const
static PluginManager & Get()
void Stop(bool stopStream=true)
static ProjectAudioManager & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
static ProjectWindow & Get(AudacityProject &project)
static RealtimeEffectList & Get(AudacityProject &project)
static const std::string & XMLTag()
void WriteXML(XMLWriter &xmlFile) const
Use only in the main thread, to avoid races.
Defines a selected portion of a project.
double t1() const
bool setTimes(double t0, double t1)
double t0() const
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
wxBitmap & Bitmap(int iIndex)
Track * Get()
void EnsureVisible(bool modifyState=false)
Definition: Track.cpp:97
bool IsLeader() const
Definition: Track.cpp:405
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:486
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:230
Holds a msgid for the translation catalog; may also bind format arguments.
static const TranslatableString Inaudible
A special string value that will have no screen reader pronunciation.
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:216
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:2810
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:26
void Set(EffectSettings &&settings, std::unique_ptr< Message > pMessage) override
const std::weak_ptr< EffectSettingsAccess > mwSide
Definition: EffectUI.cpp:176
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:175
void Flush() override
Make the last Set changes "persistent" in underlying storage.
Definition: EffectUI.cpp:212
bool IsSameAs(const EffectSettingsAccess &other) const override
Definition: EffectUI.cpp:219
void SetLabel(const TranslatableString &label)
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:194
AUDACITY_DLL_API bool DoEffect(const PluginID &ID, const CommandContext &context, unsigned flags)
'Repeat Last Effect'.
Definition: EffectUI.cpp:1240
AUDACITY_DLL_API DialogFactoryResults DialogFactory(wxWindow &parent, EffectPlugin &host, EffectUIClientInterface &client, EffectSettingsAccess &access)
Definition: EffectUI.cpp:1201
bool RemoveConfigSubgroup(const EffectDefinitionInterface &ident, PluginSettings::ConfigurationType type, const RegistryPath &group)
bool GetConfigSubgroups(const EffectDefinitionInterface &ident, PluginSettings::ConfigurationType type, const RegistryPath &group, RegistryPaths &subgroups)
void SelectAllIfNone(AudacityProject &project)
wxString GetVersionForDisplay(const EffectDefinitionInterface &definition)
Definition: EffectUI.cpp:636
static RegisteredToolbarFactory factory
bool on
Definition: AudioIO.h:75
enum AudioIOEvent::Type type
AudacityProject * pProject
Definition: AudioIO.h:69
Externalized state of a plug-in.
Typically statically constructed.
Window placement information for wxWidgetsBasicUI can be constructed from a wxWindow pointer.