File indexing completed on 2024-05-05 09:05:27
0001 /* 0002 SPDX-FileCopyrightText: 2007 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 "abstractmonitor.h" 0010 #include "bin/model/markerlistmodel.hpp" 0011 #include "definitions.h" 0012 #include "utils/gentime.h" 0013 #include "scopes/sharedframe.h" 0014 #include "widgets/timecodedisplay.h" 0015 0016 #include <QTimer> 0017 #include <QToolBar> 0018 #include <QWidgetAction> 0019 0020 #include <memory> 0021 #include <unordered_set> 0022 0023 class SnapModel; 0024 class ProjectClip; 0025 class MonitorManager; 0026 class QSlider; 0027 class QToolButton; 0028 class KActionMenu; 0029 class KDualAction; 0030 class KSelectAction; 0031 class KMessageWidget; 0032 class QScrollBar; 0033 class RecManager; 0034 class QmlManager; 0035 class QLabel; 0036 class VideoWidget; 0037 class MonitorAudioLevel; 0038 class MonitorProxy; 0039 class MarkerSortModel; 0040 0041 namespace Mlt { 0042 class Profile; 0043 class Filter; 0044 } // namespace Mlt 0045 0046 class VolumeAction : public QWidgetAction 0047 { 0048 Q_OBJECT 0049 public: 0050 explicit VolumeAction(QObject *parent); 0051 QWidget *createWidget(QWidget *parent) override; 0052 0053 Q_SIGNALS: 0054 void volumeChanged(int volume); 0055 }; 0056 0057 0058 class Monitor : public AbstractMonitor 0059 { 0060 Q_OBJECT 0061 0062 public: 0063 friend class MonitorManager; 0064 0065 Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *parent = nullptr); 0066 ~Monitor() override; 0067 bool locked{false}; 0068 void resetProfile(); 0069 /** @brief Rebuild consumers after a property change */ 0070 void resetConsumer(bool fullReset); 0071 void setupMenu(QMenu *goMenu, QMenu *overlayMenu, QAction *playZone, QAction *loopZone, QMenu *markerMenu = nullptr, QAction *loopClip = nullptr); 0072 const QString activeClipId(); 0073 int position(); 0074 void updateTimecodeFormat(); 0075 void updateMarkers(); 0076 /** @brief Controller for the clip currently displayed (only valid for clip monitor). */ 0077 std::shared_ptr<ProjectClip> currentController() const; 0078 void reloadProducer(const QString &id); 0079 /** @brief Reimplemented from QWidget, updates the palette colors. */ 0080 void setPalette(const QPalette &p); 0081 /** @brief Returns current project's fps. */ 0082 double fps() const; 0083 /** @brief Get url for the clip's thumbnail */ 0084 QString getMarkerThumb(GenTime pos); 0085 int getZoneStart(); 0086 int getZoneEnd(); 0087 /** @brief Get the in and out points selected in the clip monitor. 0088 * @return a QPoint where x() is the in point, and y() is the out point + 1. 0089 * E.g. if the user sets in=100, out=101, then this returns <100, 102>. 0090 */ 0091 QPoint getZoneInfo() const; 0092 void setUpEffectGeometry(const QRect &r, const QVariantList &list = QVariantList(), const QVariantList &types = QVariantList()); 0093 /** @brief Set a property on the effect scene */ 0094 void setEffectSceneProperty(const QString &name, const QVariant &value); 0095 /** @brief Returns effective display size */ 0096 QSize profileSize() const; 0097 QRect effectRect() const; 0098 QVariantList effectPolygon() const; 0099 QVariantList effectRoto() const; 0100 void setEffectKeyframe(bool enable); 0101 void sendFrameForAnalysis(bool analyse); 0102 void updateAudioForAnalysis(); 0103 void switchMonitorInfo(int code); 0104 void restart(); 0105 void mute(bool) override; 0106 /** @brief Returns the action displaying record toolbar */ 0107 QAction *recAction(); 0108 void refreshIcons(); 0109 /** @brief Send audio thumb data to qml for on monitor display */ 0110 void prepareAudioThumb(); 0111 void connectAudioSpectrum(bool activate); 0112 /** @brief Set a property on the Qml scene **/ 0113 void setQmlProperty(const QString &name, const QVariant &value); 0114 void displayAudioMonitor(bool isActive); 0115 /** @brief Set the guides list model to currently active item (bin clip or timeline) **/ 0116 void updateGuidesList(); 0117 /** @brief Prepare split effect from timeline clip producer **/ 0118 void activateSplit(); 0119 /** @brief Clear monitor display **/ 0120 void clearDisplay(); 0121 void setProducer(std::shared_ptr<Mlt::Producer> producer, int pos = -1); 0122 void reconfigure(); 0123 /** @brief Saves current monitor frame to an image file, and add it to project if addToProject is set to true **/ 0124 void slotExtractCurrentFrame(QString frameName = QString(), bool addToProject = false); 0125 /** @brief Zoom in active monitor */ 0126 void slotZoomIn(); 0127 /** @brief Zoom out active monitor */ 0128 void slotZoomOut(); 0129 /** @brief Set a property on the MLT consumer */ 0130 void setConsumerProperty(const QString &name, const QString &value); 0131 /** @brief Play or Loop zone sets a fake "out" on the producer. It is necessary to reset this before reloading the producer */ 0132 void resetPlayOrLoopZone(const QString &binId); 0133 /** @brief Returns a pointer to monitor proxy, allowing to manage seek and consumer position */ 0134 MonitorProxy *getControllerProxy(); 0135 /** @brief Update active track in multitrack view */ 0136 void updateMultiTrackView(int tid); 0137 /** @brief Returns true if monitor is currently fullscreen */ 0138 bool monitorIsFullScreen() const; 0139 void reloadActiveStream(); 0140 /** @brief Trigger a refresh of audio thumbs colors */ 0141 void refreshAudioThumbs(); 0142 /** @brief Trigger a refresh of audio thumbs on notrmalization change */ 0143 void normalizeAudioThumbs(); 0144 /** @brief Returns true if monitor is playing */ 0145 bool isPlaying() const; 0146 /** @brief Enables / disables effect scene*/ 0147 void enableEffectScene(bool enable); 0148 /** @brief Update the document's uuid - used for qml thumb cache*/ 0149 void updateDocumentUuid(); 0150 /** @brief Focus the timecode to allow editing*/ 0151 void focusTimecode(); 0152 /** @brief Ensure the video widget has focus to make keyboard shortcuts work */ 0153 void fixFocus(); 0154 /** @brief Show a rec countdown over the monitor **/ 0155 void startCountDown(); 0156 void stopCountDown(); 0157 /** @brief Reset monitor scene to default **/ 0158 void resetScene(); 0159 /** @brief Set monitor zone **/ 0160 void loadZone(int in, int out); 0161 /** @brief Extract current frame to image file with path **/ 0162 void extractFrame(const QString &path); 0163 /** @brief Returns some infos about the GPU */ 0164 const QStringList getGPUInfo(); 0165 0166 protected: 0167 void mousePressEvent(QMouseEvent *event) override; 0168 void mouseReleaseEvent(QMouseEvent *event) override; 0169 void mouseDoubleClickEvent(QMouseEvent *event) override; 0170 void resizeEvent(QResizeEvent *event) override; 0171 void keyPressEvent(QKeyEvent *event) override; 0172 0173 /** @brief Move to another position on mouse wheel event. 0174 * 0175 * Moves towards the end of the clip/timeline on mouse wheel down/back, the 0176 * opposite on mouse wheel up/forward. 0177 * Ctrl + wheel moves by a second, without Ctrl it moves by a single frame. */ 0178 void wheelEvent(QWheelEvent *event) override; 0179 void updateBgColor(); 0180 0181 private: 0182 std::shared_ptr<ProjectClip> m_controller; 0183 /** @brief The QQuickView that handles our monitor display (video and qml overlay) **/ 0184 VideoWidget *m_glMonitor; 0185 /** @brief Container for our QQuickView monitor display (QQuickView needs to be embedded) **/ 0186 QWidget *m_glWidget; 0187 /** @brief Scrollbar for our monitor view, used when zooming the monitor **/ 0188 QScrollBar *m_verticalScroll; 0189 /** @brief Scrollbar for our monitor view, used when zooming the monitor **/ 0190 QScrollBar *m_horizontalScroll; 0191 /** @brief Manager for qml overlay for the QQuickView **/ 0192 QmlManager *m_qmlManager; 0193 std::shared_ptr<SnapModel> m_snaps; 0194 0195 std::shared_ptr<Mlt::Filter> m_splitEffect; 0196 std::shared_ptr<Mlt::Producer> m_splitProducer; 0197 std::shared_ptr<MarkerListModel> m_markerModel{nullptr}; 0198 int m_length; 0199 bool m_dragStarted; 0200 RecManager *m_recManager; 0201 /** @brief The widget showing current time position **/ 0202 TimecodeDisplay *m_timePos; 0203 KDualAction *m_playAction; 0204 KSelectAction *m_forceSize; 0205 KSelectAction *m_background; 0206 /** Has to be available so we can enable and disable it. */ 0207 QAction *m_loopClipAction; 0208 QAction *m_zoomVisibilityAction; 0209 KActionMenu *m_configMenuAction; 0210 QMenu *m_contextMenu; 0211 QMenu *m_playMenu; 0212 KActionMenu *m_markerMenu; 0213 QMenu *m_audioChannels; 0214 QToolButton *m_streamsButton; 0215 QAction *m_streamAction; 0216 QPoint m_DragStartPosition; 0217 /** true if selected clip is transition, false = selected clip is clip. 0218 * Necessary because sometimes we get two signals, e.g. we get a clip and we get selected transition = nullptr. */ 0219 bool m_loopClipTransition; 0220 GenTime getSnapForPos(bool previous); 0221 QToolBar *m_toolbar; 0222 QToolBar *m_trimmingbar; 0223 QAction *m_oneLess; 0224 QAction *m_oneMore; 0225 QAction *m_fiveLess; 0226 QAction *m_fiveMore; 0227 QLabel *m_trimmingOffset; 0228 QAction *m_editMarker; 0229 KMessageWidget *m_infoMessage; 0230 int m_forceSizeFactor; 0231 MonitorSceneType m_lastMonitorSceneType; 0232 bool m_displayingCountdown; 0233 MonitorAudioLevel *m_audioMeterWidget; 0234 QTimer m_droppedTimer; 0235 double m_displayedFps; 0236 int m_speedIndex; 0237 QMetaObject::Connection m_switchConnection; 0238 QMetaObject::Connection m_captureConnection; 0239 0240 void adjustScrollBars(float horizontal, float vertical); 0241 void loadQmlScene(MonitorSceneType type, const QVariant &sceneData = QVariant()); 0242 void updateQmlDisplay(int currentOverlay); 0243 /** @brief Create temporary Mlt::Tractor holding a clip and it's effectless clone */ 0244 void buildSplitEffect(Mlt::Producer *original); 0245 /** @brief Returns true if monitor is currently visible (not in a tab or hidden)*/ 0246 bool monitorVisible() const; 0247 /** To easily get them when creating the right click menu */ 0248 QAction *m_markIn; 0249 QAction *m_markOut; 0250 0251 private Q_SLOTS: 0252 void slotSetThumbFrame(); 0253 void slotSeek(); 0254 void updateClipZone(const QPoint zone); 0255 void slotGoToMarker(QAction *action); 0256 void slotSetVolume(int volume); 0257 void slotEditMarker(); 0258 void slotExtractCurrentZone(); 0259 void onFrameDisplayed(const SharedFrame &frame); 0260 void slotStartDrag(); 0261 void setZoom(float zoomRatio); 0262 void slotAdjustEffectCompare(); 0263 void slotShowMenu(const QPoint pos); 0264 void slotForceSize(QAction *a); 0265 void buildBackgroundedProducer(int pos); 0266 void slotSeekToKeyFrame(); 0267 void slotLockMonitor(bool lock); 0268 void slotSwitchPlay(); 0269 void slotEditInlineMarker(); 0270 /** @brief Pass keypress event to mainwindow */ 0271 void doKeyPressEvent(QKeyEvent *); 0272 /** @brief There was an error initializing Movit */ 0273 void gpuError(); 0274 void setOffsetX(int x); 0275 void setOffsetY(int y); 0276 /** @brief Pan monitor view */ 0277 void panView(QPoint diff); 0278 void slotSeekPosition(int); 0279 void addSnapPoint(int pos); 0280 void removeSnapPoint(int pos); 0281 /** @brief Process seek and optionally pause monitor */ 0282 void processSeek(int pos, bool noAudioScrub = false); 0283 /** @brief Check and display dropped frames */ 0284 void checkDrops(); 0285 /** @brief En/Disable the show record timecode feature in clip monitor */ 0286 void slotSwitchRecTimecode(bool enable); 0287 0288 public Q_SLOTS: 0289 void slotSetScreen(int screenIndex); 0290 void slotPreviewResource(const QString &path, const QString &title); 0291 // void slotSetClipProducer(DocClipBase *clip, QPoint zone = QPoint(), bool forceUpdate = false, int position = -1); 0292 void updateClipProducer(const std::shared_ptr<Mlt::Producer> &prod); 0293 void updateClipProducer(const QString &playlist); 0294 void slotOpenClip(const std::shared_ptr<ProjectClip> &controller, int in = -1, int out = -1); 0295 void slotRefreshMonitor(bool visible); 0296 void slotSeek(int pos); 0297 void stop() override; 0298 void start() override; 0299 void switchPlay(bool play); 0300 void updatePlayAction(bool play); 0301 void slotPlay() override; 0302 void pause(); 0303 void slotPlayZone(); 0304 void slotLoopZone(); 0305 /** @brief Loops the selected item (clip or transition). */ 0306 void slotLoopClip(QPoint inOut); 0307 void slotForward(double speed = 0, bool allowNormalPlay = false) override; 0308 void slotRewind(double speed = 0) override; 0309 void slotRewindOneFrame(int diff = 1); 0310 void slotForwardOneFrame(int diff = 1); 0311 /** @brief Display a non blocking error message to user **/ 0312 void warningMessage(const QString &text, int timeout = 5000, const QList<QAction *> &actions = QList<QAction *>()); 0313 void slotStart(); 0314 /** @brief Set position and information for the trimming preview 0315 * @param pos Absolute position in frames 0316 * @param offset Difference in frames beetween @p pos and the current position (to be displayed in the monitor toolbar) 0317 * @param frames1 Position in frames to be displayed in the monitor overlay for preview tile one 0318 * @param frames2 Position in frames to be displayed in the monitor overlay for preview tile two 0319 */ 0320 void slotTrimmingPos(int pos, int offset, int frames1, int frames2); 0321 /** @brief Move the position for the trimming preview by the given offset 0322 * @param offset How many frames the position should be moved 0323 * @see slotTrimmingPos 0324 */ 0325 void slotTrimmingPos(int offset); 0326 void slotEnd(); 0327 void slotSetZoneStart(); 0328 void slotSetZoneEnd(); 0329 void slotZoneStart(); 0330 void slotZoneEnd(); 0331 void slotLoadClipZone(const QPoint &zone); 0332 void slotSeekToNextSnap(); 0333 void slotSeekToPreviousSnap(); 0334 void adjustRulerSize(int length, const std::shared_ptr<MarkerSortModel> &markerModel = nullptr); 0335 void setTimePos(const QString &pos); 0336 /** @brief Display the on monitor effect scene (to adjust geometry over monitor). */ 0337 void slotShowEffectScene(MonitorSceneType sceneType, bool temporary = false, const QVariant &sceneData = QVariant()); 0338 bool effectSceneDisplayed(MonitorSceneType effectType); 0339 /** @brief split screen to compare clip with and without effect */ 0340 void slotSwitchCompare(bool enable); 0341 void slotMouseSeek(int eventDelta, uint modifiers) override; 0342 void slotSwitchFullScreen(bool minimizeOnly = false) override; 0343 /** @brief Display or hide the record toolbar */ 0344 void slotSwitchRec(bool enable); 0345 /** @brief Display or hide the trimming toolbar and monitor scene*/ 0346 void slotSwitchTrimming(bool enable); 0347 /** @brief Request QImage of current frame */ 0348 void slotGetCurrentImage(bool request); 0349 /** @brief Enable/disable display of monitor's audio levels widget */ 0350 void slotSwitchAudioMonitor(); 0351 /** @brief Request seeking */ 0352 void requestSeek(int pos); 0353 /** @brief Request seeking only if monitor is visible*/ 0354 void requestSeekIfVisible(int pos); 0355 /** @brief Check current position to show relevant infos in qml view (markers, zone in/out, etc). */ 0356 void checkOverlay(int pos = -1); 0357 void refreshMonitorIfActive(bool directUpdate = false) override; 0358 void refreshMonitor(bool directUpdate = false); 0359 void forceMonitorRefresh(); 0360 /** @brief Clear read ahead cache, to ensure up to date audio */ 0361 void purgeCache(); 0362 0363 Q_SIGNALS: 0364 void screenChanged(int screenIndex); 0365 void seekPosition(int pos); 0366 void seekRemap(int pos); 0367 void updateScene(); 0368 void durationChanged(int); 0369 void refreshClipThumbnail(const QString &); 0370 void zoneUpdated(const QPoint &); 0371 void zoneUpdatedWithUndo(const QPoint &, const QPoint &); 0372 /** @brief Editing transitions / effects over the monitor requires the renderer to send frames as QImage. 0373 * This causes a major slowdown, so we only enable it if required */ 0374 void requestFrameForAnalysis(bool); 0375 void effectChanged(const QRect &); 0376 void effectPointsChanged(const QVariantList &); 0377 void addRemoveKeyframe(); 0378 void seekToNextKeyframe(); 0379 void seekToPreviousKeyframe(); 0380 void seekToKeyframe(int); 0381 void addClipToProject(const QUrl &); 0382 /** @brief Request display of current bin clip. */ 0383 void refreshCurrentClip(); 0384 void addTimelineEffect(const QStringList &); 0385 void passKeyPress(QKeyEvent *); 0386 /** @brief Enable / disable project monitor multitrack view (split view with one track in each quarter). */ 0387 void multitrackView(bool, bool); 0388 void timeCodeUpdated(const QString &); 0389 void addMarker(); 0390 void deleteMarker(bool deleteGuide = true); 0391 void seekToPreviousSnap(); 0392 void seekToNextSnap(); 0393 void createSplitOverlay(std::shared_ptr<Mlt::Filter>); 0394 void removeSplitOverlay(); 0395 void activateTrack(int, bool notesMode = false); 0396 void autoKeyframeChanged(); 0397 void zoneDurationChanged(int duration); 0398 };