Audacity 3.2.0
RealtimeEffectStateUI.cpp
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*!********************************************************************
3
4 Audacity: A Digital Audio Editor
5
6 RealtimeEffectStateUI.cpp
7
8 Dmitry Vedenko
9
10**********************************************************************/
12
13#include <cassert>
14
15#include "EffectEditor.h"
16#include "EffectUI.h"
17#include "EffectUIServices.h"
18#include "RealtimeEffectState.h"
19
20#include "EffectBase.h"
21#include "EffectManager.h"
22#include "UndoManager.h"
23#include "ProjectHistory.h"
24#include "ProjectWindow.h"
25
26namespace
27{
28const RealtimeEffectState::RegisteredFactory realtimeEffectStateUIFactory { [](auto& state)
29 { return std::make_unique<RealtimeEffectStateUI>(state); }
30};
31} // namespace
32
33
34BEGIN_EVENT_TABLE(RealtimeEffectStateUI, wxEvtHandler)
37
39 : mRealtimeEffectState(state)
40{
41}
42
44{
45 Hide();
46}
47
48bool RealtimeEffectStateUI::IsShown() const noexcept
49{
50 return mEffectUIHost != nullptr;
51}
52
54{
55 if (mEffectUIHost != nullptr && mEffectUIHost->IsShown())
56 {
57 // Bring the host to front
58 mEffectUIHost->Raise();
59 return;
60 }
61
62 const auto ID = mRealtimeEffectState.GetID();
63 const auto effectPlugin =
64 dynamic_cast<EffectBase*>(EffectManager::Get().GetEffect(ID));
65
66 if (effectPlugin == nullptr)
67 return;
68
69 const auto client = dynamic_cast<EffectUIServices *>(effectPlugin);
70
71 // Effect has no client interface
72 if (client == nullptr)
73 return;
74
75 auto& projectWindow = ProjectWindow::Get(project);
76
77 std::shared_ptr<EffectInstance> pInstance;
78
79 auto access = mRealtimeEffectState.GetAccess();
80
81 // EffectUIHost invokes shared_from_this on access
83 &projectWindow, project, *effectPlugin, *client, pInstance, *access,
84 mRealtimeEffectState.shared_from_this()));
85
86 if (!dlg->Initialize())
87 return;
88
89 // Dialog is owned by its parent now!
90 mEffectUIHost = dlg.release();
91
93
94 client->ShowClientInterface(*effectPlugin,
95 projectWindow, *mEffectUIHost, mEffectUIHost->GetEditor(), false);
96
97 // The dialog was modal? That shouldn't have happened
98 if (mEffectUIHost == nullptr || !mEffectUIHost->IsShown())
99 {
100 assert(false);
101 mEffectUIHost = {};
102 }
103
104 if (mEffectUIHost) {
105 mEffectUIHost->PushEventHandler(this);
107 }
108
109 mProjectWindowDestroyedSubscription = projectWindow.Subscribe(
111 // This achieves autosave on close of project before other important
112 // project state is destroyed
113 Hide(&project);
114 });
115
116 mParameterChangedSubscription = mEffectUIHost->GetEditor()->Subscribe(
117 [this](auto) { if (mpProject) { // This can be null if closing an effect without making changes.
118 UndoManager::Get(*mpProject).MarkUnsaved();
119 }
120 });
121}
122
124{
125 if (mEffectUIHost != nullptr)
126 {
127 mpProject = project; // May reassign as null to skip autosave in OnClose
128 // EffectUIHost calls Destroy in OnClose handler
129 mEffectUIHost->Close();
130 mEffectUIHost = {};
131 }
132}
133
135{
136 if(IsShown())
137 Hide(&project);
138 else
139 Show(project);
140}
141
142void RealtimeEffectStateUI::SetTargetName(const wxString& targetName)
143{
144 mTargetName = targetName;
145 UpdateTitle();
146}
147
149{
151}
152
155{
156 return Get(const_cast<RealtimeEffectState&>(state));
157}
158
160{
161 if (mEffectUIHost == nullptr)
162 return;
163
164 if (mEffectName.empty())
165 {
166 const auto ID = mRealtimeEffectState.GetID();
167 const auto effectPlugin = EffectManager::Get().GetEffect(ID);
168
169 if (effectPlugin != nullptr)
170 mEffectName = effectPlugin->GetDefinition().GetName();
171 }
172
173 const auto title =
174 mTargetName.empty() ?
176 /* i18n-hint: First %s is an effect name, second is a track name */
177 XO("%s - %s").Format(mEffectName, mTargetName);
178
179 mEffectUIHost->SetTitle(title);
180 mEffectUIHost->SetName(title);
181}
182
184{
186}
187
188void RealtimeEffectStateUI::OnClose(wxCloseEvent & evt)
189{
190 auto next = GetNextHandler();
191 mEffectUIHost->RemoveEventHandler(this);
192 auto pProject = mpProject;
193 mpProject = nullptr;
194 if (pProject)
195 AutoSave(*pProject);
196
197 // Pass the event through to the dialog
198 if (next)
199 next->ProcessEvent(evt);
200}
END_EVENT_TABLE()
XO("Cut/Copy/Paste")
#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
const auto project
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
Definition: ClientData.h:318
Base class for many of the effects in Audacity.
Definition: EffectBase.h:33
EffectPlugin * GetEffect(const PluginID &ID)
static EffectManager & Get()
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
static ProjectWindow & Get(AudacityProject &project)
std::shared_ptr< EffectSettingsAccess > GetAccess()
const PluginID & GetID() const noexcept
UI state for realtime effect.
Observer::Subscription mParameterChangedSubscription
TranslatableString mEffectName
bool IsShown() const noexcept
Observer::Subscription mProjectWindowDestroyedSubscription
void OnClose(wxCloseEvent &evt)
RealtimeEffectState & mRealtimeEffectState
void SetTargetName(const wxString &name)
void Show(AudacityProject &project)
void Toggle(AudacityProject &project)
wxWeakRef< EffectUIHost > mEffectUIHost
AudacityProject * mpProject
static RealtimeEffectStateUI & Get(RealtimeEffectState &state)
void Hide(AudacityProject *project=nullptr)
void AutoSave(AudacityProject &project)
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:71
void MarkUnsaved()
const RealtimeEffectState::RegisteredFactory realtimeEffectStateUIFactory
Message sent when the project window is closed.
Definition: ProjectWindow.h:29