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 "Channel.h"
14
16{
17}
18
20{
21}
22
23// Deep copy of states
25{
26 auto result = std::make_unique<RealtimeEffectList>();
27 for (auto &pState : mStates)
28 result->mStates.push_back(pState);
29 result->SetActive(this->IsActive());
30 return result;
31}
32
33// Access for per-project effect list
35{
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
57{
58 return Get(const_cast<AudacityProject &>(project));
59}
60
63{
64 [](auto&)
65 {
66 return std::make_unique<RealtimeEffectList>();
67 }
68};
69
70// Access for per-group effect list
72{
73 return group.Attachments::Get<RealtimeEffectList>(channelGroupEffects);
74}
75
77 const ChannelGroup &group)
78{
79 return Get(const_cast<ChannelGroup &>(group));
80}
81
82bool
83RealtimeEffectList::AddState(std::shared_ptr<RealtimeEffectState> pState)
84{
85 const auto &id = pState->GetID();
86 if (pState->GetEffect() != nullptr) {
87 auto shallowCopy = mStates;
88 shallowCopy.emplace_back(pState);
89 // Lock for only a short time
90 (LockGuard{ mLock }, swap(shallowCopy, mStates));
91
94 mStates.size() - 1,
95 { },
96 pState
97 });
98
99 return true;
100 }
101 else
102 // Effect initialization failed for the id
103 return false;
104}
105
106bool
108 std::shared_ptr<RealtimeEffectState> pState)
109{
110 if (index >= mStates.size())
111 return false;
112 const auto &id = pState->GetID();
113 if (pState->GetEffect() != nullptr) {
114 auto shallowCopy = mStates;
115
118 index,
119 { },
120 shallowCopy[index]
121 });
122
123 swap(pState, shallowCopy[index]);
124 // Lock for only a short time
125 (LockGuard{ mLock }, swap(shallowCopy, mStates));
126
129 index,
130 { },
131 pState
132 });
133
134 return true;
135 }
136 else
137 // Effect initialization failed for the id
138 return false;
139}
140
142 const std::shared_ptr<RealtimeEffectState> pState)
143{
144 auto shallowCopy = mStates;
145 auto end = shallowCopy.end(),
146 found = std::find(shallowCopy.begin(), end, pState);
147 if (found != end)
148 {
149 const auto index = std::distance(shallowCopy.begin(), found);
150 shallowCopy.erase(found);
151
152 // Lock for only a short time
153 (LockGuard{ mLock }, swap(shallowCopy, mStates));
154
157 static_cast<size_t>(index),
158 { },
159 pState
160 });
161 }
162}
163
165{
166 decltype(mStates) temp;
167
168 // Swap an empty list in as a whole, not removing one at a time
169 // Lock for only a short time
170 (LockGuard{ mLock }, swap(temp, mStates));
171
172 for (auto index = temp.size(); index--;)
174 { RealtimeEffectListMessage::Type::Remove, index, {}, temp[index] });
175}
176
177std::optional<size_t> RealtimeEffectList::FindState(
178 const std::shared_ptr<RealtimeEffectState> &pState) const
179{
180 const auto begin = mStates.begin()
181 , end = mStates.end()
182 , iter = std::find(begin, end, pState);
183 if (iter == end)
184 return {};
185 return std::distance(begin, iter);
186}
187
189{
190 return mStates.size();
191}
192
193std::shared_ptr<RealtimeEffectState>
194RealtimeEffectList::GetStateAt(size_t index) noexcept
195{
196 if (index < mStates.size())
197 return mStates[index];
198 return nullptr;
199}
200
201std::shared_ptr<const RealtimeEffectState>
202RealtimeEffectList::GetStateAt(size_t index) const noexcept
203{
204 return const_cast<RealtimeEffectList*>(this)->GetStateAt(index);
205}
206
207void RealtimeEffectList::MoveEffect(size_t fromIndex, size_t toIndex)
208{
209 assert(fromIndex < mStates.size());
210 assert(toIndex < mStates.size());
211
212 auto shallowCopy = mStates;
213 if(fromIndex == toIndex)
214 return;
215 if(fromIndex < toIndex)
216 {
217 const auto first = shallowCopy.begin() + fromIndex;
218 const auto last = shallowCopy.begin() + toIndex + 1;
219 std::rotate(first, first + 1, last);
220 }
221 else
222 {
223 const auto first =
224 shallowCopy.rbegin() + (shallowCopy.size() - (fromIndex + 1));
225 const auto last = shallowCopy.rbegin() + (shallowCopy.size() - toIndex);
226 std::rotate(first, first + 1, last);
227 }
228 // Lock for only a short time
229 (LockGuard{ mLock }, swap(shallowCopy, mStates));
230
233 fromIndex,
234 toIndex,
235 mStates[toIndex]
236 });
237}
238
239const std::string &RealtimeEffectList::XMLTag()
240{
241 static const std::string result{"effects"};
242 return result;
243}
244
245static constexpr auto activeAttribute = "active";
246
248 const std::string_view &tag, const AttributesList &attrs)
249{
250 if (tag == XMLTag()) {
251 for (auto &[attr, value] : attrs) {
252 if (attr == activeAttribute)
253 SetActive(value.Get<bool>());
254 }
255 return true;
256 }
257 return false;
258}
259
261{
262 if (tag == RealtimeEffectState::XMLTag()) {
264 return mStates.back().get();
265 }
266 return nullptr;
267}
268
270{
271 xmlFile.StartTag(XMLTag());
273 for (const auto & state : mStates)
274 state->WriteXML(xmlFile);
275 xmlFile.EndTag(XMLTag());
276}
277
279{
280 // Restore per-project states
281 Set(project, shared_from_this());
282}
283
285{
286 return mActive.load(std::memory_order_relaxed);
287}
288
290{
291 (LockGuard{ mLock }, mActive.store(value, std::memory_order_relaxed));
292}
293
295 [](AudacityProject &project) -> std::shared_ptr<UndoStateExtension> {
296 return RealtimeEffectList::Get(project).shared_from_this();
297 }
298};
Abstract class ChannelGroup with two discrete iterable dimensions, channels and intervals; subclasses...
wxString PluginID
static const ChannelGroup::Attachments::RegisteredFactory channelGroupEffects
static UndoRedoExtensionRegistry::Entry sEntry
static constexpr auto activeAttribute
static const AttachedProjectObjects::RegisteredFactory masterEffects
const auto project
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:90
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:275
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()
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:25
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:79
void WriteAttr(const wxString &name, const Identifier &value)
Definition: XMLWriter.h:36
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:102
template struct REGISTRIES_API Cloneable<>
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:628
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
void rotate(const float *oldPhase, const float *newPhase, std::complex< float > *dst, int32_t n)
Definition: VectorOps.h:140
@ Remove
Effect item was removed from the list at srcIndex position. affectedState is removed state.
@ DidReplace
Effect item was replaced with a new item at srcIndex position. affectedState is an old state.
@ Move
Item position has changed, from srcIndex to dstIndex. affectedState is the moved state.
@ Insert
New effect item was added to the list at srcIndex position. affectedState is a new state.
@ WillReplace
Effect item will be replaced with a new item at srcIndex position. affectedState is the state to be r...
static std::shared_ptr< RealtimeEffectState > make_shared(Args &&...args)
Definition: MemoryX.h:299
Typically statically constructed.
Definition: UndoManager.h:102