File indexing completed on 2024-04-14 04:47:49

0001 /*
0002     SPDX-FileCopyrightText: 2020-2022 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 #include "catch.hpp"
0006 #include "test_utils.hpp"
0007 // test specific headers
0008 #include "doc/docundostack.hpp"
0009 #include "doc/kdenlivedoc.h"
0010 #include <QString>
0011 #include <cmath>
0012 #include <iostream>
0013 #include <tuple>
0014 #include <unordered_set>
0015 
0016 #include "core.h"
0017 #include "definitions.h"
0018 
0019 using namespace fakeit;
0020 
0021 TEST_CASE("Simple Mix", "[SameTrackMix]")
0022 {
0023     // Ensure our core profile is correct
0024     REQUIRE(pCore->timecode().fps() == 25.);
0025     REQUIRE(pCore->getDurationFromString(KdenliveSettings::mix_duration()) == 25);
0026 
0027     // Create timeline
0028     auto binModel = pCore->projectItemModel();
0029     std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
0030     // Here we do some trickery to enable testing.
0031     // We mock the project class so that the undoStack function returns our undoStack
0032     KdenliveDoc document(undoStack);
0033 
0034     pCore->projectManager()->m_project = &document;
0035     QDateTime documentDate = QDateTime::currentDateTime();
0036     pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0037     auto timeline = document.getTimeline(document.uuid());
0038     pCore->projectManager()->testSetActiveDocument(&document, timeline);
0039 
0040     // Create a request
0041     int tid1 = timeline->getTrackIndexFromPosition(0);
0042     int tid3 = timeline->getTrackIndexFromPosition(1);
0043     int tid2 = timeline->getTrackIndexFromPosition(2);
0044     int tid4 = timeline->getTrackIndexFromPosition(3);
0045 
0046     // Create clip with audio
0047     QString binId = createProducerWithSound(pCore->getProjectProfile(), binModel, 100);
0048 
0049     // Create video clip
0050     QString binId2 = createProducer(pCore->getProjectProfile(), "red", binModel, 50, false);
0051     // Setup insert stream data
0052     QMap<int, QString> audioInfo;
0053     audioInfo.insert(1, QStringLiteral("stream1"));
0054     timeline->m_binAudioTargets = audioInfo;
0055 
0056     // Create AV clip 1
0057     int cid1;
0058     int cid2;
0059     int cid3;
0060     int cid4;
0061     int cid5;
0062     int audio1;
0063     int audio2;
0064     int audio5;
0065     REQUIRE(timeline->requestClipInsertion(binId, tid2, 100, cid1));
0066     REQUIRE(timeline->requestItemResize(cid1, 10, true, true));
0067     audio1 = timeline->getClipSplitPartner(cid1);
0068 
0069     // Create AV clip 2
0070     REQUIRE(timeline->requestClipInsertion(binId, tid2, 110, cid2));
0071     REQUIRE(timeline->requestItemResize(cid2, 10, true, true));
0072     REQUIRE(timeline->requestClipMove(cid2, tid2, 110));
0073     audio2 = timeline->getClipSplitPartner(cid2);
0074 
0075     // Create color clip 1
0076     REQUIRE(timeline->requestClipInsertion(binId2, tid2, 500, cid3));
0077     REQUIRE(timeline->requestItemResize(cid3, 20, true, true));
0078     REQUIRE(timeline->requestClipInsertion(binId2, tid2, 520, cid4));
0079     REQUIRE(timeline->requestItemResize(cid4, 20, true, true));
0080     int mixDuration = pCore->getDurationFromString(KdenliveSettings::mix_duration());
0081 
0082     auto state0 = [&]() {
0083         REQUIRE(timeline->getClipsCount() == 6);
0084         REQUIRE(timeline->getClipPlaytime(cid1) == 10);
0085         REQUIRE(timeline->getClipPosition(cid1) == 100);
0086         REQUIRE(timeline->getClipPlaytime(cid2) == 10);
0087         REQUIRE(timeline->getClipPosition(cid2) == 110);
0088         REQUIRE(timeline->getClipPosition(cid3) == 500);
0089         REQUIRE(timeline->getClipPlaytime(cid3) == 20);
0090         REQUIRE(timeline->getClipPosition(cid4) == 520);
0091         REQUIRE(timeline->getClipPlaytime(cid4) == 20);
0092         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0093         REQUIRE(timeline->getTrackById_const(tid1)->mixCount() == 0);
0094         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0095     };
0096 
0097     auto state0b = [&]() {
0098         REQUIRE(timeline->getClipsCount() == 8);
0099         REQUIRE(timeline->getClipPlaytime(cid1) == 10);
0100         REQUIRE(timeline->getClipPosition(cid1) == 100);
0101         REQUIRE(timeline->getClipPlaytime(cid2) == 10);
0102         REQUIRE(timeline->getClipPosition(cid2) == 110);
0103         REQUIRE(timeline->getClipPlaytime(cid5) == 10);
0104         REQUIRE(timeline->getClipPosition(cid5) == 120);
0105         REQUIRE(timeline->getClipPosition(cid3) == 500);
0106         REQUIRE(timeline->getClipPlaytime(cid3) == 20);
0107         REQUIRE(timeline->getClipPosition(cid4) == 520);
0108         REQUIRE(timeline->getClipPlaytime(cid4) == 20);
0109         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0110         REQUIRE(timeline->getTrackById_const(tid1)->mixCount() == 0);
0111         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0112     };
0113 
0114     auto state1 = [&]() {
0115         REQUIRE(timeline->getClipsCount() == 6);
0116         REQUIRE(timeline->getClipPlaytime(cid1) > 10);
0117         REQUIRE(timeline->getClipPosition(cid1) == 100);
0118         REQUIRE(timeline->getClipPlaytime(cid2) > 10);
0119         REQUIRE(timeline->getClipPosition(cid2) < 110);
0120         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
0121         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0122     };
0123 
0124     auto state1b = [&]() {
0125         REQUIRE(timeline->getClipsCount() == 8);
0126         REQUIRE(timeline->getClipPlaytime(cid1) > 10);
0127         REQUIRE(timeline->getClipPosition(cid1) == 100);
0128         REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
0129         REQUIRE(timeline->m_allClips[audio1]->getSubPlaylistIndex() == 0);
0130         REQUIRE(timeline->getClipPlaytime(cid2) > 10);
0131         REQUIRE(timeline->getClipPosition(cid2) < 110);
0132         REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 1);
0133         REQUIRE(timeline->m_allClips[audio2]->getSubPlaylistIndex() == 1);
0134         REQUIRE(timeline->getClipPlaytime(cid5) == 10);
0135         REQUIRE(timeline->getClipPosition(cid5) == 120);
0136         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0137         REQUIRE(timeline->m_allClips[audio5]->getSubPlaylistIndex() == 0);
0138         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
0139         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0140     };
0141 
0142     auto state3 = [&, mixDuration]() {
0143         REQUIRE(timeline->getClipsCount() == 6);
0144         REQUIRE(timeline->getClipPlaytime(cid1) > 30);
0145         REQUIRE(timeline->getClipPosition(cid1) == 100);
0146         REQUIRE(timeline->getClipPlaytime(cid2) > 30);
0147         REQUIRE(timeline->getClipPosition(cid2) < 130);
0148         REQUIRE(timeline->m_allClips[cid2]->getMixDuration() == mixDuration);
0149         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
0150         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0151     };
0152 
0153     auto state2 = [&]() {
0154         REQUIRE(timeline->getClipsCount() == 6);
0155         REQUIRE(timeline->getClipPlaytime(cid3) == 32);
0156         REQUIRE(timeline->getClipPosition(cid3) == 500);
0157         REQUIRE(timeline->getClipPlaytime(cid4) == 33);
0158         REQUIRE(timeline->getClipPosition(cid4) == 507);
0159         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0160         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0161         REQUIRE(timeline->getTrackById_const(tid1)->mixCount() == 0);
0162         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0163     };
0164 
0165     SECTION("Create and delete mix on color clips")
0166     {
0167         state0();
0168         REQUIRE(timeline->mixClip(cid4));
0169         state2();
0170         undoStack->undo();
0171         state0();
0172         undoStack->redo();
0173         state2();
0174         undoStack->undo();
0175         state0();
0176     }
0177 
0178     SECTION("Create mix on color clips and move main (right side) clip")
0179     {
0180         // CID 3 length=20, pos=500, CID4 length=20, pos=520
0181         // Default mix duration = 25 frames (12 before / 13 after)
0182         state0();
0183         REQUIRE(timeline->mixClip(cid4));
0184         state2();
0185 
0186         // Move right clip to the left, should fail
0187         REQUIRE(timeline->requestClipMove(cid4, tid2, 506) == false);
0188 
0189         // Move clip inside mix zone, should delete the mix
0190         REQUIRE(timeline->requestClipMove(cid4, tid2, 509));
0191         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0192         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0193         undoStack->undo();
0194         state2();
0195         // Move clip outside mix zone, should delete the mix and move it back to playlist 0
0196         REQUIRE(timeline->requestClipMove(cid4, tid2, 600));
0197         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0198         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0199         undoStack->undo();
0200         state2();
0201         // Move clip to another track, should delete mix
0202         REQUIRE(timeline->requestClipMove(cid4, tid4, 600));
0203         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0204         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0205         REQUIRE(timeline->getTrackById_const(tid4)->mixCount() == 0);
0206         undoStack->undo();
0207         state2();
0208         undoStack->undo();
0209         state0();
0210     }
0211 
0212     SECTION("Create mix on color clip and move left side clip")
0213     {
0214         state0();
0215         REQUIRE(timeline->mixClip(cid4));
0216         state2();
0217 
0218         // Move left clip to the right, should silently fail
0219         REQUIRE(timeline->requestClipMove(cid3, tid2, 502, true, true, false) == false);
0220         REQUIRE(timeline->getClipPosition(cid3) == 500);
0221 
0222         // Move clip inside mix zone, should delete the mix
0223         REQUIRE(timeline->requestClipMove(cid3, tid2, 499));
0224         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0225         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0226         undoStack->undo();
0227         state2();
0228         // Move clip outside mix zone, should delete the mix
0229         REQUIRE(timeline->requestClipMove(cid3, tid2, 450));
0230         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0231         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0232         undoStack->undo();
0233         state2();
0234         // Move clip to another track, should delete mix
0235         REQUIRE(timeline->requestClipMove(cid3, tid4, 600));
0236         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0237         REQUIRE(timeline->getTrackById_const(tid4)->mixCount() == 0);
0238         undoStack->undo();
0239         state2();
0240         undoStack->undo();
0241         state0();
0242     }
0243 
0244     SECTION("Create mix on color clips and move some to another track")
0245     {
0246         state0();
0247         // insert third color clip
0248         cid5 = -1;
0249         REQUIRE(timeline->requestClipInsertion(binId2, tid2, 540, cid5));
0250         REQUIRE(timeline->requestItemResize(cid5, 20, true, true));
0251         REQUIRE(timeline->getClipPosition(cid5) == 540);
0252         audio5 = timeline->getClipSplitPartner(cid5);
0253 
0254         // CID 3 length=20, pos=500, CID4 length=20, pos=520, CID5 length=20, pos=540
0255         // Default mix duration = 25 frames (12 before / 13 after)
0256 
0257         REQUIRE(timeline->mixClip(cid3));
0258         REQUIRE(timeline->mixClip(cid4));
0259         REQUIRE(timeline->getClipPosition(cid5) < 540);
0260         undoStack->undo();
0261         REQUIRE(timeline->getClipPosition(cid5) == 540);
0262         undoStack->redo();
0263         REQUIRE(timeline->getClipPosition(cid5) < 540);
0264         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0265         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0266         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0267         REQUIRE(timeline->getTrackById_const(tid4)->mixCount() == 0);
0268         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 2);
0269 
0270         // Move middle clip to another track, should delete the mixes
0271         REQUIRE(timeline->requestClipMove(cid4, tid4, 500));
0272         REQUIRE(timeline->getClipPosition(cid5) == 540);
0273         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0274         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0275         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0276         REQUIRE(timeline->getTrackById_const(tid4)->mixCount() == 0);
0277         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0278 
0279         // Undo track move
0280         undoStack->undo();
0281         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0282         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0283         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0284         REQUIRE(timeline->getTrackById_const(tid4)->mixCount() == 0);
0285         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 2);
0286 
0287         // Undo mixes
0288         undoStack->undo();
0289         undoStack->undo();
0290         // undo 3rd clip resize & insert
0291         undoStack->undo();
0292         undoStack->undo();
0293         state0();
0294     }
0295 
0296     SECTION("Create mix on color clips and group move")
0297     {
0298         state0();
0299         REQUIRE(timeline->mixClip(cid4));
0300         state2();
0301         // Move clip inside mix zone, should resize the mix
0302         auto g1 = std::unordered_set<int>({cid3, cid4});
0303         REQUIRE(timeline->requestClipsGroup(g1));
0304         // Move clip to another track, should delete mix
0305         REQUIRE(timeline->requestClipMove(cid4, tid4, 600));
0306         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0307         REQUIRE(timeline->getTrackById_const(tid4)->mixCount() == 1);
0308         undoStack->undo();
0309         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0310         REQUIRE(timeline->getTrackById_const(tid4)->mixCount() == 0);
0311         state2();
0312         // Move on same track
0313         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0314         REQUIRE(timeline->requestClipMove(cid4, tid3, 800));
0315         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0316         undoStack->undo();
0317         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0318         state2();
0319         // Undo group
0320         undoStack->undo();
0321         // Undo mix
0322         undoStack->undo();
0323         state0();
0324     }
0325 
0326     SECTION("Create and delete mix on AV clips")
0327     {
0328         state0();
0329         // Clips are cid1 at 100, cid2 at 110
0330         REQUIRE(timeline->requestItemResize(cid2, 30, true, true) == 30);
0331         REQUIRE(timeline->requestItemResize(cid2, 10, false, true) == 10);
0332         REQUIRE(timeline->requestClipMove(cid2, tid2, 110));
0333         REQUIRE(timeline->mixClip(cid1));
0334         state1();
0335         undoStack->undo();
0336         state0();
0337         undoStack->redo();
0338         state1();
0339         undoStack->undo();
0340         state0();
0341     }
0342 
0343     SECTION("Create mix and move AV clips")
0344     {
0345         // CID 1 length=10, pos=100, CID2 length=10, pos=110
0346         // Default mix duration = 25 frames (12 before / 13 after)
0347         // Resize CID2 so that it has some space to expand left
0348         REQUIRE(timeline->requestItemResize(cid2, 30, true, true) == 30);
0349         REQUIRE(timeline->requestItemResize(cid2, 10, false, true) == 10);
0350         REQUIRE(timeline->requestClipMove(cid2, tid2, 110));
0351         // Resize clip, should resize the mix
0352         state0();
0353         REQUIRE(timeline->mixClip(cid2));
0354         state1();
0355         // Resize right clip, should resize the mix
0356         REQUIRE(timeline->requestItemResize(cid2, 15, false, true) == 15);
0357         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
0358         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0359         undoStack->undo();
0360         state1();
0361         // Resize left clip, should resize the mix
0362         REQUIRE(timeline->requestItemResize(cid1, 20, true, true) == 20);
0363         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
0364         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0365         undoStack->undo();
0366         state1();
0367         // Move clip outside mix zone, should delete the mix
0368         REQUIRE(timeline->requestClipMove(cid2, tid2, 200));
0369         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 0);
0370         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0371         undoStack->undo();
0372         state1();
0373         // Undo mix
0374         undoStack->undo();
0375         state0();
0376     }
0377 
0378     SECTION("Create chained mixes on AV clips")
0379     {
0380         // CID 1 length=10, pos=100, CID2 length=10, pos=110
0381         // Default mix duration = 25 frames (12 before / 13 after)
0382         // Resize CID2 so that it has some space to expand left
0383         REQUIRE(timeline->requestItemResize(cid2, 30, true, true) == 30);
0384         REQUIRE(timeline->requestItemResize(cid2, 10, false, true) == 10);
0385         REQUIRE(timeline->requestClipMove(cid2, tid2, 110));
0386         state0();
0387 
0388         // Create a third AV clip and make some space
0389         cid5 = -1;
0390         REQUIRE(timeline->requestClipInsertion(binId, tid2, 120, cid5));
0391         REQUIRE(timeline->requestItemResize(cid5, 30, true, true) == 30);
0392         REQUIRE(timeline->requestItemResize(cid5, 10, false, true) == 10);
0393         REQUIRE(timeline->requestClipMove(cid5, tid2, 120));
0394         audio5 = timeline->getClipSplitPartner(cid5);
0395 
0396         state0b();
0397 
0398         // CID 1 length=10, pos=100, CID2 length=20, pos=130, CID5 length=20, pos=130
0399 
0400         // Create mix between cid1 and cid2
0401         REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 0);
0402         REQUIRE(timeline->mixClip(cid1));
0403         state1b();
0404         REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid2) == false);
0405         REQUIRE(timeline->getTrackById_const(tid3)->mixIsReversed(audio2) == false);
0406 
0407         // Create mix between cid2 and cid5
0408         REQUIRE(timeline->mixClip(cid2));
0409         REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid2) == false);
0410         REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid5) == true);
0411         REQUIRE(timeline->getTrackById_const(tid3)->mixIsReversed(audio2) == false);
0412         REQUIRE(timeline->getTrackById_const(tid3)->mixIsReversed(audio5) == true);
0413         // Undo cid5 mix
0414         undoStack->undo();
0415 
0416         state1b();
0417         // Undo cid2 mix
0418         undoStack->undo();
0419         // Undo cid5
0420         undoStack->undo();
0421         undoStack->undo();
0422         undoStack->undo();
0423         undoStack->undo();
0424 
0425         state0();
0426     }
0427 
0428     SECTION("Create mix on color clip and resize")
0429     {
0430         state0();
0431         // CID 3 length=20, pos=500, CID4 length=20, pos=520
0432         // Default mix duration = 25 frames (12 before / 13 after)
0433         REQUIRE(timeline->mixClip(cid3));
0434         state2();
0435         // Resize left clip, should resize the mix
0436         REQUIRE(timeline->requestItemResize(cid3, 24, true, true) == 24);
0437         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0438         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0439         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0440         undoStack->undo();
0441         state2();
0442         // Resize left clip outside mix zone, should delete the mix
0443         REQUIRE(timeline->requestItemResize(cid3, 4, true, true) == 20);
0444         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0445         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0446         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0447         undoStack->undo();
0448         state2();
0449         // Resize right clip, should resize the mix
0450         REQUIRE(timeline->requestItemResize(cid4, 16, false, true) == 16);
0451         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0452         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0453         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0454         undoStack->undo();
0455         state2();
0456         // Resize right clip outside mix zone, should delete the mix
0457         REQUIRE(timeline->requestItemResize(cid4, 4, false, true) == 20);
0458         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0459         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0460         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0461         undoStack->undo();
0462         state2();
0463         // Resize right clip before left clip, should limit the resize to left clip position
0464         REQUIRE(timeline->requestItemResize(cid4, 50, false, true) == 40);
0465         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0466         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0467         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0468         undoStack->undo();
0469         state2();
0470         // Resize left clip past right clip, should limit the resize to left clip position
0471         REQUIRE(timeline->requestItemResize(cid3, 100, true, true) == 40);
0472         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0473         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0474         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0475         undoStack->undo();
0476         state2();
0477 
0478         // Before mix: CID 3 length=20, pos=500, CID4 length=20, pos=520
0479         // Default mix duration = 25 frames (12 before / 13 after)
0480 
0481         // Resize left clip before right clip start, then right clip outside left clip, should delete the mix
0482         REQUIRE(timeline->requestItemResize(cid3, 20, true, true) == 20);
0483         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0484         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0485         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0486         REQUIRE(timeline->requestItemResize(cid4, 20, false, true) == 20);
0487         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0488         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0489         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0490         undoStack->undo();
0491         undoStack->undo();
0492         state2();
0493 
0494         // Resize right clip after left clip end, then left clip outside right clip, should delete the mix
0495         REQUIRE(timeline->requestItemResize(cid4, 20, false, true) == 20);
0496         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0497         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0498         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0499         REQUIRE(timeline->requestItemResize(cid3, 20, true, true) == 20);
0500         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0501         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0502         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0503         undoStack->undo();
0504         undoStack->undo();
0505         state2();
0506 
0507         undoStack->undo();
0508         state0();
0509     }
0510 
0511     SECTION("Create mix on AV clips and resize")
0512     {
0513         state0();
0514         // CID 1 length=10, pos=100, CID2 length=10, pos=110
0515         REQUIRE(timeline->m_allClips[cid1]->getPlaytime() == 10);
0516         REQUIRE(timeline->m_allClips[cid2]->getPlaytime() == 10);
0517         // Resize clip in to have some space for mix
0518         REQUIRE(timeline->requestItemResize(cid2, 90, true, true) == 90);
0519         REQUIRE(timeline->requestItemResize(cid2, 30, false, true) == 30);
0520         REQUIRE(timeline->requestClipMove(cid2, tid2, 130));
0521         REQUIRE(timeline->requestItemResize(cid1, 30, true, true) == 30);
0522 
0523         REQUIRE(timeline->mixClip(cid1));
0524         state3();
0525         // CID 1 length=30, pos=100, CID2 length=30, pos=130
0526         // Default mix duration = 25 frames (12 before / 13 after)
0527         // Resize left clip, should resize the mix
0528         REQUIRE(timeline->requestItemResize(cid1, 35, true, true) == 35);
0529         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0530         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
0531         REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
0532         REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 1);
0533         undoStack->undo();
0534         state3();
0535         // Resize left clip outside mix zone, should delete the mix
0536         REQUIRE(timeline->requestItemResize(cid1, 10, true, true) == 30);
0537         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0538         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 0);
0539         REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
0540         REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 0);
0541         undoStack->undo();
0542         state3();
0543         // Resize right clip, should resize the mix
0544         REQUIRE(timeline->requestItemResize(cid2, 25, false, true) == 25);
0545         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0546         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
0547         REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
0548         REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 1);
0549         undoStack->undo();
0550         state3();
0551         // Resize right clip outside mix zone, should delete the mix
0552         REQUIRE(timeline->requestItemResize(cid2, 4, false, true) == 30);
0553         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0554         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 0);
0555         REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
0556         REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 0);
0557         undoStack->undo();
0558         state3();
0559         // Resize right clip before left clip, should limit to left clip position
0560         REQUIRE(timeline->requestItemResize(cid2, 80, false, true) == 60);
0561         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0562         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
0563         REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
0564         REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 1);
0565         undoStack->undo();
0566         state3();
0567         // Resize left clip after right clip, should limit to right clip duration
0568         REQUIRE(timeline->requestItemResize(cid1, 80, true, true) == 60);
0569         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0570         REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
0571         REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
0572         REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 1);
0573         undoStack->undo();
0574         state3();
0575         undoStack->undo();
0576         undoStack->undo();
0577         undoStack->undo();
0578         undoStack->undo();
0579         undoStack->undo();
0580         state0();
0581     }
0582 
0583     SECTION("Test chained mixes on color clips")
0584     {
0585         // Add 2 more color clips
0586         cid5 = -1;
0587         int cid6;
0588         int cid7;
0589         state0();
0590         REQUIRE(timeline->requestClipInsertion(binId2, tid2, 540, cid5));
0591         REQUIRE(timeline->requestItemResize(cid5, 20, true, true));
0592         REQUIRE(timeline->requestClipInsertion(binId2, tid2, 560, cid6));
0593         REQUIRE(timeline->requestItemResize(cid6, 40, true, true));
0594         REQUIRE(timeline->requestClipInsertion(binId2, tid2, 600, cid7));
0595         REQUIRE(timeline->requestItemResize(cid7, 20, true, true));
0596         audio5 = timeline->getClipSplitPartner(cid5);
0597 
0598         // Cid3 pos=500, duration=20
0599         // Cid4 pos=520, duration=20
0600         // Cid5 pos=540, duration=20
0601         // Cid6 pos=560, duration=40
0602         // Cid7 pos=600, duration=20
0603 
0604         // Mix 3 and 4
0605         REQUIRE(timeline->mixClip(cid3));
0606         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0607         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0608         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0609         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0610         REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0611         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0612 
0613         // Mix 6 and 7
0614         REQUIRE(timeline->mixClip(cid6));
0615         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0616         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0617         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0618         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0619         REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 1);
0620         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 2);
0621 
0622         // Mix 5 and 6
0623         REQUIRE(timeline->mixClip(cid5));
0624         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0625         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0626         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0627         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 1);
0628         REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0629         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 3);
0630 
0631         // Undo mix 5 and 6
0632         undoStack->undo();
0633         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0634         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0635         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0636         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0637         REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 1);
0638         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 2);
0639 
0640         // Undo mix 6 and 7
0641         undoStack->undo();
0642         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0643         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0644         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0645         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0646         REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0647         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0648 
0649         // Undo mix 3 and 4
0650         undoStack->undo();
0651 
0652         // Undo insert/resize ops
0653         undoStack->undo();
0654         undoStack->undo();
0655         undoStack->undo();
0656         undoStack->undo();
0657         undoStack->undo();
0658         undoStack->undo();
0659 
0660         state0();
0661     }
0662 
0663     SECTION("Test chained mixes and check mix direction")
0664     {
0665         // Add 3 more color clips
0666         cid5 = -1;
0667         int cid6;
0668         int cid7;
0669         state0();
0670         REQUIRE(timeline->requestClipInsertion(binId2, tid2, 540, cid5));
0671         REQUIRE(timeline->requestItemResize(cid5, 20, true, true));
0672         REQUIRE(timeline->requestClipInsertion(binId2, tid2, 560, cid6));
0673         REQUIRE(timeline->requestItemResize(cid6, 40, true, true));
0674         REQUIRE(timeline->requestClipInsertion(binId2, tid2, 600, cid7));
0675         REQUIRE(timeline->requestItemResize(cid7, 20, true, true));
0676 
0677         // Cid3 pos=500, duration=20
0678         // Cid4 pos=520, duration=20
0679         // Cid5 pos=540, duration=20
0680         // Cid6 pos=560, duration=40
0681         // Cid7 pos=600, duration=20
0682 
0683         auto mix0 = [&]() {
0684             REQUIRE(timeline->getClipsCount() == 9);
0685             REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0686             REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0687             REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 1);
0688             REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0689             REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0690             REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0691             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid5) == false);
0692         };
0693 
0694         auto mix1 = [&]() {
0695             REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0696             REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0697             REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 1);
0698             REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0699             REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0700             REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 2);
0701             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid5) == false);
0702             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid6) == true);
0703         };
0704 
0705         auto mix2 = [&]() {
0706             REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0707             REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0708             REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 1);
0709             REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0710             REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 1);
0711             REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 3);
0712             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid5) == false);
0713             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid6) == true);
0714             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid7) == false);
0715         };
0716 
0717         auto mix3 = [&]() {
0718             REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0719             REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0720             REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0721             REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 1);
0722             REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0723             REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 4);
0724             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid4) == false);
0725             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid5) == true);
0726             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid6) == false);
0727             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid7) == true);
0728         };
0729 
0730         // Mix 4 and 5
0731         REQUIRE(timeline->mixClip(cid4));
0732         mix0();
0733 
0734         // Mix 5 and 6
0735         REQUIRE(timeline->mixClip(cid5));
0736         mix1();
0737 
0738         // Mix 6 and 7
0739         REQUIRE(timeline->mixClip(cid6));
0740         mix2();
0741 
0742         // Mix 3 and 4, this will revert all subsequent mixes
0743         REQUIRE(timeline->mixClip(cid3));
0744         mix3();
0745 
0746         // Undo mix 3 and 4
0747         undoStack->undo();
0748         mix2();
0749 
0750         // Now switch mixes to Slide type
0751         timeline->switchComposition(cid7, QString("slide"));
0752         timeline->switchComposition(cid6, QString("slide"));
0753         timeline->switchComposition(cid5, QString("slide"));
0754         mix2();
0755 
0756         // Mix 3 and 4, this will revert all subsequent mixes
0757         REQUIRE(timeline->mixClip(cid3));
0758         mix3();
0759 
0760         // Undo mix 3 and 4
0761         undoStack->undo();
0762         mix2();
0763 
0764         // Now switch mixes to Wipe type
0765         timeline->switchComposition(cid7, QString("wipe"));
0766         timeline->switchComposition(cid6, QString("wipe"));
0767         timeline->switchComposition(cid5, QString("wipe"));
0768         mix2();
0769 
0770         // Mix 3 and 4, this will revert all subsequent mixes
0771         REQUIRE(timeline->mixClip(cid3));
0772         mix3();
0773 
0774         // Undo mix 3 and 4
0775         undoStack->undo();
0776         mix2();
0777 
0778         // Undo Wipe mix switch on cid5
0779         undoStack->undo();
0780         // Undo mix switch on cid6
0781         undoStack->undo();
0782         // Undo mix switch on cid7
0783         undoStack->undo();
0784         mix2();
0785 
0786         // Undo Slide mix switch on cid5
0787         undoStack->undo();
0788         // Undo mix switch on cid6
0789         undoStack->undo();
0790         // Undo mix switch on cid7
0791         undoStack->undo();
0792         mix2();
0793 
0794         // Undo mix 6 and 7
0795         undoStack->undo();
0796         mix1();
0797         // Undo mix 5 and 6
0798         undoStack->undo();
0799         mix0();
0800         // Undo mix 4 and 5
0801         undoStack->undo();
0802 
0803         // Undo insert/resize ops
0804         undoStack->undo();
0805         undoStack->undo();
0806         undoStack->undo();
0807         undoStack->undo();
0808         undoStack->undo();
0809         undoStack->undo();
0810 
0811         state0();
0812     }
0813 
0814     SECTION("Test mixes track move and direction")
0815     {
0816         // Add 3 more av clips
0817         cid5 = -1;
0818         int cid6;
0819         int cid7;
0820         state0();
0821         REQUIRE(timeline->requestClipInsertion(binId, tid2, 540, cid5));
0822         REQUIRE(timeline->requestItemResize(cid5, 20, true, true));
0823         REQUIRE(timeline->requestClipInsertion(binId, tid2, 560, cid6));
0824         REQUIRE(timeline->requestItemResize(cid6, 40, true, true));
0825         REQUIRE(timeline->requestClipInsertion(binId, tid2, 600, cid7));
0826         REQUIRE(timeline->requestItemResize(cid7, 20, true, true));
0827         audio5 = timeline->getClipSplitPartner(cid5);
0828 
0829         // Cid3 pos=500, duration=20
0830         // Cid4 pos=520, duration=20
0831         // Cid5 pos=540, duration=20
0832         // Cid6 pos=560, duration=40
0833         // Cid7 pos=600, duration=20
0834 
0835         auto mix0 = [&]() {
0836             REQUIRE(timeline->getClipsCount() == 12);
0837             REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0838             REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0839             REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 1);
0840             REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0841             REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0842             REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0843             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid5) == false);
0844         };
0845 
0846         auto mix1 = [&]() {
0847             REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0848             REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0849             REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 1);
0850             REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0851             REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0852             REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 2);
0853             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid5) == false);
0854             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid6) == true);
0855         };
0856 
0857         auto mix2 = [&]() {
0858             REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0859             REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
0860             REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 1);
0861             REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0862             REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 1);
0863             REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 3);
0864             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid5) == false);
0865             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid6) == true);
0866             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid7) == false);
0867         };
0868 
0869         auto mix3 = [&]() {
0870             REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0871             REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0872             REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0873             REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 1);
0874             REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0875             REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 4);
0876             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid4) == false);
0877             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid5) == true);
0878             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid6) == false);
0879             REQUIRE(timeline->getTrackById_const(tid2)->mixIsReversed(cid7) == true);
0880         };
0881 
0882         auto mix3b = [&]() {
0883             REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0884             REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0885             REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0886             REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 1);
0887             REQUIRE(timeline->m_allClips[cid7]->getSubPlaylistIndex() == 0);
0888             REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 0);
0889             REQUIRE(timeline->getTrackById_const(tid4)->mixCount() == 4);
0890             REQUIRE(timeline->getTrackById_const(tid4)->mixIsReversed(cid4) == false);
0891             REQUIRE(timeline->getTrackById_const(tid4)->mixIsReversed(cid5) == true);
0892             REQUIRE(timeline->getTrackById_const(tid4)->mixIsReversed(cid6) == false);
0893             REQUIRE(timeline->getTrackById_const(tid4)->mixIsReversed(cid7) == true);
0894         };
0895 
0896         // Mix 4 and 5
0897         REQUIRE(timeline->mixClip(cid4));
0898         mix0();
0899 
0900         // Mix 5 and 6
0901         REQUIRE(timeline->mixClip(cid5));
0902         mix1();
0903 
0904         // Mix 6 and 7
0905         REQUIRE(timeline->mixClip(cid6));
0906         mix2();
0907 
0908         // Mix 3 and 4, this will revert all subsequent mixes
0909         REQUIRE(timeline->mixClip(cid3));
0910         mix3();
0911 
0912         // Move everything to another track
0913         auto g1 = std::unordered_set<int>({cid3, cid4, cid5, cid6, cid7});
0914         REQUIRE(timeline->requestClipsGroup(g1));
0915 
0916         REQUIRE(timeline->requestClipMove(cid3, tid4, 600));
0917         // Now clips 3, 4, 5, 6 and 7 will be on top video track. Check mixes have the correct direction
0918         mix3b();
0919         // Undo track move
0920         undoStack->undo();
0921         mix3();
0922         // Redo track move
0923         undoStack->redo();
0924         mix3b();
0925         undoStack->undo();
0926         undoStack->undo();
0927         undoStack->undo();
0928         undoStack->undo();
0929         undoStack->undo();
0930         undoStack->undo();
0931 
0932         // Undo insert/resize ops
0933         undoStack->undo();
0934         undoStack->undo();
0935         undoStack->undo();
0936         undoStack->undo();
0937         undoStack->undo();
0938         undoStack->undo();
0939 
0940         state0();
0941     }
0942     SECTION("Test chained mixes and cuts")
0943     {
0944         // Add 2 more color clips
0945         cid5 = -1;
0946         int cid6;
0947         state0();
0948         REQUIRE(timeline->requestItemResize(cid4, 80, true, true));
0949         REQUIRE(timeline->requestClipInsertion(binId2, tid2, 600, cid5));
0950         REQUIRE(timeline->requestItemResize(cid5, 80, true, true));
0951         REQUIRE(timeline->requestClipInsertion(binId2, tid2, 680, cid6));
0952         REQUIRE(timeline->requestItemResize(cid6, 80, true, true));
0953         audio5 = timeline->getClipSplitPartner(cid5);
0954 
0955         // Cid3 pos=500, duration=20
0956         // Cid4 pos=520, duration=80
0957         // Cid5 pos=600, duration=80
0958         // Cid6 pos=680, duration=80
0959 
0960         // Mix 3 and 4
0961         REQUIRE(timeline->mixClip(cid3));
0962         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0963         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0964         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0965         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0966         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
0967 
0968         // Mix 4 and 5
0969         REQUIRE(timeline->mixClip(cid4));
0970         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0971         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0972         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0973         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
0974         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 2);
0975 
0976         // Mix 5 and 6
0977         REQUIRE(timeline->mixClip(cid5));
0978         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0979         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
0980         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
0981         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 1);
0982         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 3);
0983 
0984         // Now try to cut mixes and check they are in the correct subplaylist
0985 
0986         // Cut a clip with mix start only
0987         REQUIRE(TimelineFunctions::requestClipCut(timeline, cid3, 505));
0988         // Get newly created cut clip
0989         int clone = timeline->getClipByPosition(tid2, 506, 0);
0990         // Ensure each clip is on the correct playlist
0991         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 1);
0992         REQUIRE(timeline->m_allClips[clone]->getSubPlaylistIndex() == 0);
0993         // Undo cid3 cut
0994         undoStack->undo();
0995         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
0996         undoStack->redo();
0997         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 1);
0998         undoStack->undo();
0999 
1000         // Cut a clip with mix at start and end
1001         REQUIRE(TimelineFunctions::requestClipCut(timeline, cid4, 540));
1002         // Get newly created cut clip
1003         clone = timeline->getClipByPosition(tid2, 540, 1);
1004         // Ensure each clip is on the correct playlist
1005         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
1006         REQUIRE(timeline->m_allClips[clone]->getSubPlaylistIndex() == 1);
1007         // Undo cid3 cut
1008         undoStack->undo();
1009         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
1010         undoStack->redo();
1011         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
1012         REQUIRE(timeline->m_allClips[clone]->getSubPlaylistIndex() == 1);
1013         undoStack->undo();
1014 
1015         // Cut a clip with mix at end
1016         REQUIRE(TimelineFunctions::requestClipCut(timeline, cid6, 710));
1017         // Get newly created cut clip
1018         clone = timeline->getClipByPosition(tid2, 710, 0);
1019         // Ensure each clip is on the correct playlist
1020         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
1021         REQUIRE(timeline->m_allClips[clone]->getSubPlaylistIndex() == 0);
1022         undoStack->undo();
1023         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
1024         undoStack->redo();
1025         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
1026         REQUIRE(timeline->m_allClips[clone]->getSubPlaylistIndex() == 0);
1027         undoStack->undo();
1028 
1029         // Undo mix 5 and 6
1030         undoStack->undo();
1031         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
1032         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
1033         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
1034         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
1035         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 2);
1036 
1037         // Undo mix 4 and 5
1038         undoStack->undo();
1039         REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
1040         REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
1041         REQUIRE(timeline->m_allClips[cid5]->getSubPlaylistIndex() == 0);
1042         REQUIRE(timeline->m_allClips[cid6]->getSubPlaylistIndex() == 0);
1043         REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
1044 
1045         // Undo mix 3 and 4
1046         undoStack->undo();
1047 
1048         // Undo insert/resize ops
1049         undoStack->undo();
1050         undoStack->undo();
1051         undoStack->undo();
1052         undoStack->undo();
1053         undoStack->undo();
1054         state0();
1055     }
1056     timeline.reset();
1057     pCore->projectManager()->closeCurrentDocument(false, false);
1058 }