Audacity 3.2.0
RealtimeEffectList.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 RealtimeEffectList.cpp
6
7 *********************************************************************/
8
10#include "RealtimeEffectState.h"
11
12#include "Project.h"
13#include "Track.h"
14
16{
17}
18
20{
21}
22
23// Deep copy of states
24std::unique_ptr<ClientData::Cloneable<>> RealtimeEffectList::Clone() const
25{
26 auto result = std::make_unique<RealtimeEffectList>();
27 for (auto &pState : mStates)
28 result->mStates.push_back(RealtimeEffectState::make_shared(*pState));
29 result->SetActive(this->IsActive());
30 return result;
31}
32
33// Access for per-project effect list
35{
36 [](AudacityProject &project)
37 {
38 return std::make_shared<RealtimeEffectList>();
39 }
40};
41
43{
44 return project.AttachedObjects::Get<RealtimeEffectList>(masterEffects);
45}
46
48 AudacityProject &project, const std::shared_ptr<RealtimeEffectList> &list)
49{
50 auto &result = *list;
51 project.AttachedObjects::Assign(masterEffects, list);
52 return result;
53}
54
56{
57 return Get(const_cast<AudacityProject &>(project));
58}
59
61{
63 {
64 return std::make_unique<RealtimeEffectList>();
65 }
66};
67
68// Access for per-track effect list
70{
71 return track.GetGroupData()
72 .Track::ChannelGroupAttachments::Get<RealtimeEffectList>(trackEffects);
73}
74
76{
77 return Get(const_cast<Track &>(track));
78}
79
80bool
81RealtimeEffectList::AddState(std::shared_ptr<RealtimeEffectState> pState)
82{
83 const auto &id = pState->GetID();
84 if (pState->GetEffect() != nullptr) {
85 auto shallowCopy = mStates;
86 shallowCopy.emplace_back(move(pState));
87 // Lock for only a short time
88 (LockGuard{ mLock }, swap(shallowCopy, mStates));
89
92 mStates.size() - 1,
93 { }
94 });
95
96 return true;
97 }
98 else
99 // Effect initialization failed for the id
100 return false;
101}
102
103bool
105 std::shared_ptr<RealtimeEffectState> pState)
106{
107 if (index >= mStates.size())
108 return false;
109 const auto &id = pState->GetID();
110 if (pState->GetEffect() != nullptr) {
111 auto shallowCopy = mStates;
112 swap(pState, shallowCopy[index]);
113 // Lock for only a short time
114 (LockGuard{ mLock }, swap(shallowCopy, mStates));
115
118 index,
119 { }
120 });
121
122 return true;
123 }
124 else
125 // Effect initialization failed for the id
126 return false;
127}
128
130 const std::shared_ptr<RealtimeEffectState> pState)
131{
132 auto shallowCopy = mStates;
133 auto end = shallowCopy.end(),
134 found = std::find(shallowCopy.begin(), end, pState);
135 if (found != end)
136 {
137 const auto index = std::distance(shallowCopy.begin(), found);
138 shallowCopy.erase(found);
139
140 // Lock for only a short time
141 (LockGuard{ mLock }, swap(shallowCopy, mStates));
142
145 static_cast<size_t>(index),
146 { }
147 });
148 }
149}
150
152{
153 decltype(mStates) temp;
154
155 // Swap an empty list in as a whole, not removing one at a time
156 // Lock for only a short time
157 (LockGuard{ mLock }, swap(temp, mStates));
158
159 for (auto index = temp.size(); index--;)
162}
163
164std::optional<size_t> RealtimeEffectList::FindState(
165 const std::shared_ptr<RealtimeEffectState> &pState) const
166{
167 const auto begin = mStates.begin()
168 , end = mStates.end()
169 , iter = std::find(begin, end, pState);
170 if (iter == end)
171 return {};
172 return std::distance(begin, iter);
173}
174
176{
177 return mStates.size();
178}
179
180std::shared_ptr<RealtimeEffectState>
181RealtimeEffectList::GetStateAt(size_t index) noexcept
182{
183 if (index < mStates.size())
184 return mStates[index];
185 return nullptr;
186}
187
188std::shared_ptr<const RealtimeEffectState>
189RealtimeEffectList::GetStateAt(size_t index) const noexcept
190{
191 return const_cast<RealtimeEffectList*>(this)->GetStateAt(index);
192}
193
194void RealtimeEffectList::MoveEffect(size_t fromIndex, size_t toIndex)
195{
196 assert(fromIndex < mStates.size());
197 assert(toIndex < mStates.size());
198
199 auto shallowCopy = mStates;
200 if(fromIndex == toIndex)
201 return;
202 if(fromIndex < toIndex)
203 {
204 const auto first = shallowCopy.begin() + fromIndex;
205 const auto last = shallowCopy.begin() + toIndex + 1;
206 std::rotate(first, first + 1, last);
207 }
208 else
209 {
210 const auto first = shallowCopy.rbegin() + (shallowCopy.size() - (fromIndex + 1));
211 const auto last = shallowCopy.rbegin() + (shallowCopy.size() - toIndex);
212 std::rotate(first, first + 1, last);
213 }
214 // Lock for only a short time
215 (LockGuard{ mLock }, swap(shallowCopy, mStates));
216
219 fromIndex,
220 toIndex
221 });
222}
223
224const std::string &RealtimeEffectList::XMLTag()
225{
226 static const std::string result{"effects"};
227 return result;
228}
229
230static constexpr auto activeAttribute = "active";
231
233 const std::string_view &tag, const AttributesList &attrs)
234{
235 if (tag == XMLTag()) {
236 for (auto &[attr, value] : attrs) {
237 if (attr == activeAttribute)
238 SetActive(value.Get<bool>());
239 }
240 return true;
241 }
242 return false;
243}
244
246{
247 if (tag == RealtimeEffectState::XMLTag()) {
249 return mStates.back().get();
250 }
251 return nullptr;
252}
253
255{
256 xmlFile.StartTag(XMLTag());
258 for (const auto & state : mStates)
259 state->WriteXML(xmlFile);
260 xmlFile.EndTag(XMLTag());
261}
262
264{
265 // Restore per-project states
266 Set(project, shared_from_this());
267}
268
270{
271 return mActive.load(std::memory_order_relaxed);
272}
273
275{
276 (LockGuard{ mLock }, mActive.store(value, std::memory_order_relaxed));
277}
278
280 [](AudacityProject &project) -> std::shared_ptr<UndoStateExtension> {
281 return RealtimeEffectList::Get(project).shared_from_this();
282 }
283};
wxString PluginID
Definition: EffectManager.h:30
static const Track::ChannelGroupAttachments::RegisteredFactory trackEffects
static UndoRedoExtensionRegistry::Entry sEntry
static constexpr auto activeAttribute
static const AttachedProjectObjects::RegisteredFactory masterEffects
declares abstract base class Track, TrackList, and iterators over TrackList
std::vector< Attribute > AttributesList
Definition: XMLTagHandler.h:40
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:266
CallbackReturn Publish(const RealtimeEffectListMessage &message)
Send a message to connected callbacks.
Definition: Observer.h:207
static RealtimeEffectList & Get(AudacityProject &project)
std::optional< size_t > FindState(const std::shared_ptr< RealtimeEffectState > &pState) const
Report the position of a state in the list.
std::lock_guard< Lock > LockGuard
bool AddState(std::shared_ptr< RealtimeEffectState > pState)
void RestoreUndoRedoState(AudacityProject &project) noexcept override
Modify the project when undoing or redoing to some state in history.
std::unique_ptr< ClientData::Cloneable<> > Clone() const override
size_t GetStatesCount() const noexcept
bool IsActive() const
Non-blocking atomic boolean load.
void RemoveState(std::shared_ptr< RealtimeEffectState > pState)
void Clear()
Use only in the main thread. Sends Remove messages.
std::atomic< bool > mActive
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
void SetActive(bool value)
Done by main thread only, under a lock guard.
static RealtimeEffectList & Set(AudacityProject &project, const std::shared_ptr< RealtimeEffectList > &list)
static const std::string & XMLTag()
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
Use only in the main thread. May add a state while deserializing.
void WriteXML(XMLWriter &xmlFile) const
Use only in the main thread, to avoid races.
void MoveEffect(size_t fromIndex, size_t toIndex)
Use only in the main thread. Changes effect order in the stack. Does nothing if fromIndex equals toIn...
bool ReplaceState(size_t index, std::shared_ptr< RealtimeEffectState > pState)
std::shared_ptr< RealtimeEffectState > GetStateAt(size_t index) noexcept
static const std::string & XMLTag()
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
ChannelGroupData & GetGroupData()
Definition: Track.cpp:179
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:42
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:26
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:80
void WriteAttr(const wxString &name, const Identifier &value)
Definition: XMLWriter.h:37
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:103
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:753
@ Replace
Effect item was replaced with a new item at srcIndex position.
@ Remove
Effect item was removed from the list at srcIndex position.
@ Move
Item position has changed, from srcIndex to dstIndex.
@ Insert
New effect item was added to the list at srcIndex position.
static std::shared_ptr< RealtimeEffectState > make_shared(Args &&...args)
Definition: MemoryX.h:497
Typically statically constructed.
Definition: UndoManager.h:107