diff --git a/src/monitor/monitorproxy.cpp b/src/monitor/monitorproxy.cpp index a0a188758..64e2ff000 100644 --- a/src/monitor/monitorproxy.cpp +++ b/src/monitor/monitorproxy.cpp @@ -1,254 +1,262 @@ /*************************************************************************** * Copyright (C) 2018 by Jean-Baptiste Mardelle (jb@kdenlive.org) * * This file is part of Kdenlive. See www.kdenlive.org. * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "monitorproxy.h" +#include "core.h" +#include "monitormanager.h" #include "glwidget.h" #include "kdenlivesettings.h" #include "definitions.h" #include "doc/kthumb.h" #include #include #include #include MonitorProxy::MonitorProxy(GLWidget *parent) : QObject(parent) , q(parent) , m_position(0) , m_seekPosition(-1) , m_zoneIn(0) , m_zoneOut(-1) { } int MonitorProxy::seekPosition() const { return m_seekPosition; } int MonitorProxy::position() const { return m_position; } int MonitorProxy::rulerHeight() const { return q->m_rulerHeight; } int MonitorProxy::overlayType() const { return (q->m_id == (int)Kdenlive::ClipMonitor ? KdenliveSettings::clipMonitorOverlayGuides() : KdenliveSettings::projectMonitorOverlayGuides()); } void MonitorProxy::setOverlayType(int ix) { if (q->m_id == (int)Kdenlive::ClipMonitor) { KdenliveSettings::setClipMonitorOverlayGuides(ix); } else { KdenliveSettings::setProjectMonitorOverlayGuides(ix); } } QString MonitorProxy::markerComment() const { return m_markerComment; } void MonitorProxy::requestSeekPosition(int pos) { q->activateMonitor(); m_seekPosition = pos; emit seekPositionChanged(); emit seekRequestChanged(); } void MonitorProxy::setPosition(int pos) { m_position = pos; emit positionChanged(); } void MonitorProxy::setMarkerComment(const QString &comment) { if (m_markerComment == comment) { return; } m_markerComment = comment; emit markerCommentChanged(); } void MonitorProxy::setSeekPosition(int pos) { m_seekPosition = pos; emit seekPositionChanged(); } void MonitorProxy::pauseAndSeek(int pos) { q->switchPlay(false); requestSeekPosition(pos); } int MonitorProxy::zoneIn() const { return m_zoneIn; } int MonitorProxy::zoneOut() const { return m_zoneOut; } void MonitorProxy::setZoneIn(int pos) { if (m_zoneIn > 0) { emit removeSnap(m_zoneIn); } m_zoneIn = pos; if (pos > 0) { emit addSnap(pos); } emit zoneChanged(); } void MonitorProxy::setZoneOut(int pos) { if (m_zoneOut > 0) { emit removeSnap(m_zoneOut); } m_zoneOut = pos; if (pos > 0) { emit addSnap(pos); } emit zoneChanged(); } void MonitorProxy::setZone(int in, int out) { if (m_zoneIn > 0) { emit removeSnap(m_zoneIn); } if (m_zoneOut > 0) { emit removeSnap(m_zoneOut); } m_zoneIn = in; m_zoneOut = out; if (m_zoneIn > 0) { emit addSnap(m_zoneIn); } if (m_zoneOut > 0) { emit addSnap(m_zoneOut); } emit zoneChanged(); } void MonitorProxy::setZone(QPoint zone) { setZone(zone.x(), zone.y()); } void MonitorProxy::resetZone() { m_zoneIn = 0; m_zoneOut = -1; } QPoint MonitorProxy::zone() const { return QPoint(m_zoneIn, m_zoneOut); } const QString &MonitorProxy::timecode() const { return m_timecode; } void MonitorProxy::setTimecode(const QString &tc) { m_timecode = tc; emit timecodeChanged(); } QImage MonitorProxy::extractFrame(int frame_position, const QString &path, int width, int height, bool useSourceProfile) { if (width == -1) { width = q->m_monitorProfile->width(); height = q->m_monitorProfile->height(); } else if (width % 2 == 1) { width++; } if (!path.isEmpty()) { QScopedPointer producer(new Mlt::Producer(*q->m_monitorProfile, path.toUtf8().constData())); if (producer && producer->is_valid()) { QImage img = KThumb::getFrame(producer.data(), frame_position, width, height); return img; } } if ((q->m_producer == nullptr) || !path.isEmpty()) { QImage pix(width, height, QImage::Format_RGB32); pix.fill(Qt::black); return pix; } Mlt::Frame *frame = nullptr; QImage img; if (useSourceProfile) { // Our source clip's resolution is higher than current profile, export at full res QScopedPointer tmpProfile(new Mlt::Profile()); QString service = q->m_producer->get("mlt_service"); QScopedPointer tmpProd(new Mlt::Producer(*tmpProfile, service.toUtf8().constData(), q->m_producer->get("resource"))); tmpProfile->from_producer(*tmpProd); width = tmpProfile->width(); height = tmpProfile->height(); if (tmpProd && tmpProd->is_valid()) { Mlt::Filter scaler(*tmpProfile, "swscale"); Mlt::Filter converter(*tmpProfile, "avcolor_space"); tmpProd->attach(scaler); tmpProd->attach(converter); // TODO: paste effects // Clip(*tmpProd).addEffects(*q->m_producer); tmpProd->seek(q->m_producer->position()); frame = tmpProd->get_frame(); img = KThumb::getFrame(frame, width, height); delete frame; } } else if (KdenliveSettings::gpu_accel()) { QString service = q->m_producer->get("mlt_service"); QScopedPointer tmpProd( new Mlt::Producer(*q->m_monitorProfile, service.toUtf8().constData(), q->m_producer->get("resource"))); Mlt::Filter scaler(*q->m_monitorProfile, "swscale"); Mlt::Filter converter(*q->m_monitorProfile, "avcolor_space"); tmpProd->attach(scaler); tmpProd->attach(converter); tmpProd->seek(q->m_producer->position()); frame = tmpProd->get_frame(); img = KThumb::getFrame(frame, width, height); delete frame; } else { frame = q->m_producer->get_frame(); img = KThumb::getFrame(frame, width, height); delete frame; } return img; } + +void MonitorProxy::activateClipMonitor(bool isClipMonitor) +{ + pCore->monitorManager()->activateMonitor(isClipMonitor ? Kdenlive::ClipMonitor : Kdenlive::ProjectMonitor); +} + diff --git a/src/monitor/monitorproxy.h b/src/monitor/monitorproxy.h index 636e50f62..6f4bf2f16 100644 --- a/src/monitor/monitorproxy.h +++ b/src/monitor/monitorproxy.h @@ -1,100 +1,103 @@ /*************************************************************************** * Copyright (C) 2018 by Jean-Baptiste Mardelle (jb@kdenlive.org) * * This file is part of Kdenlive. See www.kdenlive.org. * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ /** @brief This class is a wrapper around the monitor / glwidget and handles communication * with the qml overlay through its properties. */ #ifndef MONITORPROXY_H #define MONITORPROXY_H #include #include class GLWidget; class MonitorProxy : public QObject { Q_OBJECT // Q_PROPERTY(int consumerPosition READ consumerPosition NOTIFY consumerPositionChanged) Q_PROPERTY(int position READ position NOTIFY positionChanged) Q_PROPERTY(int seekPosition READ seekPosition WRITE setSeekPosition NOTIFY seekPositionChanged) Q_PROPERTY(int zoneIn READ zoneIn WRITE setZoneIn NOTIFY zoneChanged) Q_PROPERTY(int zoneOut READ zoneOut WRITE setZoneOut NOTIFY zoneChanged) Q_PROPERTY(int rulerHeight READ rulerHeight NOTIFY rulerHeightChanged) Q_PROPERTY(QString markerComment READ markerComment NOTIFY markerCommentChanged) Q_PROPERTY(int overlayType READ overlayType WRITE setOverlayType NOTIFY overlayTypeChanged) Q_PROPERTY(QString timecode READ timecode NOTIFY timecodeChanged) public: MonitorProxy(GLWidget *parent); int seekPosition() const; int position() const; int rulerHeight() const; int overlayType() const; void setOverlayType(int ix); QString markerComment() const; Q_INVOKABLE void requestSeekPosition(int pos); void setPosition(int pos); void setMarkerComment(const QString &comment); void setSeekPosition(int pos); void pauseAndSeek(int pos); int zoneIn() const; int zoneOut() const; void setZoneIn(int pos); void setZoneOut(int pos); Q_INVOKABLE void setZone(int in, int out); + /** brief: Activate clip monitor if param is true, project monitor otherwise + * */ + Q_INVOKABLE void activateClipMonitor(bool isClipMonitor); void setZone(QPoint zone); void resetZone(); QPoint zone() const; const QString &timecode() const; void setTimecode(const QString &tc); QImage extractFrame(int frame_position, const QString &path = QString(), int width = -1, int height = -1, bool useSourceProfile = false); signals: void positionChanged(); void seekPositionChanged(); void seekRequestChanged(); void zoneChanged(); void markerCommentChanged(); void rulerHeightChanged(); void addSnap(int); void removeSnap(int); void triggerAction(const QString &name); void overlayTypeChanged(); void timecodeChanged(); void seekNextKeyframe(); void seekPreviousKeyframe(); void addRemoveKeyframe(); void seekToKeyframe(); private: GLWidget *q; int m_position; int m_seekPosition; int m_zoneIn; int m_zoneOut; QString m_markerComment; QString m_timecode; }; #endif diff --git a/src/monitor/view/SceneToolBar.qml b/src/monitor/view/SceneToolBar.qml index c7b3ccc15..470b7589c 100644 --- a/src/monitor/view/SceneToolBar.qml +++ b/src/monitor/view/SceneToolBar.qml @@ -1,56 +1,71 @@ import QtQuick.Controls 1.3 import QtQuick.Controls.Styles 1.3 import QtQuick.Layouts 1.3 import QtQuick 2.0 Rectangle { id: scenetoolbar objectName: "scenetoolbar" width: fullscreenButton.width height: childrenRect.height SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } color: Qt.rgba(myPalette.window.r, myPalette.window.g, myPalette.window.b, 0.7) radius: 4 border.color : Qt.rgba(0, 0, 0, 0.3) border.width: 1 Column { ToolButton { id: fullscreenButton objectName: "fullScreen" iconName: "view-fullscreen" tooltip: "Switch Full Screen" - onClicked: controller.triggerAction('monitor_fullscreen') + onClicked: { + controller.activateClipMonitor(root.isClipMonitor) + controller.triggerAction('monitor_fullscreen') + } } ToolButton { objectName: "switchOverlay" iconName: "view-grid" tooltip: "Change Overlay" onClicked: { root.switchOverlay() } } ToolButton { iconName: "zoom-in" tooltip: "Zoom in" - onClicked: controller.triggerAction('monitor_zoomin') + onClicked: { + controller.activateClipMonitor(root.isClipMonitor) + controller.triggerAction('monitor_zoomin') + } } ToolButton { iconName: "zoom-out" tooltip: "Zoom out" - onClicked: controller.triggerAction('monitor_zoomout') + onClicked: { + controller.activateClipMonitor(root.isClipMonitor) + controller.triggerAction('monitor_zoomout') + } } ToolButton { objectName: "addMarker" iconName: "list-add" tooltip: root.isClipMonitor ? "Add Marker" : "Add Guide" - onClicked: controller.triggerAction('add_marker_guide_quickly') + onClicked: { + controller.activateClipMonitor(root.isClipMonitor) + controller.triggerAction('add_marker_guide_quickly') + } } ToolButton { objectName: "removeMarker" iconName: "list-remove" tooltip: root.isClipMonitor ? "Remove Marker" : "Remove Guide" - onClicked: root.isClipMonitor ? controller.triggerAction('delete_clip_marker') : controller.triggerAction('delete_guide') + onClicked: { + controller.activateClipMonitor(root.isClipMonitor) + root.isClipMonitor ? controller.triggerAction('delete_clip_marker') : controller.triggerAction('delete_guide') + } } } }