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

0001 /*
0002     SPDX-FileCopyrightText: 2023 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("Replace Clip", "[ReplaceClip]")
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 tracks
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 clips with audio
0047     QString binId = createProducerWithSound(pCore->getProjectProfile(), binModel, 100);
0048     QString binId2 = createProducerWithSound(pCore->getProjectProfile(), binModel, 100);
0049     QString binId3 = createProducerWithSound(pCore->getProjectProfile(), binModel, 15);
0050 
0051     // Setup insert stream data
0052     QMap<int, QString> audioInfo;
0053     audioInfo.insert(1, QStringLiteral("stream1"));
0054     timeline->m_binAudioTargets = audioInfo;
0055 
0056     int cid1;
0057     int cid2;
0058     int cid3;
0059     int audio1;
0060     int audio2;
0061     int audio3;
0062     // Create AV clip 1 at 100, duration 10 from first Bin clip
0063     REQUIRE(timeline->requestClipInsertion(binId, tid2, 100, cid1));
0064     REQUIRE(timeline->requestItemResize(cid1, 10, true, true));
0065     audio1 = timeline->getClipSplitPartner(cid1);
0066 
0067     // Create AV clip 2 at 110, duration 10 from second Bin clip
0068     REQUIRE(timeline->requestClipInsertion(binId2, tid2, 110, cid2));
0069     REQUIRE(timeline->requestItemResize(cid2, 10, true, true));
0070     REQUIRE(timeline->requestClipMove(cid2, tid2, 110));
0071     audio2 = timeline->getClipSplitPartner(cid2);
0072 
0073     // Create AV clip 3 at 200, duration 20 from first Bin clip
0074     REQUIRE(timeline->requestClipInsertion(binId, tid2, 200, cid3));
0075     REQUIRE(timeline->requestItemResize(cid3, 20, true, true));
0076     audio3 = timeline->getClipSplitPartner(cid3);
0077 
0078     auto state0 = [&]() {
0079         REQUIRE(timeline->getClipsCount() == 6);
0080         REQUIRE(timeline->getClipPlaytime(cid1) == 10);
0081         REQUIRE(timeline->getClipPosition(cid1) == 100);
0082         REQUIRE(timeline->getClipPlaytime(cid2) == 10);
0083         REQUIRE(timeline->getClipPosition(cid2) == 110);
0084         REQUIRE(timeline->getClipPosition(cid3) == 200);
0085         REQUIRE(timeline->getClipPlaytime(cid3) == 20);
0086         REQUIRE(timeline->getClipPlaytime(audio1) == 10);
0087         REQUIRE(timeline->getClipPosition(audio1) == 100);
0088         REQUIRE(timeline->getClipPlaytime(audio2) == 10);
0089         REQUIRE(timeline->getClipPosition(audio2) == 110);
0090         REQUIRE(timeline->getClipPosition(audio3) == 200);
0091         REQUIRE(timeline->getClipPlaytime(audio3) == 20);
0092         REQUIRE(timeline->m_allClips[cid1]->binId() == binId);
0093         REQUIRE(timeline->m_allClips[audio1]->binId() == binId);
0094         REQUIRE(timeline->m_allClips[cid2]->binId() == binId2);
0095         REQUIRE(timeline->m_allClips[audio2]->binId() == binId2);
0096         REQUIRE(timeline->m_allClips[cid3]->binId() == binId);
0097         REQUIRE(timeline->m_allClips[audio3]->binId() == binId);
0098     };
0099 
0100     auto state1 = [&]() {
0101         REQUIRE(timeline->getClipsCount() == 6);
0102         REQUIRE(timeline->getClipPlaytime(cid1) == 10);
0103         REQUIRE(timeline->getClipPosition(cid1) == 100);
0104         REQUIRE(timeline->getClipPlaytime(cid2) == 10);
0105         REQUIRE(timeline->getClipPosition(cid2) == 110);
0106         REQUIRE(timeline->getClipPosition(cid3) == 200);
0107         REQUIRE(timeline->getClipPlaytime(cid3) == 20);
0108         REQUIRE(timeline->getClipPlaytime(audio1) == 10);
0109         REQUIRE(timeline->getClipPosition(audio1) == 100);
0110         REQUIRE(timeline->getClipPlaytime(audio2) == 10);
0111         REQUIRE(timeline->getClipPosition(audio2) == 110);
0112         REQUIRE(timeline->getClipPosition(audio3) == 200);
0113         REQUIRE(timeline->getClipPlaytime(audio3) == 20);
0114         REQUIRE(timeline->m_allClips[cid1]->binId() == binId);
0115         REQUIRE(timeline->m_allClips[audio1]->binId() == binId2);
0116         REQUIRE(timeline->m_allClips[cid2]->binId() == binId2);
0117         REQUIRE(timeline->m_allClips[audio2]->binId() == binId2);
0118         REQUIRE(timeline->m_allClips[cid3]->binId() == binId);
0119         REQUIRE(timeline->m_allClips[audio3]->binId() == binId2);
0120     };
0121 
0122     auto state2 = [&]() {
0123         REQUIRE(timeline->getClipsCount() == 6);
0124         REQUIRE(timeline->getClipPlaytime(cid1) == 10);
0125         REQUIRE(timeline->getClipPosition(cid1) == 100);
0126         REQUIRE(timeline->getClipPlaytime(cid2) == 10);
0127         REQUIRE(timeline->getClipPosition(cid2) == 110);
0128         REQUIRE(timeline->getClipPosition(cid3) == 200);
0129         REQUIRE(timeline->getClipPlaytime(cid3) == 20);
0130         REQUIRE(timeline->getClipPlaytime(audio1) == 10);
0131         REQUIRE(timeline->getClipPosition(audio1) == 100);
0132         REQUIRE(timeline->getClipPlaytime(audio2) == 10);
0133         REQUIRE(timeline->getClipPosition(audio2) == 110);
0134         REQUIRE(timeline->getClipPosition(audio3) == 200);
0135         REQUIRE(timeline->getClipPlaytime(audio3) == 20);
0136         REQUIRE(timeline->m_allClips[cid1]->binId() == binId2);
0137         REQUIRE(timeline->m_allClips[audio1]->binId() == binId);
0138         REQUIRE(timeline->m_allClips[cid2]->binId() == binId2);
0139         REQUIRE(timeline->m_allClips[audio2]->binId() == binId2);
0140         REQUIRE(timeline->m_allClips[cid3]->binId() == binId2);
0141         REQUIRE(timeline->m_allClips[audio3]->binId() == binId);
0142     };
0143 
0144     auto state3 = [&]() {
0145         REQUIRE(timeline->getClipsCount() == 6);
0146         REQUIRE(timeline->getClipPlaytime(cid1) == 10);
0147         REQUIRE(timeline->getClipPosition(cid1) == 100);
0148         REQUIRE(timeline->getClipPlaytime(cid2) == 10);
0149         REQUIRE(timeline->getClipPosition(cid2) == 110);
0150         REQUIRE(timeline->getClipPosition(cid3) == 200);
0151         REQUIRE(timeline->getClipPlaytime(cid3) == 20);
0152         REQUIRE(timeline->getClipPlaytime(audio1) == 10);
0153         REQUIRE(timeline->getClipPosition(audio1) == 100);
0154         REQUIRE(timeline->getClipPlaytime(audio2) == 10);
0155         REQUIRE(timeline->getClipPosition(audio2) == 110);
0156         REQUIRE(timeline->getClipPosition(audio3) == 200);
0157         REQUIRE(timeline->getClipPlaytime(audio3) == 20);
0158         REQUIRE(timeline->m_allClips[cid1]->binId() == binId2);
0159         REQUIRE(timeline->m_allClips[audio1]->binId() == binId2);
0160         REQUIRE(timeline->m_allClips[cid2]->binId() == binId2);
0161         REQUIRE(timeline->m_allClips[audio2]->binId() == binId2);
0162         REQUIRE(timeline->m_allClips[cid3]->binId() == binId2);
0163         REQUIRE(timeline->m_allClips[audio3]->binId() == binId2);
0164     };
0165     auto state4 = [&]() {
0166         REQUIRE(timeline->getClipsCount() == 6);
0167         REQUIRE(timeline->getClipPlaytime(cid1) == 10);
0168         REQUIRE(timeline->getClipPosition(cid1) == 100);
0169         REQUIRE(timeline->getClipPlaytime(cid2) == 10);
0170         REQUIRE(timeline->getClipPosition(cid2) == 110);
0171         REQUIRE(timeline->getClipPosition(cid3) == 200);
0172         REQUIRE(timeline->getClipPlaytime(cid3) == 20);
0173         REQUIRE(timeline->getClipPlaytime(audio1) == 10);
0174         REQUIRE(timeline->getClipPosition(audio1) == 100);
0175         REQUIRE(timeline->getClipPlaytime(audio2) == 10);
0176         REQUIRE(timeline->getClipPosition(audio2) == 110);
0177         REQUIRE(timeline->getClipPosition(audio3) == 200);
0178         REQUIRE(timeline->getClipPlaytime(audio3) == 20);
0179         REQUIRE(timeline->m_allClips[cid1]->binId() == binId);
0180         REQUIRE(timeline->m_allClips[audio1]->binId() == binId3);
0181         REQUIRE(timeline->m_allClips[cid2]->binId() == binId2);
0182         REQUIRE(timeline->m_allClips[audio2]->binId() == binId2);
0183         REQUIRE(timeline->m_allClips[cid3]->binId() == binId);
0184         REQUIRE(timeline->m_allClips[audio3]->binId() == binId);
0185     };
0186 
0187     SECTION("Replace audio from Bin Clip 1 with Bin Clip 2")
0188     {
0189         state0();
0190         pCore->projectManager()->replaceTimelineInstances(binId, binId2, true, false);
0191         state1();
0192         undoStack->undo();
0193         state0();
0194         undoStack->redo();
0195         state1();
0196         undoStack->undo();
0197         state0();
0198     }
0199     SECTION("Replace video from Bin Clip 1 with Bin Clip 2")
0200     {
0201         state0();
0202         pCore->projectManager()->replaceTimelineInstances(binId, binId2, false, true);
0203         state2();
0204         undoStack->undo();
0205         state0();
0206         undoStack->redo();
0207         state2();
0208         undoStack->undo();
0209         state0();
0210     }
0211     SECTION("Replace video and audio from Bin Clip 1 with Bin Clip 2")
0212     {
0213         state0();
0214         pCore->projectManager()->replaceTimelineInstances(binId, binId2, true, true);
0215         state3();
0216         undoStack->undo();
0217         state0();
0218         undoStack->redo();
0219         state3();
0220         undoStack->undo();
0221         state0();
0222     }
0223 
0224     SECTION("Replace audio from Bin Clip 1 with shorter Bin Clip 3")
0225     {
0226         state0();
0227         pCore->projectManager()->replaceTimelineInstances(binId, binId3, true, false);
0228         state4();
0229         undoStack->undo();
0230         state0();
0231         undoStack->redo();
0232         state4();
0233         undoStack->undo();
0234         state0();
0235     }
0236     timeline.reset();
0237     pCore->projectManager()->closeCurrentDocument(false, false);
0238 }