Skip to content

Commit f9a4e10

Browse files
committed
Fixes for inserting space into the edit. This operation failed to update automation curves in racks or macro parameters, and also had edge-cases where space would be doubly-inserted into some curves.
1 parent 0368b12 commit f9a4e10

13 files changed

+150
-97
lines changed

modules/tracktion_engine/model/automation/tracktion_AutomationCurve.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,28 @@ void AutomationCurve::getBezierEnds (int index, double& x1out, float& y1out, dou
980980
y2out = static_cast<float> (ends.y2);
981981
}
982982

983+
void AutomationCurve::insertSpace (AutomatableParameter& param, TimePosition time, TimeDuration length)
984+
{
985+
if (getNumPoints() == 0)
986+
return;
987+
988+
auto um = getUndoManager_p (edit);
989+
auto defaultValue = param.getCurrentBaseValue();
990+
auto valueAtInsertionTime = getValueAt (time, defaultValue);
991+
992+
for (int k = getNumPoints(); --k >= 0;)
993+
if (getPointTime (k) >= time)
994+
movePoint (param, k,
995+
getPointTime (k) + length,
996+
getPointValue (k), false, um);
997+
998+
if (! juce::approximatelyEqual (valueAtInsertionTime, getValueAt (time, defaultValue)))
999+
addPoint (time, valueAtInsertionTime, 0.0f, um);
1000+
1001+
if (! juce::approximatelyEqual (valueAtInsertionTime, getValueAt (time + length, defaultValue)))
1002+
addPoint (time + length, valueAtInsertionTime, 0.0f, um);
1003+
}
1004+
9831005
void AutomationCurve::removeAllAutomationCurvesRecursively (const juce::ValueTree& v)
9841006
{
9851007
for (int i = v.getNumChildren(); --i >= 0;)

modules/tracktion_engine/model/automation/tracktion_AutomationCurve.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ class AutomationCurve
108108

109109
void simplify (EditTimeRange, EditDuration minTimeDifference, float minValueDifference, juce::UndoManager*);
110110

111+
/// Inserts space at the given time, moving all points at or after that time.
112+
void insertSpace (AutomatableParameter&, TimePosition, TimeDuration);
113+
111114
//==============================================================================
112115
static void removeAllAutomationCurvesRecursively (const juce::ValueTree&);
113116

modules/tracktion_engine/model/clips/tracktion_ContainerClip.test.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ class ContainerClipTests : public juce::UnitTest
136136
auto clip2VolPlug = dynamic_cast<VolumeAndPanPlugin*> (clip2->getPluginList()->insertPlugin (VolumeAndPanPlugin::create(), 0).get());
137137

138138
auto autoItems = getAllAutomatableEditItems (*edit);
139-
expect (autoItems.contains (ccVolPlug));
140-
expect (autoItems.contains (clip1VolPlug));
141-
expect (autoItems.contains (clip2VolPlug));
139+
expect (std::find (autoItems.begin(), autoItems.end(), ccVolPlug) != autoItems.end());
140+
expect (std::find (autoItems.begin(), autoItems.end(), clip1VolPlug) != autoItems.end());
141+
expect (std::find (autoItems.begin(), autoItems.end(), clip2VolPlug) != autoItems.end());
142142

143143
auto allParams = edit->getAllAutomatableParams (true);
144144
expect (allParams.contains (ccVolPlug->volParam.get()));

modules/tracktion_engine/model/edit/tracktion_Edit.test.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,29 @@ TEST_SUITE("tracktion_engine")
2626
CHECK(edit);
2727
CHECK(getAudioTracks (*edit).size() == 1);
2828
}
29+
30+
TEST_CASE ("insertSpaceIntoEdit: moves master volume automation")
31+
{
32+
auto& engine = *Engine::getEngines()[0];
33+
auto edit = Edit::createSingleTrackEdit (engine, Edit::EditRole::forRendering);
34+
auto um = &edit->getUndoManager();
35+
36+
auto masterVol = edit->getMasterVolumePlugin();
37+
REQUIRE (masterVol != nullptr);
38+
39+
auto volParam = masterVol->volParam.get();
40+
REQUIRE (volParam != nullptr);
41+
42+
auto& curve = volParam->getCurve();
43+
curve.addPoint (5_tp, 0.5f, 0.0f, um);
44+
45+
CHECK (curve.getPointTime (0) == 5_tp);
46+
47+
insertSpaceIntoEdit (*edit, { 2_tp, 2_td });
48+
49+
// Point should move from 5s to 7s
50+
CHECK (curve.getPointTime (0) == 7_tp);
51+
}
2952
}
3053

3154
//==============================================================================

modules/tracktion_engine/model/edit/tracktion_EditUtilities.cpp

Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,64 @@ bool referencesProjectItem (Edit& edit, ProjectItemRef itemRef)
4141

4242
//==============================================================================
4343
//==============================================================================
44-
void insertSpaceIntoEdit (Edit& edit, TimeRange timeRange)
44+
void insertSpaceIntoEdit (Edit& edit, TimeRange timeRange, const juce::Array<Track*>& onlyTheseTracks)
4545
{
46+
const bool allTracks = onlyTheseTracks.isEmpty();
4647
const bool doTempoTrackFirst = ! edit.getTimecodeFormat().isBarsBeats();
4748
const auto time = timeRange.getStart();
4849
const auto length = timeRange.getLength();
4950

50-
if (doTempoTrackFirst)
51-
edit.getTempoTrack()->insertSpaceIntoTrack (time, length);
51+
std::vector<ClipTrack*> clipTracks;
52+
std::vector<AutomatableEditItem*> automatableItems;
5253

53-
for (auto ct : getTracksOfType<ClipTrack> (edit, true))
54+
if (allTracks)
5455
{
55-
ct->splitAt (time);
56-
ct->insertSpaceIntoTrack (time, length);
56+
for (auto ct : getTracksOfType<ClipTrack> (edit, true))
57+
clipTracks.push_back (ct);
58+
59+
automatableItems = getAllAutomatableEditItems (edit);
60+
}
61+
else
62+
{
63+
for (auto t : onlyTheseTracks)
64+
{
65+
if (auto ct = dynamic_cast<ClipTrack*> (t))
66+
clipTracks.push_back (ct);
67+
68+
for (auto sub : t->getAllSubTracks (true))
69+
if (auto ct = dynamic_cast<ClipTrack*> (sub))
70+
clipTracks.push_back (ct);
71+
72+
auto trackItems = t->getAllAutomatableEditItems();
73+
automatableItems.insert (automatableItems.end(), trackItems.begin(), trackItems.end());
74+
}
5775
}
5876

59-
if (! doTempoTrackFirst)
60-
edit.getTempoTrack()->insertSpaceIntoTrack (time, length);
77+
// Deduplicate
78+
std::sort (clipTracks.begin(), clipTracks.end());
79+
clipTracks.erase (std::unique (clipTracks.begin(), clipTracks.end()), clipTracks.end());
80+
81+
std::sort (automatableItems.begin(), automatableItems.end());
82+
automatableItems.erase (std::unique (automatableItems.begin(), automatableItems.end()), automatableItems.end());
83+
84+
if (allTracks && doTempoTrackFirst)
85+
{
86+
edit.pitchSequence.insertSpaceIntoSequence (time, length, false);
87+
edit.tempoSequence.insertSpaceIntoSequence (time, length, false);
88+
}
89+
90+
for (auto ct : clipTracks)
91+
ct->insertSpace (time, length);
92+
93+
for (auto item : automatableItems)
94+
for (auto param : item->getAutomatableParameters())
95+
param->getCurve().insertSpace (*param, time, length);
96+
97+
if (allTracks && ! doTempoTrackFirst)
98+
{
99+
edit.pitchSequence.insertSpaceIntoSequence (time, length, false);
100+
edit.tempoSequence.insertSpaceIntoSequence (time, length, false);
101+
}
61102
}
62103

63104
void insertSpaceIntoEditFromBeatRange (Edit& edit, BeatRange beatRange)
@@ -1043,51 +1084,57 @@ void midiPanic (Edit& edit, bool resetPlugins)
10431084
}
10441085

10451086
//==============================================================================
1046-
juce::Array<AutomatableEditItem*> getAllAutomatableEditItems (const Edit& edit)
1087+
std::vector<AutomatableEditItem*> getAllAutomatableEditItems (const Edit& edit)
10471088
{
10481089
CRASH_TRACER
1049-
juce::Array<AutomatableEditItem*> destArray;
1090+
std::vector<AutomatableEditItem*> items;
10501091

10511092
if (auto mpl = edit.getGlobalMacros().getMacroParameterList())
1052-
destArray.add (mpl);
1093+
items.push_back (mpl);
10531094

10541095
edit.visitAllTracksRecursive ([&] (Track& t)
10551096
{
10561097
if (auto m = dynamic_cast<MacroParameterElement*> (&t))
10571098
if (auto mpl = m->getMacroParameterList())
1058-
destArray.add (mpl);
1099+
items.push_back (mpl);
10591100

1060-
destArray.addArray (t.getAllAutomatableEditItems());
1101+
auto trackItems = t.getAllAutomatableEditItems();
1102+
items.insert (items.end(), trackItems.begin(), trackItems.end());
10611103
return true;
10621104
});
10631105

10641106
for (auto p : edit.getMasterPluginList())
10651107
{
10661108
if (auto mpl = p->getMacroParameterList())
1067-
destArray.add (mpl);
1109+
items.push_back (mpl);
10681110

1069-
destArray.add (p);
1111+
items.push_back (p);
10701112
}
10711113

10721114
for (auto r : edit.getRackList().getTypes())
10731115
{
10741116
for (auto p : r->getPlugins())
10751117
{
1076-
destArray.add (p);
1118+
items.push_back (p);
10771119

10781120
if (auto mpl = p->getMacroParameterList())
1079-
destArray.add (mpl);
1121+
items.push_back (mpl);
10801122
}
10811123

10821124
if (auto mpl = r->getMacroParameterList())
1083-
destArray.add (mpl);
1125+
items.push_back (mpl);
10841126

1085-
destArray.addArray (r->getModifierList().getModifiers());
1127+
for (auto m : r->getModifierList().getModifiers())
1128+
items.push_back (m);
10861129
}
10871130

1088-
destArray.add (edit.getMasterVolumePlugin().get());
1131+
items.push_back (edit.getMasterVolumePlugin().get());
10891132

1090-
return destArray;
1133+
// Deduplicate
1134+
std::sort (items.begin(), items.end());
1135+
items.erase (std::unique (items.begin(), items.end()), items.end());
1136+
1137+
return items;
10911138
}
10921139

10931140
void deleteAutomation (const SelectableList& selectedClips)

modules/tracktion_engine/model/edit/tracktion_EditUtilities.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ bool referencesProjectItem (Edit&, ProjectItemRef);
3232
//==============================================================================
3333

3434
/// Inserts blank space in to an Edit, splitting clips if necessary.
35-
void insertSpaceIntoEdit (Edit&, TimeRange timeRangeToInsert);
35+
/// If onlyTheseTracks is provided, only those tracks are affected; otherwise all tracks are.
36+
void insertSpaceIntoEdit (Edit&, TimeRange timeRangeToInsert,
37+
const juce::Array<Track*>& onlyTheseTracks = {});
3638

3739
/// Inserts a number of blank beats in to the Edit.
3840
void insertSpaceIntoEditFromBeatRange (Edit&, BeatRange);
@@ -237,7 +239,7 @@ juce::ReferenceCountedObjectPtr<PluginType> insertNewPlugin (Track&, int index =
237239
//==============================================================================
238240

239241
/** Returns all AutomatableEditItems in an Edit. */
240-
juce::Array<AutomatableEditItem*> getAllAutomatableEditItems (const Edit&);
242+
std::vector<AutomatableEditItem*> getAllAutomatableEditItems (const Edit&);
241243

242244
/** Deletes the automation covered by the selected clips. */
243245
void deleteAutomation (const SelectableList& selectedClips);

modules/tracktion_engine/model/tracks/tracktion_ClipTrack.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -534,12 +534,11 @@ void ClipTrack::splitAt (TimePosition time)
534534
engine::split (*this, time);
535535
}
536536

537-
void ClipTrack::insertSpaceIntoTrack (TimePosition time, TimeDuration amountOfSpace)
537+
void ClipTrack::insertSpace (TimePosition time, TimeDuration length)
538538
{
539-
CRASH_TRACER
540-
Track::insertSpaceIntoTrack (time, amountOfSpace);
539+
splitAt (time);
541540

542-
// make a copied list first, as they'll get moved out-of-order..
541+
// Build a copied list first, as clips get moved out-of-order
543542
Clip::Array clipsToDo;
544543
const auto& clips = getClips();
545544

@@ -555,7 +554,7 @@ void ClipTrack::insertSpaceIntoTrack (TimePosition time, TimeDuration amountOfSp
555554

556555
for (int i = clipsToDo.size(); --i >= 0;)
557556
if (auto c = clipsToDo.getUnchecked (i).get())
558-
c->setStart (c->getPosition().getStart() + amountOfSpace, false, true);
557+
c->setStart (c->getPosition().getStart() + length, false, true);
559558
}
560559

561560
juce::Array<TimePosition> ClipTrack::findAllTimesOfInterest()

modules/tracktion_engine/model/tracks/tracktion_ClipTrack.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,6 @@ class ClipTrack : public Track,
4646
int getIndexOfNextTrackItemAt (TimePosition) override;
4747
TrackItem* getNextTrackItemAt (TimePosition) override;
4848

49-
/** inserts space and moves everything up */
50-
void insertSpaceIntoTrack (TimePosition, TimeDuration) override;
51-
5249
//==============================================================================
5350
TimeDuration getLength() const;
5451
TimeDuration getLengthIncludingInputTracks() const;
@@ -92,6 +89,9 @@ class ClipTrack : public Track,
9289
/** split all clips at this time */
9390
void splitAt (TimePosition);
9491

92+
/** Inserts space at the given time, moving clips whose center is after that point. */
93+
void insertSpace (TimePosition, TimeDuration);
94+
9595
/** finds the next cut point */
9696
TimePosition getNextTimeOfInterest (TimePosition afterThisTime);
9797
TimePosition getPreviousTimeOfInterest (TimePosition beforeThisTime);

modules/tracktion_engine/model/tracks/tracktion_TempoTrack.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,6 @@ TrackItem* TempoTrack::getNextTrackItemAt (TimePosition time)
5151
return getTrackItem (getIndexOfNextTrackItemAt (time));
5252
}
5353

54-
void TempoTrack::insertSpaceIntoTrack (TimePosition time, TimeDuration amountOfSpace)
55-
{
56-
Track::insertSpaceIntoTrack (time, amountOfSpace);
57-
58-
// Insert in to pitch sequence first of the tempo calculations will be different
59-
edit.pitchSequence.insertSpaceIntoSequence (time, amountOfSpace, false);
60-
edit.tempoSequence.insertSpaceIntoSequence (time, amountOfSpace, false);
61-
}
62-
6354
juce::Array<TrackItem*> TempoTrack::buildTrackItemList() const
6455
{
6556
juce::Array<TrackItem*> items;

modules/tracktion_engine/model/tracks/tracktion_TempoTrack.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ class TempoTrack : public Track
4545
/** @internal */
4646
bool canContainPlugin (Plugin*) const override;
4747

48-
/** @internal */
49-
void insertSpaceIntoTrack (TimePosition, TimeDuration) override;
50-
5148
private:
5249
juce::Array<TrackItem*> buildTrackItemList() const;
5350

0 commit comments

Comments
 (0)