tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_EditInsertPoint.cpp
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11namespace tracktion { inline namespace engine
12{
13
15 : edit (e)
16{
17}
18
20{
21 if (lockInsertPointCount != 0)
22 return false;
23
24 if (time)
26
27 nextInsertPointClipOwner = clipOwner != nullptr ? clipOwner->getClipOwnerID()
28 : EditItemID();
29
30 if (auto cs = dynamic_cast<ClipSlot*> (clipOwner))
31 nextInsertPointTrack = cs->track.itemID;
32 else if (dynamic_cast<Track*> (clipOwner) != nullptr)
33 nextInsertPointTrack = nextInsertPointClipOwner;
34
35 return true;
36}
37
39{
40 if (lockInsertPointCount == 0)
41 {
42 nextInsertPointTime = std::max (0_tp, time);
43 nextInsertIsAfterSelected = false;
44 }
45}
46
48{
49 if (lockInsertPointCount == 0)
50 {
51 setNextInsertPoint (time);
52 nextInsertPointClipOwner = {};
53 nextInsertPointTrack = track != nullptr ? track->itemID : EditItemID();
54 }
55}
56
57void EditInsertPoint::lockInsertPoint (bool lock) noexcept
58{
59 if (lock)
60 ++lockInsertPointCount;
61 else
62 --lockInsertPointCount;
63}
64
66{
67 nextInsertIsAfterSelected = true;
68}
69
71 TimePosition& start, bool pasteAfterSelection, SelectionManager* sm)
72{
73 return chooseInsertPoint (track, start, pasteAfterSelection, sm,
74 [] (auto& t) { return t.isAudioTrack() || t.isFolderTrack(); });
75}
76
77void EditInsertPoint::chooseInsertPoint (Track::Ptr& track, TimePosition& start, bool pasteAfterSelection, SelectionManager* sm,
78 std::function<bool (Track&)> allowedTrackPredicate)
79{
81 jassert (allowedTrackPredicate);
82 track = findTrackForID (edit, nextInsertPointTrack);
83 start = nextInsertPointTime;
84
85 if (nextInsertIsAfterSelected || pasteAfterSelection)
86 {
87 if (sm != nullptr)
88 {
89 if (auto firstSelectedTrack = findAllTracksContainingSelectedItems (sm->getSelectedObjects()).getFirst())
90 track = firstSelectedTrack;
91
92 auto selectedClipTimeRange = getTimeRangeForSelectedItems (sm->getSelectedObjects());
93
94 if (! selectedClipTimeRange.isEmpty())
95 {
96 start = selectedClipTimeRange.getEnd();
97
98 if (edit.getTransport().snapToTimecode)
99 start = edit.getTransport().getSnapType().roundTimeNearest (start, edit.tempoSequence);
100 }
101 }
102 }
103
104 while (track != nullptr && ! allowedTrackPredicate (*track))
105 {
106 if (auto next = track->getSiblingTrack (1, false))
107 track = next;
108 else
109 break;
110 }
111
112 if (track == nullptr)
113 {
114 if (sm != nullptr)
115 track = findFirstClipTrackFromSelection (sm->getSelectedObjects());
116
117 if (track == nullptr)
118 {
120 track = getAudioTracks (edit).getFirst();
121 }
122 }
123
124 jassert (track != nullptr);
125}
126
128 std::function<bool (Track&)> allowedTrackPredicate)
129{
131 jassert (allowedTrackPredicate);
132 auto track = findTrackForID (edit, nextInsertPointTrack);
133 auto clipOwner = nextInsertPointClipOwner.isValid() ? findClipOwnerForID (edit, nextInsertPointClipOwner)
134 : track != nullptr ? dynamic_cast<ClipOwner*> (track)
135 : nullptr;
136 auto time = nextInsertPointTime;
137
138 // Find the next track after the selection if required
139 if (nextInsertIsAfterSelected || pasteAfterSelection)
140 {
141 if (sm != nullptr)
142 {
143 // Get the selected track first
144 if (auto firstSelectedTrack = findAllTracksContainingSelectedItems (sm->getSelectedObjects()).getFirst())
145 track = firstSelectedTrack;
146
147 // Then see if it's actually a Slot that's selected
148 if (auto clipSlot = sm->getFirstItemOfType<ClipSlot>())
149 {
150 clipOwner = clipSlot;
151 track = &clipSlot->track;
152 }
153 else if (auto clip = sm->getFirstItemOfType<Clip>())
154 {
155 // Or a Clip in a ClipSlot
156 if (auto clipClipSlot = clip->getClipSlot())
157 {
158 clipOwner = clipClipSlot;
159 track = &clipClipSlot->track;
160 }
161 }
162
163 if (auto selectedClipTimeRange = getTimeRangeForSelectedItems (sm->getSelectedObjects());
164 ! selectedClipTimeRange.isEmpty())
165 {
166 time = selectedClipTimeRange.getEnd();
167
168 if (edit.getTransport().snapToTimecode)
169 time = edit.getTransport().getSnapType().roundTimeNearest (time, edit.tempoSequence);
170 }
171 }
172 }
173
174 // Check the Track is allowed by the predicate and if not, find the next allowed track
175 while (track != nullptr && ! allowedTrackPredicate (*track))
176 {
177 if (auto next = track->getSiblingTrack (1, false))
178 track = next;
179 else
180 break;
181 }
182
183 // If the Track is still nullptr, find it from the selection, otherwise, create a new one
184 if (track == nullptr)
185 {
186 if (sm != nullptr)
187 track = findFirstClipTrackFromSelection (sm->getSelectedObjects());
188
189 if (track == nullptr)
190 {
192 track = getAudioTracks (edit).getFirst();
193 clipOwner = dynamic_cast<ClipOwner*> (track);
194 }
195 }
196
197 jassert (track != nullptr);
198 return { track, clipOwner, { time } };
199}
200
201}} // namespace tracktion { inline namespace engine
ElementType getFirst() const noexcept
Base class for items that can contain clips.
virtual EditItemID getClipOwnerID()=0
Must return the ID of this ClipOwner.
Represents a slot on a track that a Clip can live in to be played as a launched clip.
A clip in an edit.
bool setNextInsertPoint(ClipOwner *, std::optional< TimePosition >)
Sets the next insertion point to a given ClipOwner and Time (if provided).
EditInsertPoint(Edit &)
Creates an EditInsertPoint for a given Edit.
void lockInsertPoint(bool lock) noexcept
Locks the insert point so calls to setNextInsertPoint won't have any effect.
virtual void chooseInsertPoint(juce::ReferenceCountedObjectPtr< Track > &, TimePosition &start, bool pasteAfterSelection, SelectionManager *)
Returns the track and time position content should be pasted at.
void setNextInsertPointAfterSelected()
Sets a flag to signify chooseInsertPoint should use the selected track as the insertion point.
A struct representing a resolved insertion point.
The Tracktion Edit class!
TransportControl & getTransport() const noexcept
Returns the TransportControl which is used to stop/stop/position playback and recording.
void ensureNumberOfAudioTracks(int minimumNumTracks)
Creates new tracks to ensure the minimum number.
TempoSequence tempoSequence
The global TempoSequence of this Edit.
Manages a list of items that are currently selected.
Base class for tracks which contain clips and plugins and can be added to Edit[s].
TimecodeSnapType getSnapType() const noexcept
Returns the current snap type.
#define jassert(expression)
T max(T... args)
TimeRange getTimeRangeForSelectedItems(const SelectableList &selected)
Returns the time range covered by the given items.
ClipTrack * findFirstClipTrackFromSelection(const SelectableList &items)
Returns the first ClipTrack from the selected tracks or clips.
ClipOwner * findClipOwnerForID(const Edit &edit, EditItemID id)
Returns the ClipOwner with a given ID if it can be found in the Edit.
juce::Array< AudioTrack * > getAudioTracks(const Edit &edit)
Returns all the AudioTracks in an Edit.
Track * findTrackForID(const Edit &edit, EditItemID id)
Returns the Track with a given ID if contained in the Edit.
juce::Array< Track * > findAllTracksContainingSelectedItems(const SelectableList &items)
Returns all the tracks containing the selected tracks or TrackItems.
T next(T... args)
Represents a position in real-life time.
ID for objects of type EditElement - e.g.
time
#define CRASH_TRACER
This macro adds the current location to a stack which gets logged if a crash happens.