File indexing completed on 2022-11-22 14:07:16

0001 /*
0002     SPDX-FileCopyrightText: 2021 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003 
0004 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #pragma once
0008 
0009 #include "ui_timeremap_ui.h"
0010 
0011 #include "definitions.h"
0012 #include "utils/timecode.h"
0013 
0014 #include <QWidget>
0015 #include <QTimer>
0016 #include <QMutex>
0017 
0018 #include "mlt++/Mlt.h"
0019 
0020 class ProjectClip;
0021 class TimecodeDisplay;
0022 
0023 
0024 /**
0025  * @class RemapView
0026  * @brief A widget to view remap keyframes.
0027  * @author Jean-Baptiste Mardelle
0028  */
0029 
0030 class RemapView : public QWidget
0031 {
0032     Q_OBJECT
0033 
0034 public:
0035     friend class TimeRemap;
0036     explicit RemapView(QWidget *parent = nullptr);
0037     void setBinClipDuration(std::shared_ptr<ProjectClip> clip, int duration);
0038     void setDuration(std::shared_ptr<Mlt::Producer> service, int duration, int sourceDuration = 0);
0039     void loadKeyframes(const QString &mapData);
0040     const QString getKeyframesData(QMap<int,int> keyframes = {}) const;
0041     int position() const;
0042     int remapDuration() const;
0043     int remapMax() const;
0044     bool movingKeyframe() const;
0045     void refreshOnDurationChanged(int remapDuration);
0046     /** @brief Returns true if timeline cursor is inside the remapped clip */
0047     bool isInRange() const;
0048     QTimer timer;
0049 
0050 protected:
0051     void resizeEvent(QResizeEvent *event) override;
0052     void paintEvent(QPaintEvent *event) override;
0053     void mouseMoveEvent(QMouseEvent *event) override;
0054     void mousePressEvent(QMouseEvent *event) override;
0055     void mouseReleaseEvent(QMouseEvent *event) override;
0056     void wheelEvent(QWheelEvent *event) override;
0057     std::shared_ptr<Mlt::Link> m_remapLink;
0058     /** @brief The position of the clip in timeline, used to seek to correct place */
0059     int m_startPos;
0060     /** @brief The in frame of the clip in timeline, used to correctly offset keyframes */
0061     int m_inFrame;
0062     int m_oldInFrame;
0063     /** @brief the original in/out of the clip when opening the remap widget, used to snap to ends */
0064     std::pair<int,int> m_originalRange;
0065 
0066 public slots:
0067     void updateInPos(int pos);
0068     void updateOutPos(int pos);
0069     void slotSetPosition(int pos);
0070     void slotSetBottomPosition(int pos);
0071     void addKeyframe();
0072     void goNext();
0073     void goPrev();
0074     void updateBeforeSpeed(double speed);
0075     void updateAfterSpeed(double speed);
0076     void toggleMoveNext(bool moveNext);
0077     void reloadProducer();
0078     void centerCurrentKeyframe();
0079     void centerCurrentTopKeyframe();
0080 
0081 private:
0082     enum MOVEMODE {NoMove, TopMove, BottomMove, CursorMove, CursorMoveBottom};
0083     int m_duration;
0084     int m_sourceDuration;
0085     int m_lastMaxDuration;
0086     int m_position;
0087     /** @brief the maximum duration of the parent (bin) clip */
0088     int m_maxLength;
0089     int m_bottomPosition;
0090     double m_scale;
0091     QColor m_colSelected;
0092     QColor m_colKeyframe;
0093     int m_zoomHeight;
0094     int m_centerPos;
0095     int m_lineHeight;
0096     double m_zoomFactor;
0097     double m_zoomStart;
0098     /** @brief The zoom factor (start, end - between 0 and 1) */
0099     QPointF m_zoomHandle;
0100     /** @brief the keyframes for the remap effect. first value is output, second is source time */
0101     QMap<int, int>m_keyframes;
0102     QMap<int, int>m_keyframesOrigin;
0103     std::shared_ptr<ProjectClip> m_clip;
0104     std::shared_ptr<Mlt::Producer> m_service;
0105     QPointF m_lastZoomHandle;
0106     /** @brief Mouse is the zoom left handle */
0107     bool m_hoverZoomIn;
0108     /** @brief Mouse is the zoom right handle */
0109     bool m_hoverZoomOut;
0110     /** @brief Mouse is over the zoom bar */
0111     bool m_hoverZoom;
0112     int m_bottomView;
0113     std::pair<int, int> m_currentKeyframe;
0114     std::pair<int,int> m_currentKeyframeOriginal;
0115     MOVEMODE m_moveKeyframeMode;
0116     double m_clickOffset;
0117     int m_clickPoint;
0118     bool m_moveNext;
0119     int m_clickEnd;
0120     int m_offset;
0121     QMutex m_kfrMutex;
0122     QMap <int,int>m_selectedKeyframes;
0123     QMap<int,int>m_previousSelection;
0124     std::pair<int,int> getClosestKeyframe(int pos, bool bottomKeyframe = false) const;
0125     std::pair<double,double> getSpeed(std::pair<int,int>kf);
0126 
0127 signals:
0128     void seekToPos(int,int);
0129     void selectedKf(std::pair<int,int>, std::pair<double,double>, std::pair<bool,bool>atEnd = {true,true});
0130     void updateSpeeds(std::pair<double,double>);
0131     /** When the cursor position changes inform parent if we are on a keyframe or not. */
0132     void atKeyframe(bool isKeyframe, bool last);
0133     void updateKeyframes(bool resize);
0134     void updateKeyframesWithUndo(QMap<int,int>updatedKeyframes, QMap<int,int>previousKeyframes);
0135     void updateMaxDuration();
0136 };
0137 
0138  /**
0139  * @class TimeRemap
0140  * @brief A dialog for editing time remap effect.
0141  * @author Jean-Baptiste Mardelle
0142  */
0143 class TimeRemap : public QWidget, public Ui::TimeRemap_UI
0144 {
0145     Q_OBJECT
0146 
0147 public:
0148     explicit TimeRemap(QWidget *parent = nullptr);
0149     ~TimeRemap() override;
0150     void selectedClip(int cid);
0151     void setClip(std::shared_ptr<ProjectClip> clip, int in = -1, int out = -1);
0152     /** @brief the bin id of the clip currently active in remap widget */
0153     const QString &currentClip() const;
0154     /** @brief Returns true if timeline cursor is inside the remapped clip */
0155     bool isInRange() const;
0156 
0157 private slots:
0158     void updateKeyframes();
0159     void updateKeyframesWithUndo(const QMap<int,int>&updatedKeyframes, const QMap<int,int>&previousKeyframes);
0160     void checkClipUpdate(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int>& roles);
0161     void switchRemapParam();
0162 
0163 private:
0164     std::shared_ptr<Mlt::Link> m_splitRemap;
0165     RemapView *m_view;
0166     int m_lastLength;
0167     int m_cid;
0168     int m_splitId;
0169     QString m_binId;
0170     QMetaObject::Connection m_seekConnection1;
0171     QMetaObject::Connection m_seekConnection2;
0172     QMetaObject::Connection m_seekConnection3;
0173 
0174 };