Commit a3bc1439 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Another batch of tests and fixes for same track transitions on grouped clips

parent 0378f6d1
......@@ -2656,7 +2656,7 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
Fun sync_mix = []() { return true; };
Fun sync_end_mix = []() { return true; };
Fun sync_end_mix_undo = []() { return true; };
Fun sync_mix_undo = []() { return true; };
PUSH_LAMBDA(sync_mix, undo);
std::unordered_set<int> all_items;
QList <int> tracksWithMixes;
all_items.insert(itemId);
......@@ -2690,11 +2690,22 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
tracksWithMixes << tid;
std::pair<MixInfo, MixInfo> mixData = getTrackById_const(tid)->getMixInfo(itemId);
if (out - size >= mixData.first.firstClipInOut.second) {
// Moved outside mix, delete
Fun sync_mix_undo = [this, tid, mixData]() {
getTrackById_const(tid)->createMix(mixData.first, getTrackById_const(tid)->isAudioTrack());
return true;
};
bool switchPlaylist = getTrackById_const(tid)->hasEndMix(itemId) == false && m_allClips[itemId]->getSubPlaylistIndex() == 1;
if (switchPlaylist) {
sync_end_mix = [this, tid, itemId, mixData]() {
return getTrackById_const(tid)->switchPlaylist(mixData.first.secondClipId, m_allClips[mixData.first.secondClipId]->getPosition(), 1, 0);
};
sync_end_mix_undo = [this, tid, mixData]() {
return getTrackById_const(tid)->switchPlaylist(mixData.first.secondClipId, m_allClips[mixData.first.secondClipId]->getPosition(), 0, 1);
};
}
PUSH_LAMBDA(sync_mix_undo, undo);
}
}
}
......@@ -2733,10 +2744,22 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
}
std::pair<MixInfo, MixInfo> mixData = getTrackById_const(tid)->getMixInfo(id);
if (end - offset <= mixData.second.secondClipInOut.first) {
// Resized outside mix
Fun sync_mix_undo = [this, tid, mixData]() {
getTrackById_const(tid)->createMix(mixData.second, getTrackById_const(tid)->isAudioTrack());
return true;
};
bool switchPlaylist = getTrackById_const(tid)->hasEndMix(mixData.second.secondClipId) == false && m_allClips[mixData.second.secondClipId]->getSubPlaylistIndex() == 1;
if (switchPlaylist) {
Fun sync_end_mix2 = [this, tid, mixData]() {
return getTrackById_const(tid)->switchPlaylist(mixData.second.secondClipId, mixData.second.secondClipInOut.first, 1, 0);
};
Fun sync_end_mix_undo2 = [this, tid, mixData]() {
return getTrackById_const(tid)->switchPlaylist(mixData.second.secondClipId, m_allClips[mixData.second.secondClipId]->getPosition(), 0, 1);
};
PUSH_LAMBDA(sync_end_mix2, sync_end_mix);
PUSH_LAMBDA(sync_end_mix_undo2, sync_end_mix_undo);
}
PUSH_LAMBDA(sync_mix_undo, undo);
}
}
......@@ -2745,11 +2768,23 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
tracksWithMixes << tid;
}
std::pair<MixInfo, MixInfo> mixData = getTrackById_const(tid)->getMixInfo(id);
if (start - offset >= mixData.first.firstClipInOut.second) {
if (start + offset >= mixData.first.firstClipInOut.second) {
// Moved outside mix, remove
Fun sync_mix_undo = [this, tid, mixData]() {
getTrackById_const(tid)->createMix(mixData.first, getTrackById_const(tid)->isAudioTrack());
return true;
};
bool switchPlaylist = getTrackById_const(tid)->hasEndMix(id) == false && m_allClips[id]->getSubPlaylistIndex() == 1;
if (switchPlaylist) {
Fun sync_end_mix2 = [this, tid, mixData]() {
return getTrackById_const(tid)->switchPlaylist(mixData.first.secondClipId, m_allClips[mixData.first.secondClipId]->getPosition(), 1, 0);
};
Fun sync_end_mix_undo2 = [this, tid, mixData]() {
return getTrackById_const(tid)->switchPlaylist(mixData.first.secondClipId, m_allClips[mixData.first.secondClipId]->getPosition(), 0, 1);
};
PUSH_LAMBDA(sync_end_mix2, sync_end_mix);
PUSH_LAMBDA(sync_end_mix_undo2, sync_end_mix_undo);
}
PUSH_LAMBDA(sync_mix_undo, undo);
}
}
......@@ -2769,8 +2804,6 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
int finalPos = right ? in + size : out - size;
int finalSize;
int resizedCount = 0;
PUSH_LAMBDA(sync_mix, undo);
PUSH_LAMBDA(sync_mix_undo, undo);
for (int id : all_items) {
int tid = getItemTrackId(id);
if (tid > -1 && getTrackById_const(tid)->isLocked()) {
......@@ -2781,10 +2814,12 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
} else {
finalSize = getItemPosition(id) + getItemPlaytime(id) - finalPos;
}
result = result && requestItemResize(id, finalSize, right, logUndo, undo, redo);
resizedCount++;
}
if (!result || resizedCount == 0) {
qDebug()<<"=== RESIZE ABORTED, RESULT: "<<result;
bool undone = undo();
Q_ASSERT(undone);
TRACE_RES(-1)
......
......@@ -137,10 +137,12 @@ bool TrackModel::switchPlaylist(int clipId, int position, int sourcePlaylist, in
Q_ASSERT(!m_playlists[sourcePlaylist].is_blank_at(position) && m_playlists[destPlaylist].is_blank_at(position));
int target_clip = m_playlists[sourcePlaylist].get_clip_index_at(position);
std::unique_ptr<Mlt::Producer> prod(m_playlists[sourcePlaylist].replace_with_blank(target_clip));
m_playlists[sourcePlaylist].consolidate_blanks();
if (auto ptr = m_parent.lock()) {
std::shared_ptr<ClipModel> clip = ptr->getClipPtr(clipId);
int index = m_playlists[destPlaylist].insert_at(position, *clip, 1);
clip->setSubPlaylistIndex(destPlaylist);
m_playlists[destPlaylist].consolidate_blanks();
return index != -1;
}
return false;
......@@ -698,7 +700,6 @@ Fun TrackModel::requestClipResize_lambda(int clipId, int in, int out, bool right
qDebug()<<"==== NOPE ABORT RESIZE";
}
}
return []() { return false; };
}
......@@ -1435,6 +1436,7 @@ bool TrackModel::requestClipMix(std::pair<int, int> clipIds, int mixDuration, bo
QWriteLocker locker(&m_lock);
// By default, insertion occurs in topmost track
// Find out the clip id at position
int firstClipPos;
int secondClipPos;
int secondClipDuration;
int firstClipDuration;
......@@ -1451,7 +1453,8 @@ bool TrackModel::requestClipMix(std::pair<int, int> clipIds, int mixDuration, bo
std::shared_ptr<ClipModel> firstClip(ptr->getClipPtr(clipIds.first));
firstClipDuration = firstClip->getPlaytime();
// Ensure mix is not longer than clip
mixPosition = qMax(firstClip->getPosition(), secondClipPos - mixDuration / 2);
firstClipPos = firstClip->getPosition();
mixPosition = qMax(firstClipPos, secondClipPos - mixDuration / 2);
int maxPos = qMin(secondClipPos + secondClipDuration, secondClipPos + mixDuration - (mixDuration / 2));
mixDuration = qMin(mixDuration, maxPos - mixPosition);
if (firstClip->getSubPlaylistIndex() == 1) {
......@@ -1554,7 +1557,7 @@ bool TrackModel::requestClipMix(std::pair<int, int> clipIds, int mixDuration, bo
auto operation = requestClipDeletion_lambda(clipIds.second, updateView, finalMove, groupMove, finalMove);
bool res = operation();
if (res) {
Fun replay = [this, clipIds, dest_track, firstClipDuration, secondClipDuration, mixDuration, build_mix, secondClipPos, updateView, finalMove, groupMove, rearrange_playlists]() {
Fun replay = [this, clipIds, dest_track, firstClipPos, secondClipDuration, mixPosition, mixDuration, build_mix, secondClipPos, updateView, finalMove, groupMove, rearrange_playlists]() {
if (auto ptr = m_parent.lock()) {
ptr->getClipPtr(clipIds.second)->setSubPlaylistIndex(dest_track);
}
......@@ -1566,8 +1569,8 @@ bool TrackModel::requestClipMix(std::pair<int, int> clipIds, int mixDuration, bo
std::function<bool(void)> local_undo = []() { return true; };
std::function<bool(void)> local_redo = []() { return true; };
if (auto ptr = m_parent.lock()) {
result = ptr->getClipPtr(clipIds.second)->requestResize(secondClipDuration + mixDuration / 2, false, local_undo, local_redo, false);
result = ptr->getClipPtr(clipIds.first)->requestResize(firstClipDuration + mixDuration / 2, true, local_undo, local_redo, false);
result = ptr->getClipPtr(clipIds.second)->requestResize(secondClipPos + secondClipDuration - mixPosition, false, local_undo, local_redo, false);
result = ptr->getClipPtr(clipIds.first)->requestResize(mixPosition + mixDuration - firstClipPos, true, local_undo, local_redo, false);
QModelIndex ix = ptr->makeClipIndexFromID(clipIds.second);
emit ptr->dataChanged(ix, ix, {TimelineModel::StartRole,TimelineModel::MixRole});
}
......
......@@ -65,7 +65,7 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
// Create AV clip 2
REQUIRE(timeline->requestClipInsertion(binId, tid2, 110, cid2));
REQUIRE(timeline->requestItemResize(cid2, 10, false, true));
REQUIRE(timeline->requestItemResize(cid2, 10, true, true));
REQUIRE(timeline->requestClipMove(cid2, tid2, 110));
// Create color clip 1
......@@ -99,6 +99,16 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
};
auto state3 = [&]() {
REQUIRE(timeline->getClipsCount() == 6);
REQUIRE(timeline->getClipPlaytime(cid1) > 30);
REQUIRE(timeline->getClipPosition(cid1) == 100);
REQUIRE(timeline->getClipPlaytime(cid2) > 30);
REQUIRE(timeline->getClipPosition(cid2) < 130);
REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
};
auto state2 = [&]() {
REQUIRE(timeline->getClipsCount() == 6);
REQUIRE(timeline->getClipPlaytime(cid3) > 20);
......@@ -210,6 +220,9 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
SECTION("Create and delete mix on AV clips")
{
state0();
REQUIRE(timeline->requestItemResize(cid2, 30, true, true) == 30);
REQUIRE(timeline->requestItemResize(cid2, 10, false, true) == 10);
REQUIRE(timeline->requestClipMove(cid2, tid2, 110));
REQUIRE(timeline->mixClip(cid2));
state1();
undoStack->undo();
......@@ -224,10 +237,14 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
{
// CID 1 length=10, pos=100, CID2 length=10, pos=110
// Default mix duration = 25 frames (12 before / 13 after)
// Resize CID2 so that it has some space to expand left
REQUIRE(timeline->requestItemResize(cid2, 30, true, true) == 30);
REQUIRE(timeline->requestItemResize(cid2, 10, false, true) == 10);
REQUIRE(timeline->requestClipMove(cid2, tid2, 110));
// Resize clip, should resize the mix
state0();
REQUIRE(timeline->mixClip(cid2));
state1();
//state1();
// Move clip inside mix zone, should resize the mix
REQUIRE(timeline->requestClipMove(cid2, tid2, 101));
REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
......@@ -252,20 +269,88 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
state2();
// CID 3 length=20, pos=500, CID4 length=20, pos=520
// Default mix duration = 25 frames (12 before / 13 after)
// Resize clip, should resize the mix
REQUIRE(timeline->requestItemResize(cid3, 16, true) == 16);
// Resize left clip, should resize the mix
REQUIRE(timeline->requestItemResize(cid3, 16, true, true) == 16);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
undoStack->undo();
state2();
// Resize left clip outside mix zone, should delete the mix
REQUIRE(timeline->requestItemResize(cid3, 4, true, true) == 4);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
undoStack->undo();
state2();
// Resize right clip, should resize the mix
REQUIRE(timeline->requestItemResize(cid4, 16, false, true) == 16);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
undoStack->undo();
state2();
// Resize clip outside mix zone, should delete the mix
REQUIRE(timeline->requestItemResize(cid3, 4, true) == 4);
// Resize right clip outside mix zone, should delete the mix
REQUIRE(timeline->requestItemResize(cid4, 4, false, true) == 4);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
undoStack->undo();
//state2();
state2();
undoStack->undo();
state0();
}
SECTION("Create mix on AV clips and resize")
{
state0();
// CID 1 length=10, pos=100, CID2 length=10, pos=110
REQUIRE(timeline->m_allClips[cid1]->getPlaytime() == 10);
REQUIRE(timeline->m_allClips[cid2]->getPlaytime() == 10);
REQUIRE(timeline->requestItemResize(cid2, 50, true, true) == 50);
REQUIRE(timeline->requestItemResize(cid2, 30, false, true) == 30);
REQUIRE(timeline->requestClipMove(cid2, tid2, 130));
REQUIRE(timeline->requestItemResize(cid1, 30, true, true) == 30);
REQUIRE(timeline->mixClip(cid2));
state3();
// CID 1 length=30, pos=100, CID2 length=30, pos=130
// Default mix duration = 25 frames (12 before / 13 after)
// Resize left clip, should resize the mix
REQUIRE(timeline->requestItemResize(cid1, 25, true, true) == 25);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 1);
undoStack->undo();
state3();
// Resize left clip outside mix zone, should delete the mix
REQUIRE(timeline->requestItemResize(cid1, 10, true, true) == 10);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 0);
REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 0);
undoStack->undo();
state3();
// Resize right clip, should resize the mix
REQUIRE(timeline->requestItemResize(cid2, 25, false, true) == 25);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 1);
undoStack->undo();
state3();
// Resize right clip outside mix zone, should delete the mix
REQUIRE(timeline->requestItemResize(cid2, 4, false, true) == 4);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 0);
REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 0);
undoStack->undo();
state3();
undoStack->undo();
undoStack->undo();
undoStack->undo();
undoStack->undo();
state0();
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment