Audacity  3.2.0
SyncLock.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 @file SyncLock.cpp
6 @brief implements sync-lock logic
7 
8 Paul Licameli split from Track.cpp
9 
10 **********************************************************************/
11 
12 #include "SyncLock.h"
13 
14 #include "ProjectSettings.h"
15 #include "Track.h"
16 
17 namespace {
18 inline bool IsSyncLockableNonSeparatorTrack( const Track *pTrack )
19 {
20  return pTrack && GetSyncLockPolicy::Call(*pTrack) == SyncLockPolicy::Grouped;
21 }
22 
23 inline bool IsSeparatorTrack( const Track *pTrack )
24 {
25  return pTrack &&
27 }
28 
29 bool IsGoodNextSyncLockTrack(const Track *t, bool inSeparatorSection)
30 {
31  if (!t)
32  return false;
33  const bool isSeparator = IsSeparatorTrack(t);
34  if (inSeparatorSection)
35  return isSeparator;
36  else if (isSeparator)
37  return true;
38  else
40 }
41 }
42 
43 bool SyncLock::IsSyncLockSelected( const Track *pTrack )
44 {
45  if (!pTrack)
46  return false;
47  auto pList = pTrack->GetOwner();
48  if (!pList)
49  return false;
50 
51  auto p = pList->GetOwner();
52  if (!p || !ProjectSettings::Get( *p ).IsSyncLocked())
53  return false;
54 
55  auto shTrack = pTrack->SubstituteOriginalTrack();
56  if (!shTrack)
57  return false;
58 
59  const auto pOrigTrack = shTrack.get();
60  auto trackRange = Group( pOrigTrack );
61 
62  if (trackRange.size() <= 1) {
63  // Not in a sync-locked group.
64  // Return true iff selected and of a sync-lockable type.
65  return (IsSyncLockableNonSeparatorTrack( pOrigTrack ) ||
66  IsSeparatorTrack( pOrigTrack )) && pTrack->GetSelected();
67  }
68 
69  // Return true iff any track in the group is selected.
70  return *(trackRange + &Track::IsSelected).begin();
71 }
72 
74 {
75  return pTrack && (pTrack->IsSelected() || IsSyncLockSelected(pTrack));
76 }
77 
78 namespace {
79 std::pair<Track *, Track *> FindSyncLockGroup( Track *pMember)
80 {
81  if (!pMember)
82  return { nullptr, nullptr };
83 
84  // A non-trivial sync-locked group is a maximal sub-sequence of the tracks
85  // consisting of any positive number of audio tracks followed by zero or
86  // more label tracks.
87 
88  // Step back through any label tracks.
89  auto pList = pMember->GetOwner();
90  auto member = pList->Find(pMember);
91  while (*member && IsSeparatorTrack(*member) )
92  --member;
93 
94  // Step back through the wave and note tracks before the label tracks.
95  Track *first = nullptr;
96  while (*member && IsSyncLockableNonSeparatorTrack(*member)) {
97  first = *member;
98  --member;
99  }
100 
101  if (!first)
102  // Can't meet the criteria described above. In that case,
103  // consider the track to be the sole member of a group.
104  return { pMember, pMember };
105 
106  auto last = pList->Find(first);
107  auto next = last;
108  bool inLabels = false;
109 
110  while (*++next) {
111  if ( ! IsGoodNextSyncLockTrack(*next, inLabels) )
112  break;
113  last = next;
114  inLabels = IsSeparatorTrack(*last);
115  }
116 
117  return { first, *last };
118 }
119 
120 }
121 
123 {
124  auto pList = pTrack->GetOwner();
125  auto tracks = FindSyncLockGroup(const_cast<Track*>( pTrack ) );
126  return pList->Any().StartingWith(tracks.first).EndingAfter(tracks.second);
127 }
128 
130  return [](auto&){ return SyncLockPolicy::Isolated; };
131 }
DEFINE_ATTACHED_VIRTUAL
DEFINE_ATTACHED_VIRTUAL(GetSyncLockPolicy)
Definition: SyncLock.cpp:129
Track::SubstituteOriginalTrack
std::shared_ptr< const Track > SubstituteOriginalTrack() const
Definition: Track.cpp:1076
AttachedVirtualFunction::Call
static Return Call(This &obj, Arguments &&...arguments)
Invoke the method – but only after static initialization time.
Definition: AttachedVirtualFunction.h:223
ClientData::Site::Find
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:333
AttachedVirtualFunction
Class template generates single-dispatch, open method registry tables.
Definition: AttachedVirtualFunction.h:159
SyncLockPolicy::Isolated
@ Isolated
Never part of a group.
anonymous_namespace{SyncLock.cpp}::FindSyncLockGroup
std::pair< Track *, Track * > FindSyncLockGroup(Track *pMember)
Definition: SyncLock.cpp:79
Track::GetOwner
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:378
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:45
ProjectSettings.h
ProjectSettings::IsSyncLocked
bool IsSyncLocked() const
Definition: ProjectSettings.cpp:180
anonymous_namespace{SyncLock.cpp}::IsSyncLockableNonSeparatorTrack
bool IsSyncLockableNonSeparatorTrack(const Track *pTrack)
Definition: SyncLock.cpp:18
SyncLock::IsSyncLockSelected
static bool IsSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:43
SyncLockPolicy::EndSeparator
@ EndSeparator
Delimits the end of a group (of which it is a part)
Track::IsSelected
bool IsSelected() const
Definition: Track.cpp:295
SyncLock::IsSelectedOrSyncLockSelected
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:73
anonymous_namespace{SyncLock.cpp}::IsGoodNextSyncLockTrack
bool IsGoodNextSyncLockTrack(const Track *t, bool inSeparatorSection)
Definition: SyncLock.cpp:29
TrackIterRange
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
Definition: Track.h:1119
Track::GetSelected
bool GetSelected() const
Definition: Track.h:428
SyncLock.h
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:224
SyncLockPolicy::Grouped
@ Grouped
Can be part of a group.
SyncLock::Group
static TrackIterRange< Track > Group(Track *pTrack)
Definition: SyncLock.cpp:122
Track.h
declares abstract base class Track, TrackList, and iterators over TrackList
anonymous_namespace{SyncLock.cpp}::IsSeparatorTrack
bool IsSeparatorTrack(const Track *pTrack)
Definition: SyncLock.cpp:23