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

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_MarkerManager.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
14MarkerManager::MarkerManager (Edit& e, const juce::ValueTree& v)
15 : edit (e), state (v)
16{
17 state.addListener (this);
18}
19
20MarkerManager::~MarkerManager()
21{
22 state.removeListener (this);
23}
24
25juce::ReferenceCountedArray<MarkerClip> MarkerManager::getMarkers() const
26{
29
30 if (auto mt = edit.getMarkerTrack())
31 for (auto clip : mt->getClips())
32 if (auto mc = dynamic_cast<MarkerClip*> (clip))
33 results.add (mc);
34
35 TrackItem::sortByTime (results);
36 return results;
37}
38
39int MarkerManager::getNextUniqueID (int start)
40{
41 juce::SortedSet<int> uniqueIDs;
42
43 for (auto m : getMarkers())
44 uniqueIDs.add (m->getMarkerID());
45
46 while (uniqueIDs.contains (start))
47 ++start;
48
49 return start;
50}
51
52void MarkerManager::checkForDuplicates (MarkerClip& clip, bool changeOthers)
53{
54 for (auto m : getMarkers())
55 {
56 if (&clip != m && clip.getMarkerID() == m->getMarkerID())
57 {
58 if (changeOthers)
59 m->setMarkerID (getNextUniqueID (clip.getMarkerID()));
60 else
61 clip.setMarkerID (getNextUniqueID (clip.getMarkerID()));
62 }
63 }
64}
65
66MarkerClip* MarkerManager::getMarkerByID (int id)
67{
68 for (auto m : getMarkers())
69 if (m->getMarkerID() == id)
70 return m;
71
72 return {};
73}
74
75MarkerClip* MarkerManager::getNextMarker (TimePosition nowTime)
76{
77 MarkerClip* next = nullptr;
78
79 for (auto m : getMarkers())
80 {
81 auto diff = m->getPosition().getStart() - nowTime;
82 auto nextDiff = next ? next->getPosition().getStart() - nowTime : TimeDuration();
83
84 if (diff > TimeDuration::fromSeconds (0.001) && ((next == nullptr) || (diff < nextDiff)))
85 next = m;
86 }
87
88 return next;
89}
90
91MarkerClip* MarkerManager::getPrevMarker (TimePosition nowTime)
92{
93 MarkerClip* prev = nullptr;
94
95 for (auto m : getMarkers())
96 {
97 auto diff = m->getPosition().getStart() - nowTime;
98 auto prevDiff = prev ? prev->getPosition().getStart() - nowTime : TimeDuration();
99
100 if (diff < TimeDuration::fromSeconds (-0.001) && ((prev == nullptr) || (diff > prevDiff)))
101 prev = m;
102 }
103
104 return prev;
105}
106
107MarkerClip::Ptr MarkerManager::createMarker (int number, TimePosition pos, TimeDuration length,
108 Clip::SyncType type, SelectionManager* sm)
109{
110 if (length == TimeDuration())
111 {
112 auto& tempo = edit.tempoSequence.getTempoAt (pos);
113 length = TimeDuration::fromSeconds (tempo.getMatchingTimeSig().numerator.get() * tempo.getApproxBeatLength().inSeconds());
114 }
115
116 if (auto track = edit.getMarkerTrack())
117 {
118 if (auto clip = dynamic_cast<MarkerClip*> (track->insertNewClip (TrackItem::Type::marker,
119 { pos, pos + length }, sm)))
120 {
121 clip->setSyncType (type);
122 clip->setStart (pos, true, true);
123
124 if (length > TimeDuration())
125 clip->setLength (length, true);
126
127 if (number >= 0)
128 clip->setMarkerID (number);
129
130 return clip;
131 }
132 }
133
135 return {};
136}
137
138Clip::SyncType MarkerManager::getNewMarkerMode() const
139{
140 const int newMarkerMode = edit.engine.getPropertyStorage().getProperty (SettingID::newMarker);
141
142 if (newMarkerMode == 0 || (newMarkerMode == 2 && edit.getTimecodeFormat().isBarsBeats()))
143 return Clip::syncBarsBeats;
144
145 return Clip::syncAbsolute;
146}
147
148MarkerClip::Ptr MarkerManager::createMarker (int number, TimePosition pos, TimeDuration length, SelectionManager* sm)
149{
150 return createMarker (number, pos, length, getNewMarkerMode(), sm);
151}
152
153void MarkerManager::valueTreeChanged (const juce::ValueTree& v)
154{
155 if (v.hasType (IDs::MARKERTRACK) || v.getParent().hasType (IDs::MARKERTRACK))
156 sendChangeMessage();
157}
158
159void MarkerManager::valueTreePropertyChanged (juce::ValueTree& v, const juce::Identifier&) { valueTreeChanged (v); }
160void MarkerManager::valueTreeChildAdded (juce::ValueTree& p, juce::ValueTree&) { valueTreeChanged (p); }
161void MarkerManager::valueTreeChildRemoved (juce::ValueTree& p, juce::ValueTree&, int) { valueTreeChanged (p); }
162void MarkerManager::valueTreeParentChanged (juce::ValueTree& v) { valueTreeChanged (v); }
163
164}} // namespace tracktion { inline namespace engine
bool contains(const ElementType &elementToLookFor) const noexcept
Manages a list of items that are currently selected.
#define jassertfalse
T next(T... args)
T prev(T... args)
Represents a duration in real-life time.
Represents a position in real-life time.
#define CRASH_TRACER
This macro adds the current location to a stack which gets logged if a crash happens.