1 #include "test_utils.hpp"
2 
3 using namespace fakeit;
4 Mlt::Profile profile_timewarp;
5 
6 TEST_CASE("Test of timewarping", "[Timewarp]")
7 {
8     auto binModel = pCore->projectItemModel();
9     binModel->clean();
10     std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
11     std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack);
12 
13     // Here we do some trickery to enable testing.
14     // We mock the project class so that the undoStack function returns our undoStack
15 
16     Mock<ProjectManager> pmMock;
17     When(Method(pmMock, undoStack)).AlwaysReturn(undoStack);
18     When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)));
19 
20     ProjectManager &mocked = pmMock.get();
21     pCore->m_projectManager = &mocked;
22 
23     // We also mock timeline object to spy few functions and mock others
24     TimelineItemModel tim(&profile_timewarp, undoStack);
25     Mock<TimelineItemModel> timMock(tim);
__anon90cc78240102(...) 26     auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {});
27     TimelineItemModel::finishConstruct(timeline, guideModel);
28 
29     RESET(timMock);
30     TimelineModel::next_id = 0;
31     undoStack->undo();
32     undoStack->redo();
33     undoStack->redo();
34     undoStack->undo();
35 
36     QString binId = createProducer(profile_timewarp, "red", binModel);
37     QString binId2 = createProducer(profile_timewarp, "blue", binModel);
38     QString binId3 = createProducerWithSound(profile_timewarp, binModel);
39 
40     int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
41     int tid1 = TrackModel::construct(timeline);
42     int tid2 = TrackModel::construct(timeline);
43     Q_UNUSED(tid1);
44     Q_UNUSED(tid2);
45     int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly);
46     int cid3 = ClipModel::construct(timeline, binId3, -1, PlaylistState::VideoOnly);
47 
48     timeline->m_allClips[cid1]->m_endlessResize = false;
49     timeline->m_allClips[cid2]->m_endlessResize = false;
50     timeline->m_allClips[cid3]->m_endlessResize = false;
51 
52     SECTION("Timewarping orphan clip")
53     {
54         int originalDuration = timeline->getClipPlaytime(cid3);
55         REQUIRE(timeline->checkConsistency());
56         REQUIRE(timeline->getClipTrackId(cid3) == -1);
57         REQUIRE(timeline->getClipSpeed(cid3) == 1.);
58 
__anon90cc78240202() 59         std::function<bool(void)> undo = []() { return true; };
__anon90cc78240302() 60         std::function<bool(void)> redo = []() { return true; };
61 
62         REQUIRE(timeline->requestClipTimeWarp(cid3, 0.1, false, true, undo, redo));
63 
64         REQUIRE(timeline->getClipSpeed(cid3) == 0.1);
65         INFO(timeline->m_allClips[cid3]->getIn());
66         INFO(timeline->m_allClips[cid3]->getOut());
67         REQUIRE(timeline->getClipPlaytime(cid3) == originalDuration / 0.1);
68 
69         undo();
70 
71         REQUIRE(timeline->getClipSpeed(cid3) == 1.);
72         REQUIRE(timeline->getClipPlaytime(cid3) == originalDuration);
73 
74         redo();
75 
76         REQUIRE(timeline->getClipSpeed(cid3) == 0.1);
77         REQUIRE(timeline->getClipPlaytime(cid3) == originalDuration / 0.1);
78 
__anon90cc78240402() 79         std::function<bool(void)> undo2 = []() { return true; };
__anon90cc78240502() 80         std::function<bool(void)> redo2 = []() { return true; };
81         REQUIRE(timeline->requestClipTimeWarp(cid3, 1.2, false, true, undo2, redo2));
82 
83         REQUIRE(timeline->getClipSpeed(cid3) == 1.2);
84         REQUIRE(timeline->getClipPlaytime(cid3) == int(originalDuration / 1.2));
85 
86         undo2();
87         REQUIRE(timeline->getClipSpeed(cid3) == 0.1);
88         REQUIRE(timeline->getClipPlaytime(cid3) == originalDuration / 0.1);
89 
90         undo();
91         REQUIRE(timeline->getClipSpeed(cid3) == 1.);
92         REQUIRE(timeline->getClipPlaytime(cid3) == originalDuration);
93 
94         // Finally, we test that setting a very high speed isn't possible.
95         // Specifically, it must be impossible to make the clip shorter than one frame
96         int curLength = timeline->getClipPlaytime(cid3);
97 
98         // This is the limit, should work
99         REQUIRE(timeline->requestClipTimeWarp(cid3, double(curLength), false, true, undo2, redo2));
100 
101         REQUIRE(timeline->getClipSpeed(cid3) == double(curLength));
102         REQUIRE(timeline->getClipPlaytime(cid3) == 1);
103 
104         // This is the higher than the limit, should not work
105         // (we have some error margin in duration rounding, multiply by 10)
106         REQUIRE_FALSE(timeline->requestClipTimeWarp(cid3, double(curLength) * 10, false, true, undo2, redo2));
107     }
108     binModel->clean();
109     pCore->m_projectManager = nullptr;
110 }
111