Audacity 3.2.0
SyncLock.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5@file SyncLock.cpp
6@brief implements sync-lock logic
7
8Paul Licameli split from Track.cpp
9
10**********************************************************************/
11
12#include "SyncLock.h"
13
14#include "Prefs.h"
15#include "Project.h"
16#include "Track.h"
17
21 auto result = std::make_shared< SyncLockState >( project );
22 return result;
23 }
24};
25
27{
28 return project.AttachedObjects::Get< SyncLockState >(
30}
31
33{
34 return Get( const_cast< AudacityProject & >( project ) );
35}
36
38 : mProject{project}
39 , mIsSyncLocked(SyncLockTracks.Read())
40{
41}
42
44{
45 return mIsSyncLocked;
46}
47
49{
50 if (flag != mIsSyncLocked) {
52 Publish({ flag });
53 }
54}
55
56namespace {
57inline bool IsSyncLockableNonSeparatorTrack(const Track *pTrack)
58{
59 return pTrack && GetSyncLockPolicy::Call(*pTrack) == SyncLockPolicy::Grouped;
60}
61
62inline bool IsSeparatorTrack( const Track *pTrack )
63{
64 return pTrack &&
66}
67
68bool IsGoodNextSyncLockTrack(const Track *t, bool inSeparatorSection)
69{
70 if (!t)
71 return false;
72 const bool isSeparator = IsSeparatorTrack(t);
73 if (inSeparatorSection)
74 return isSeparator;
75 else if (isSeparator)
76 return true;
77 else
79}
80}
81
83{
84 if (!pTrack)
85 return false;
86 auto pList = pTrack->GetOwner();
87 if (!pList)
88 return false;
89
90 auto p = pList->GetOwner();
91 if (!p || !SyncLockState::Get( *p ).IsSyncLocked())
92 return false;
93
94 auto shTrack = pTrack->SubstituteOriginalTrack();
95 if (!shTrack)
96 return false;
97
98 const auto pOrigTrack = shTrack.get();
99 auto trackRange = Group( pOrigTrack );
100
101 if (trackRange.size() <= 1) {
102 // Not in a sync-locked group.
103 // Return true iff selected and of a sync-lockable type.
104 return (IsSyncLockableNonSeparatorTrack( pOrigTrack ) ||
105 IsSeparatorTrack( pOrigTrack )) && pTrack->GetSelected();
106 }
107
108 // Return true iff any track in the group is selected.
109 return *(trackRange + &Track::IsSelected).begin();
110}
111
113{
114 return pTrack && (pTrack->IsSelected() || IsSyncLockSelected(pTrack));
115}
116
117namespace {
118std::pair<Track *, Track *> FindSyncLockGroup(Track *pMember)
119{
120 if (!pMember)
121 return { nullptr, nullptr };
122
123 // A non-trivial sync-locked group is a maximal sub-sequence of the tracks
124 // consisting of any positive number of audio tracks followed by zero or
125 // more label tracks.
126
127 // Step back through any label tracks.
128 auto pList = pMember->GetOwner();
129 auto member = pList->Find(pMember);
130 while (*member && IsSeparatorTrack(*member))
131 --member;
132
133 // Step back through the wave and note tracks before the label tracks.
134 Track *first = nullptr;
135 while (*member && IsSyncLockableNonSeparatorTrack(*member)) {
136 first = *member;
137 --member;
138 }
139
140 if (!first)
141 // Can't meet the criteria described above. In that case,
142 // consider the track to be the sole member of a group.
143 return { pMember, pMember };
144
145 auto last = pList->Find(first);
146 auto next = last;
147 bool inLabels = false;
148
149 while (*++next) {
150 if (!IsGoodNextSyncLockTrack(*next, inLabels))
151 break;
152 last = next;
153 inLabels = IsSeparatorTrack(*last);
154 }
155
156 return { first, *last };
157}
158
159}
160
162{
163 auto pList = pTrack->GetOwner();
164 auto tracks = FindSyncLockGroup(const_cast<Track*>( pTrack ) );
165 return pList->Any()
166 .StartingWith(tracks.first).EndingAfter(tracks.second);
167}
168
170 return [](auto&){ return SyncLockPolicy::Isolated; };
171}
172
173BoolSetting SyncLockTracks{ "/GUI/SyncLockTracks", false };
DEFINE_ATTACHED_VIRTUAL(GetSyncLockPolicy)
Definition: SyncLock.cpp:169
BoolSetting SyncLockTracks
Definition: SyncLock.cpp:173
static const AudacityProject::AttachedObjects::RegisteredFactory sSyncLockStateKey
Definition: SyncLock.cpp:19
@ EndSeparator
Delimits the end of a group (of which it is a part)
@ Grouped
Can be part of a group.
@ Isolated
Never part of a group.
const auto tracks
const auto project
declares abstract base class Track, TrackList, and iterators over TrackList
static std::once_flag flag
Class template generates single-dispatch, open method registry tables.
static Return Call(This &obj, Arguments ...arguments)
Invoke the method – but only after static initialization time.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:344
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:274
Subclass * Find(const RegisteredFactory &key)
Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand...
Definition: ClientData.h:341
CallbackReturn Publish(const SyncLockChangeMessage &message)
Send a message to connected callbacks.
Definition: Observer.h:207
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:112
static bool IsSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:82
static TrackIterRange< Track > Group(Track *pTrack)
Definition: SyncLock.cpp:161
bool IsSyncLocked() const
Definition: SyncLock.cpp:43
void SetSyncLock(bool flag)
Definition: SyncLock.cpp:48
static SyncLockState & Get(AudacityProject &project)
Definition: SyncLock.cpp:26
bool mIsSyncLocked
Definition: SyncLock.h:38
SyncLockState(AudacityProject &project)
Definition: SyncLock.cpp:37
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:122
bool GetSelected() const
Selectedness is always the same for all channels of a group.
Definition: Track.cpp:70
bool IsSelected() const
Definition: Track.cpp:288
std::shared_ptr< const Track > SubstituteOriginalTrack() const
Definition: Track.cpp:1185
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:254
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
bool IsSeparatorTrack(const Track *pTrack)
Definition: SyncLock.cpp:62
bool IsSyncLockableNonSeparatorTrack(const Track *pTrack)
Definition: SyncLock.cpp:57
std::pair< Track *, Track * > FindSyncLockGroup(Track *pMember)
Definition: SyncLock.cpp:118
bool IsGoodNextSyncLockTrack(const Track *t, bool inSeparatorSection)
Definition: SyncLock.cpp:68
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
Definition: Track.h:807