File indexing completed on 2024-04-14 04:46:26

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