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 "EffectManager.h"
21#include "UndoManager.h"
22#include "ProjectHistory.h"
23#include "ProjectWindow.h"
24#include "Track.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 = EffectManager::Get().GetEffect(ID);
64
65 if (effectPlugin == nullptr)
66 return;
67
68 const auto client = dynamic_cast<EffectUIServices *>(effectPlugin);
69
70 // Effect has no client interface
71 if (client == nullptr)
72 return;
73
74 auto& projectWindow = ProjectWindow::Get(project);
75
76 std::shared_ptr<EffectInstance> pInstance;
77
78 auto access = mRealtimeEffectState.GetAccess();
79
80 // EffectUIHost invokes shared_from_this on access
82 &projectWindow, project, *effectPlugin, *client, pInstance, *access,
83 mRealtimeEffectState.shared_from_this()));
84
85 if (!dlg->Initialize())
86 return;
87
88 // Dialog is owned by its parent now!
89 mEffectUIHost = dlg.release();
90
92
93 client->ShowClientInterface(*effectPlugin,
94 projectWindow, *mEffectUIHost, mEffectUIHost->GetEditor(), false);
95
96 // The dialog was modal? That shouldn't have happened
97 if (mEffectUIHost == nullptr || !mEffectUIHost->IsShown())
98 {
99 assert(false);
100 mEffectUIHost = {};
101 }
102
103 if (mEffectUIHost) {
104 mEffectUIHost->PushEventHandler(this);
105 mpProject = &project;
106 }
107
108 mProjectWindowDestroyedSubscription = projectWindow.Subscribe(
109 [this, &project](ProjectWindowDestroyedMessage) {
110 // This achieves autosave on close of project before other important
111 // project state is destroyed
112 Hide(&project);
113 });
114
115 mParameterChangedSubscription = mEffectUIHost->GetEditor()->Subscribe(
116 [this](auto) { UndoManager::Get(*mpProject).MarkUnsaved(); });
117}
118
120{
121 if (mEffectUIHost != nullptr)
122 {
123 mpProject = project; // May reassign as null to skip autosave in OnClose
124 // EffectUIHost calls Destroy in OnClose handler
125 mEffectUIHost->Close();
126 mEffectUIHost = {};
127 }
128}
129
131{
132 if(IsShown())
133 Hide(&project);
134 else
135 Show(project);
136}
137
139{
140 mTrackName = track.GetName();
141
142 UpdateTitle();
143}
144
146{
148}
149
152{
153 return Get(const_cast<RealtimeEffectState&>(state));
154}
155
157{
158 if (mEffectUIHost == nullptr)
159 return;
160
161 if (mEffectName.empty())
162 {
163 const auto ID = mRealtimeEffectState.GetID();
164 const auto effectPlugin = EffectManager::Get().GetEffect(ID);
165
166 if (effectPlugin != nullptr)
167 mEffectName = effectPlugin->GetDefinition().GetName();
168 }
169
170 const auto title =
171 mTrackName.empty() ?
173 /* i18n-hint: First %s is an effect name, second is a track name */
174 XO("%s - %s").Format(mEffectName, mTrackName);
175
176 mEffectUIHost->SetTitle(title);
177 mEffectUIHost->SetName(title);
178}
179
181{
183}
184
185void RealtimeEffectStateUI::OnClose(wxCloseEvent & evt)
186{
187 auto next = GetNextHandler();
188 mEffectUIHost->RemoveEventHandler(this);
189 auto pProject = mpProject;
190 mpProject = nullptr;
191 if (pProject)
192 AutoSave(*pProject);
193
194 // Pass the event through to the dialog
195 if (next)
196 next->ProcessEvent(evt);
197}
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:162
static const auto title
declares abstract base class Track, TrackList, and iterators over TrackList
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:309
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 Show(AudacityProject &project)
void Toggle(AudacityProject &project)
wxWeakRef< EffectUIHost > mEffectUIHost
AudacityProject * mpProject
static RealtimeEffectStateUI & Get(RealtimeEffectState &state)
void UpdateTrackData(const Track &track)
void Hide(AudacityProject *project=nullptr)
void AutoSave(AudacityProject &project)
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:226
wxString GetName() const
Definition: Track.h:467
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:33