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 "PendingTracks.h"
15#include "Prefs.h"
16#include "Project.h"
17#include "Track.h"
18
22 auto result = std::make_shared< SyncLockState >( project );
23 return result;
24 }
25};
26
28{
29 return project.AttachedObjects::Get< SyncLockState >(
31}
32
34{
35 return Get( const_cast< AudacityProject & >( project ) );
36}
37
39 : mProject{project}
40 , mIsSyncLocked(SyncLockTracks.Read())
41{
42}
43
45{
46 return mIsSyncLocked;
47}
48
50{
51 if (flag != mIsSyncLocked) {
53 Publish({ flag });
54 }
55}
56
57namespace {
58inline bool IsSyncLockableNonSeparatorTrack(const Track &track)
59{
61}
62
63inline bool IsSeparatorTrack(const Track &track)
64{
66}
67
68bool IsGoodNextSyncLockTrack(const Track &t, bool inSeparatorSection)
69{
70 const bool isSeparator = IsSeparatorTrack(t);
71 if (inSeparatorSection)
72 return isSeparator;
73 else if (isSeparator)
74 return true;
75 else
77}
78}
79
81{
82 auto pList = track.GetOwner();
83 if (!pList)
84 return false;
85
86 auto p = pList->GetOwner();
87 if (!p || !SyncLockState::Get( *p ).IsSyncLocked())
88 return false;
89
90 auto &orig = PendingTracks::Get(*p).SubstituteOriginalTrack(track);
91 auto trackRange = Group(orig);
92
93 if (trackRange.size() <= 1) {
94 // Not in a sync-locked group.
95 // Return true iff selected and of a sync-lockable type.
96 return (IsSyncLockableNonSeparatorTrack(orig) ||
97 IsSeparatorTrack(orig)) && track.GetSelected();
98 }
99
100 // Return true iff any track in the group is selected.
101 return *(trackRange + &Track::IsSelected).begin();
102}
103
105{
106 return track.IsSelected() || IsSyncLockSelected(track);
107}
108
109namespace {
110std::pair<Track *, Track *> FindSyncLockGroup(Track &member)
111{
112 // A non-trivial sync-locked group is a maximal sub-sequence of the tracks
113 // consisting of any positive number of audio tracks followed by zero or
114 // more label tracks.
115
116 // Step back through any label tracks.
117 auto pList = member.GetOwner();
118 auto ppMember = pList->Find(&member);
119 while (*ppMember && IsSeparatorTrack(**ppMember))
120 --ppMember;
121
122 // Step back through the wave and note tracks before the label tracks.
123 Track *first = nullptr;
124 while (*ppMember && IsSyncLockableNonSeparatorTrack(**ppMember)) {
125 first = *ppMember;
126 --ppMember;
127 }
128
129 if (!first)
130 // Can't meet the criteria described above. In that case,
131 // consider the track to be the sole member of a group.
132 return { &member, &member };
133
134 auto last = pList->Find(first);
135 auto next = last;
136 bool inLabels = false;
137
138 while (*++next) {
139 if (!IsGoodNextSyncLockTrack(**next, inLabels))
140 break;
141 last = next;
142 inLabels = IsSeparatorTrack(**last);
143 }
144
145 return { first, *last };
146}
147
148}
149
151{
152 auto pList = track.GetOwner();
153 assert(pList); // precondition
154 auto tracks = FindSyncLockGroup(const_cast<Track&>(track));
155 return pList->Any()
156 .StartingWith(tracks.first).EndingAfter(tracks.second);
157}
158
160 return [](auto&){ return SyncLockPolicy::Isolated; };
161}
162
163BoolSetting SyncLockTracks{ "/GUI/SyncLockTracks", false };
DEFINE_ATTACHED_VIRTUAL(GetSyncLockPolicy)
Definition: SyncLock.cpp:159
BoolSetting SyncLockTracks
Definition: SyncLock.cpp:163
static const AudacityProject::AttachedObjects::RegisteredFactory sSyncLockStateKey
Definition: SyncLock.cpp:20
@ 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:346
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:275
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:342
CallbackReturn Publish(const SyncLockChangeMessage &message)
Send a message to connected callbacks.
Definition: Observer.h:207
const Track & SubstituteOriginalTrack(const Track &track) const
static PendingTracks & Get(AudacityProject &project)
static TrackIterRange< Track > Group(Track &track)
Definition: SyncLock.cpp:150
static bool IsSelectedOrSyncLockSelected(const Track &track)
Definition: SyncLock.cpp:104
static bool IsSyncLockSelected(const Track &track)
Definition: SyncLock.cpp:80
bool IsSyncLocked() const
Definition: SyncLock.cpp:44
void SetSyncLock(bool flag)
Definition: SyncLock.cpp:49
static SyncLockState & Get(AudacityProject &project)
Definition: SyncLock.cpp:27
bool mIsSyncLocked
Definition: SyncLock.h:38
SyncLockState(AudacityProject &project)
Definition: SyncLock.cpp:38
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
bool GetSelected() const
Selectedness is always the same for all channels of a group.
Definition: Track.cpp:78
bool IsSelected() const
Definition: Track.cpp:258
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:230
bool IsSyncLockableNonSeparatorTrack(const Track &track)
Definition: SyncLock.cpp:58
bool IsSeparatorTrack(const Track &track)
Definition: SyncLock.cpp:63
std::pair< Track *, Track * > FindSyncLockGroup(Track &member)
Definition: SyncLock.cpp:110
bool IsGoodNextSyncLockTrack(const Track &t, bool inSeparatorSection)
Definition: SyncLock.cpp:68
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
Definition: Track.h:682