1 /* 2 SPDX-FileCopyrightText: 2021 Jean-Baptiste Mardelle <jb@kdenlive.org> 3 4 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 5 */ 6 7 #ifndef TIMEREMAP_H 8 #define TIMEREMAP_H 9 10 #include "ui_timeremap_ui.h" 11 12 #include "definitions.h" 13 #include "timecode.h" 14 15 #include <QWidget> 16 #include <QTimer> 17 #include <QMutex> 18 19 #include "mlt++/Mlt.h" 20 21 class ProjectClip; 22 class TimecodeDisplay; 23 24 25 /** 26 * @class RemapView 27 * @brief A widget to view remap keyframes. 28 * @author Jean-Baptiste Mardelle 29 */ 30 31 class RemapView : public QWidget 32 { 33 Q_OBJECT 34 35 public: 36 friend class TimeRemap; 37 explicit RemapView(QWidget *parent = nullptr); 38 void setBinClipDuration(std::shared_ptr<ProjectClip> clip, int duration); 39 void setDuration(std::shared_ptr<Mlt::Producer> service, int duration, int sourceDuration = 0); 40 void loadKeyframes(const QString &mapData); 41 const QString getKeyframesData(QMap<int,int> keyframes = {}) const; 42 int position() const; 43 int remapDuration() const; 44 int remapMax() const; 45 bool movingKeyframe() const; 46 void refreshOnDurationChanged(int remapDuration); 47 /** @brief Returns true if timeline cursor is inside the remapped clip */ 48 bool isInRange() const; 49 QTimer timer; 50 51 protected: 52 void resizeEvent(QResizeEvent *event) override; 53 void paintEvent(QPaintEvent *event) override; 54 void mouseMoveEvent(QMouseEvent *event) override; 55 void mousePressEvent(QMouseEvent *event) override; 56 void mouseReleaseEvent(QMouseEvent *event) override; 57 void wheelEvent(QWheelEvent *event) override; 58 std::shared_ptr<Mlt::Link> m_remapLink; 59 /** @brief The position of the clip in timeline, used to seek to correct place */ 60 int m_startPos; 61 /** @brief The in frame of the clip in timeline, used to correctly offset keyframes */ 62 int m_inFrame; 63 int m_oldInFrame; 64 /** @brief the original in/out of the clip when opening the remap widget, used to snap to ends */ 65 std::pair<int,int> m_originalRange; 66 67 public slots: 68 void updateInPos(int pos); 69 void updateOutPos(int pos); 70 void slotSetPosition(int pos); 71 void slotSetBottomPosition(int pos); 72 void addKeyframe(); 73 void goNext(); 74 void goPrev(); 75 void updateBeforeSpeed(double speed); 76 void updateAfterSpeed(double speed); 77 void toggleMoveNext(bool moveNext); 78 void reloadProducer(); 79 void centerCurrentKeyframe(); 80 void centerCurrentTopKeyframe(); 81 82 private: 83 enum MOVEMODE {NoMove, TopMove, BottomMove, CursorMove, CursorMoveBottom}; 84 int m_duration; 85 int m_sourceDuration; 86 int m_lastMaxDuration; 87 int m_position; 88 /** @brief the maximum duration of the parent (bin) clip */ 89 int m_maxLength; 90 int m_bottomPosition; 91 double m_scale; 92 QColor m_colSelected; 93 QColor m_colKeyframe; 94 int m_zoomHeight; 95 int m_centerPos; 96 int m_lineHeight; 97 double m_zoomFactor; 98 double m_zoomStart; 99 /** @brief The zoom factor (start, end - between 0 and 1) */ 100 QPointF m_zoomHandle; 101 /** @brief the keyframes for the remap effect. first value is output, second is source time */ 102 QMap<int, int>m_keyframes; 103 QMap<int, int>m_keyframesOrigin; 104 std::shared_ptr<ProjectClip> m_clip; 105 std::shared_ptr<Mlt::Producer> m_service; 106 QPointF m_lastZoomHandle; 107 /** @brief Mouse is the zoom left handle */ 108 bool m_hoverZoomIn; 109 /** @brief Mouse is the zoom right handle */ 110 bool m_hoverZoomOut; 111 /** @brief Mouse is over the zoom bar */ 112 bool m_hoverZoom; 113 int m_bottomView; 114 std::pair<int, int> m_currentKeyframe; 115 std::pair<int,int> m_currentKeyframeOriginal; 116 MOVEMODE m_moveKeyframeMode; 117 double m_clickOffset; 118 int m_clickPoint; 119 bool m_moveNext; 120 int m_clickEnd; 121 int m_offset; 122 QMutex m_kfrMutex; 123 QMap <int,int>m_selectedKeyframes; 124 QMap<int,int>m_previousSelection; 125 std::pair<int,int> getClosestKeyframe(int pos, bool bottomKeyframe = false) const; 126 std::pair<double,double> getSpeed(std::pair<int,int>kf); 127 128 signals: 129 void seekToPos(int,int); 130 void selectedKf(std::pair<int,int>, std::pair<double,double>, std::pair<bool,bool>atEnd = {true,true}); 131 void updateSpeeds(std::pair<double,double>); 132 /** When the cursor position changes inform parent if we are on a keyframe or not. */ 133 void atKeyframe(bool isKeyframe, bool last); 134 void updateKeyframes(bool resize); 135 void updateKeyframesWithUndo(QMap<int,int>updatedKeyframes, QMap<int,int>previousKeyframes); 136 void updateMaxDuration(); 137 }; 138 139 /** 140 * @class TimeRemap 141 * @brief A dialog for editing time remap effect. 142 * @author Jean-Baptiste Mardelle 143 */ 144 class TimeRemap : public QWidget, public Ui::TimeRemap_UI 145 { 146 Q_OBJECT 147 148 public: 149 explicit TimeRemap(QWidget *parent = nullptr); 150 ~TimeRemap() override; 151 void selectedClip(int cid); 152 void setClip(std::shared_ptr<ProjectClip> clip, int in = -1, int out = -1); 153 /** @brief the bin id of the clip currently active in remap widget */ 154 const QString ¤tClip() const; 155 /** @brief Returns true if timeline cursor is inside the remapped clip */ 156 bool isInRange() const; 157 158 private slots: 159 void updateKeyframes(bool resize = true); 160 void updateKeyframesWithUndo(QMap<int,int>updatedKeyframes, QMap<int,int>previousKeyframes); 161 void checkClipUpdate(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int>& roles); 162 void switchRemapParam(); 163 164 private: 165 std::shared_ptr<Mlt::Link> m_splitRemap; 166 TimecodeDisplay *m_in; 167 TimecodeDisplay *m_out; 168 RemapView *m_view; 169 int m_lastLength; 170 int m_cid; 171 int m_splitId; 172 QString m_binId; 173 QMetaObject::Connection m_seekConnection1; 174 QMetaObject::Connection m_seekConnection2; 175 QMetaObject::Connection m_seekConnection3; 176 177 }; 178 179 #endif 180