Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Start cleanup of monitor, fix some headers

parent de60d3f6
......@@ -35,6 +35,11 @@
#include <KMessageBox>
#include <KRecentDirs>
#include <mlt++/MltConsumer.h>
#include <mlt++/MltProducer.h>
#include <mlt++/MltProfile.h>
#include <mlt++/MltTractor.h>
Generators::Generators(Monitor *monitor, const QString &path, QWidget *parent)
: QDialog(parent)
, m_producer(nullptr)
......
......@@ -25,8 +25,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QImage>
#include <QUrl>
#include <mlt++/Mlt.h>
namespace Mlt {
class Producer;
class Frame;
......
......@@ -26,9 +26,11 @@
#include "klocalizedstring.h"
#include <KColorScheme>
#include <QGraphicsDropShadowEffect>
#include "doc/kthumb.h"
#include <mlt++/MltProducer.h>
#include <mlt++/MltProfile.h>
enum { DvdButtonItem = QGraphicsItem::UserType + 1, DvdButtonUnderlineItem = QGraphicsItem::UserType + 2 };
DvdScene::DvdScene(QObject *parent)
......
......@@ -7,5 +7,5 @@ set(kdenlive_SRCS
monitor/monitormanager.cpp
monitor/recmanager.cpp
monitor/qmlmanager.cpp
monitor/monitorcontroller.cpp
monitor/monitorproxy.cpp
PARENT_SCOPE)
......@@ -31,7 +31,7 @@
#include "core.h"
#include "glwidget.h"
#include "kdenlivesettings.h"
#include "mltcontroller/bincontroller.h"
#include "monitorproxy.h"
#include "profiles/profilemodel.hpp"
#include "qml/qmlaudiothumb.h"
#include "timeline2/view/qml/timelineitems.h"
......@@ -103,6 +103,7 @@ GLWidget::GLWidget(int id, QObject *parent)
, m_shareContext(nullptr)
, m_audioWaveDisplayed(false)
, m_fbo(nullptr)
, m_rulerHeight(QFontMetrics(QApplication::font()).lineSpacing() * 0.7)
{
m_texture[0] = m_texture[1] = m_texture[2] = 0;
qRegisterMetaType<Mlt::Frame>("Mlt::Frame");
......@@ -245,7 +246,7 @@ void GLWidget::initializeGL()
void GLWidget::resizeGL(int width, int height)
{
int x, y, w, h;
height -= m_proxy->rulerHeight();
height -= m_rulerHeight;
double this_aspect = (double)width / height;
double video_aspect = m_monitorProfile->dar();
......@@ -486,10 +487,10 @@ void GLWidget::paintGL()
QVector<QVector2D> vertices;
width = m_rect.width() * devicePixelRatio();
height = m_rect.height() * devicePixelRatio();
vertices << QVector2D(float(-width) / 2.0f, float(-height) / 2.0f + m_proxy->rulerHeight());
vertices << QVector2D(float(-width) / 2.0f, float(height) / 2.0f + m_proxy->rulerHeight());
vertices << QVector2D(float(width) / 2.0f, float(-height) / 2.0f + m_proxy->rulerHeight());
vertices << QVector2D(float(width) / 2.0f, float(height) / 2.0f + m_proxy->rulerHeight());
vertices << QVector2D(float(-width) / 2.0f, float(-height) / 2.0f + m_rulerHeight);
vertices << QVector2D(float(-width) / 2.0f, float(height) / 2.0f + m_rulerHeight);
vertices << QVector2D(float(width) / 2.0f, float(-height) / 2.0f + m_rulerHeight);
vertices << QVector2D(float(width) / 2.0f, float(height) / 2.0f + m_rulerHeight);
m_shader->enableAttributeArray(m_vertexLocation);
check_error(f);
m_shader->setAttributeArray(m_vertexLocation, vertices.constData());
......@@ -1870,3 +1871,14 @@ int GLWidget::duration() const
}
return m_producer->get_playtime();
}
void GLWidget::setConsumerProperty(const QString &name, const QString &value)
{
QMutexLocker locker(&m_mutex);
if (m_consumer) {
m_consumer->set(name.toUtf8().constData(), value.toUtf8().constData());
if (m_consumer->start() == -1) {
qCWarning(KDENLIVE_LOG) << "ERROR, Cannot start monitor";
}
}
}
......@@ -129,6 +129,8 @@ public:
void setVolume(double volume);
/** @brief Returns current producer's duration in frames */
int duration() const;
/** @brief Set a property on the MLT consumer */
void setConsumerProperty(const QString &name, const QString &value);
protected:
void mouseReleaseEvent(QMouseEvent *event) override;
......@@ -181,6 +183,7 @@ protected:
Mlt::Profile *m_monitorProfile;
QMutex m_mutex;
int m_id;
int m_rulerHeight;
private:
QRect m_rect;
......@@ -291,144 +294,4 @@ public:
QOpenGLFunctions_3_2_Core *m_gl32;
bool sendAudioForAnalysis;
};
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)
public:
MonitorProxy(GLWidget *parent)
: QObject(parent)
, q(parent)
, m_position(0)
, m_seekPosition(-1)
, m_zoneIn(0)
, m_zoneOut(-1)
, m_rulerHeight(QFontMetrics(QApplication::font()).lineSpacing() * 0.7)
{
}
int seekPosition() const { return m_seekPosition; }
int position() const { return m_position; }
int rulerHeight() const { return m_rulerHeight; }
int overlayType() const
{
return (q->m_id == (int)Kdenlive::ClipMonitor ? KdenliveSettings::clipMonitorOverlayGuides() : KdenliveSettings::projectMonitorOverlayGuides());
}
void setOverlayType(int ix)
{
if (q->m_id == (int)Kdenlive::ClipMonitor) {
KdenliveSettings::setClipMonitorOverlayGuides(ix);
} else {
KdenliveSettings::setProjectMonitorOverlayGuides(ix);
}
}
QString markerComment() const { return m_markerComment; }
Q_INVOKABLE void requestSeekPosition(int pos)
{
q->activateMonitor();
m_seekPosition = pos;
emit seekPositionChanged();
emit seekRequestChanged();
}
void setPosition(int pos)
{
m_position = pos;
emit positionChanged();
}
void setMarkerComment(const QString &comment)
{
if (m_markerComment == comment) {
return;
}
m_markerComment = comment;
emit markerCommentChanged();
}
void setSeekPosition(int pos)
{
m_seekPosition = pos;
emit seekPositionChanged();
}
void pauseAndSeek(int pos)
{
q->switchPlay(false);
requestSeekPosition(pos);
}
int zoneIn() const { return m_zoneIn; }
int zoneOut() const { return m_zoneOut; }
void setZoneIn(int pos)
{
if (m_zoneIn > 0) {
emit removeSnap(m_zoneIn);
}
m_zoneIn = pos;
if (pos > 0) {
emit addSnap(pos);
}
emit zoneChanged();
}
void setZoneOut(int pos)
{
if (m_zoneOut > 0) {
emit removeSnap(m_zoneOut);
}
m_zoneOut = pos;
if (pos > 0) {
emit addSnap(pos);
}
emit zoneChanged();
}
Q_INVOKABLE void 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 setZone(QPoint zone) { setZone(zone.x(), zone.y()); }
void resetZone()
{
m_zoneIn = 0;
m_zoneOut = -1;
}
QPoint zone() const { return QPoint(m_zoneIn, m_zoneOut); }
signals:
void positionChanged();
void seekPositionChanged();
void seekRequestChanged();
void zoneChanged();
void markerCommentChanged();
void rulerHeightChanged();
void addSnap(int);
void removeSnap(int);
Q_INVOKABLE void triggerAction(const QString &name);
void overlayTypeChanged();
private:
GLWidget *q;
int m_position;
int m_seekPosition;
int m_zoneIn;
int m_zoneOut;
int m_rulerHeight;
QString m_markerComment;
};
#endif
......@@ -31,10 +31,10 @@
#include "mltcontroller/bincontroller.h"
#include "mltcontroller/clip.h"
#include "mltcontroller/clipcontroller.h"
#include "monitorcontroller.hpp"
#include "project/projectmanager.h"
#include "qmlmanager.h"
#include "recmanager.h"
#include "monitorproxy.h"
#include "scopes/monitoraudiolevel.h"
#include "timeline2/model/snapmodel.hpp"
#include "transitions/transitionsrepository.hpp"
......@@ -160,7 +160,6 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
connect(m_glMonitor, &GLWidget::panView, this, &Monitor::panView);
connect(m_glMonitor, &GLWidget::seekPosition, this, &Monitor::slotSeekPosition, Qt::DirectConnection);
connect(m_glMonitor, &GLWidget::activateMonitor, this, &AbstractMonitor::slotActivateMonitor, Qt::DirectConnection);
m_monitorController = new MonitorController(m_glMonitor);
m_videoWidget = QWidget::createWindowContainer(qobject_cast<QWindow *>(m_glMonitor));
m_videoWidget->setAcceptDrops(true);
auto *leventEater = new QuickEventEater(this);
......@@ -1027,10 +1026,10 @@ void Monitor::slotExtractCurrentFrame(QString frameName, bool addToProject)
m_controller->getProducerProperty(QStringLiteral("kdenlive:proxy")) != QLatin1String("-")) {
// using proxy, use original clip url to get frame
frame =
m_monitorController->extractFrame(m_glMonitor->getCurrentPos(), m_controller->getProducerProperty(QStringLiteral("kdenlive:originalurl")),
m_glMonitor->getControllerProxy()->extractFrame(m_glMonitor->getCurrentPos(), m_controller->getProducerProperty(QStringLiteral("kdenlive:originalurl")),
-1, -1, b != nullptr ? b->isChecked() : false);
} else {
frame = m_monitorController->extractFrame(m_glMonitor->getCurrentPos(), QString(), -1, -1, b != nullptr ? b->isChecked() : false);
frame = m_glMonitor->getControllerProxy()->extractFrame(m_glMonitor->getCurrentPos(), QString(), -1, -1, b != nullptr ? b->isChecked() : false);
}
frame.save(selectedFile);
if (b != nullptr) {
......@@ -2018,7 +2017,7 @@ void Monitor::prepareAudioThumb(int channels, QVariantList &audioCache)
void Monitor::slotUpdateQmlTimecode(const QString &tc)
{
checkDrops(m_glMonitor->droppedFrames());
m_glMonitor->rootObject()->setProperty("timecode", tc);
m_glMonitor->getControllerProxy()->setTimecode(tc);
}
void Monitor::slotSwitchAudioMonitor()
......@@ -2136,3 +2135,8 @@ void Monitor::slotZoomOut()
{
m_glMonitor->slotZoom(false);
}
void Monitor::setConsumerProperty(const QString &name, const QString &value)
{
m_glMonitor->setConsumerProperty(name, value);
}
......@@ -50,7 +50,6 @@ class QToolButton;
class QmlManager;
class GLWidget;
class MonitorAudioLevel;
class MonitorController;
namespace Mlt {
class Profile;
......@@ -160,6 +159,8 @@ public:
void slotZoomIn();
/** @brief Zoom out active monitor */
void slotZoomOut();
/** @brief Set a property on the MLT consumer */
void setConsumerProperty(const QString &name, const QString &value);
protected:
void mousePressEvent(QMouseEvent *event) override;
......@@ -178,7 +179,6 @@ protected:
void enterEvent(QEvent *event) override;
void leaveEvent(QEvent *event) override;
virtual QStringList mimeTypes() const;
MonitorController *m_monitorController;
private:
std::shared_ptr<ProjectClip> m_controller;
......
......@@ -23,7 +23,6 @@
#include "kdenlivesettings.h"
#include "mainwindow.h"
#include "mltcontroller/bincontroller.h"
#include "monitorcontroller.hpp"
#include "renderer.h"
#include "utils/KoIconUtils.h"
......@@ -94,10 +93,10 @@ AbstractMonitor *MonitorManager::monitor(Kdenlive::MonitorId monitorName)
void MonitorManager::setConsumerProperty(const QString &name, const QString &value)
{
if (m_clipMonitor) {
m_clipMonitor->m_monitorController->setConsumerProperty(name, value);
m_clipMonitor->setConsumerProperty(name, value);
}
if (m_projectMonitor) {
m_projectMonitor->m_monitorController->setConsumerProperty(name, value);
m_projectMonitor->setConsumerProperty(name, value);
}
}
......
/***************************************************************************
* Copyright (C) 2017 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
* 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 *
......@@ -19,47 +19,194 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include "monitorcontroller.hpp"
#include "doc/kthumb.h"
#include "monitorproxy.h"
#include "glwidget.h"
#include "kdenlivesettings.h"
#include "definitions.h"
#include "doc/kthumb.h"
#include <mlt++/MltConsumer.h>
#include <mlt++/MltProducer.h>
#include <mlt++/MltProfile.h>
#include <mlt++/MltFilter.h>
MonitorController::MonitorController(GLWidget *widget)
: QObject(widget)
, m_glWidget(widget)
MonitorProxy::MonitorProxy(GLWidget *parent) :
QObject(parent)
, q(parent)
, m_position(0)
, m_seekPosition(-1)
, m_zoneIn(0)
, m_zoneOut(-1)
{
}
void MonitorController::setConsumerProperty(const QString &name, const QString &value)
int MonitorProxy::seekPosition() const
{
QMutexLocker locker(&m_glWidget->m_mutex);
if (m_glWidget->m_consumer) {
m_glWidget->m_consumer->set(name.toUtf8().constData(), value.toUtf8().constData());
if (m_glWidget->m_consumer->start() == -1) {
qCWarning(KDENLIVE_LOG) << "ERROR, Cannot start monitor";
}
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 MonitorController::extractFrame(int frame_position, const QString &path, int width, int height, bool useSourceProfile)
QImage MonitorProxy::extractFrame(int frame_position, const QString &path, int width, int height, bool useSourceProfile)
{
if (width == -1) {
width = m_glWidget->m_monitorProfile->width();
height = m_glWidget->m_monitorProfile->height();
width = q->m_monitorProfile->width();
height = q->m_monitorProfile->height();
} else if (width % 2 == 1) {
width++;
}
if (!path.isEmpty()) {
QScopedPointer<Mlt::Producer> producer(new Mlt::Producer(*m_glWidget->m_monitorProfile, path.toUtf8().constData()));
QScopedPointer<Mlt::Producer> 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 ((m_glWidget->m_producer == nullptr) || !path.isEmpty()) {
if ((q->m_producer == nullptr) || !path.isEmpty()) {
QImage pix(width, height, QImage::Format_RGB32);
pix.fill(Qt::black);
return pix;
......@@ -69,8 +216,8 @@ QImage MonitorController::extractFrame(int frame_position, const QString &path,
if (useSourceProfile) {
// Our source clip's resolution is higher than current profile, export at full res
QScopedPointer<Mlt::Profile> tmpProfile(new Mlt::Profile());
QString service = m_glWidget->m_producer->get("mlt_service");
QScopedPointer<Mlt::Producer> tmpProd(new Mlt::Producer(*tmpProfile, service.toUtf8().constData(), m_glWidget->m_producer->get("resource")));
QString service = q->m_producer->get("mlt_service");
QScopedPointer<Mlt::Producer> tmpProd(new Mlt::Producer(*tmpProfile, service.toUtf8().constData(), q->m_producer->get("resource")));
tmpProfile->from_producer(*tmpProd);
width = tmpProfile->width();
height = tmpProfile->height();
......@@ -80,26 +227,26 @@ QImage MonitorController::extractFrame(int frame_position, const QString &path,
tmpProd->attach(scaler);
tmpProd->attach(converter);
// TODO: paste effects
// Clip(*tmpProd).addEffects(*m_glWidget->m_producer);
tmpProd->seek(m_glWidget->m_producer->position());
// 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 = m_glWidget->m_producer->get("mlt_service");
QString service = q->m_producer->get("mlt_service");
QScopedPointer<Mlt::Producer> tmpProd(
new Mlt::Producer(*m_glWidget->m_monitorProfile, service.toUtf8().constData(), m_glWidget->m_producer->get("resource")));
Mlt::Filter scaler(*m_glWidget->m_monitorProfile, "swscale");
Mlt::Filter converter(*m_glWidget->m_monitorProfile, "avcolor_space");
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(m_glWidget->m_producer->position());
tmpProd->seek(q->m_producer->position());
frame = tmpProd->get_frame();
img = KThumb::getFrame(frame, width, height);
delete frame;
} else {
frame = m_glWidget->m_producer->get_frame();
frame = q->m_producer->get_frame();
img = KThumb::getFrame(frame, width, height);
delete frame;
}
......
/***************************************************************************
* Copyright (C) 2017 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
* 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 *
......@@ -19,23 +19,78 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef MONITORCONTROLLER_H
#define MONITORCONTROLLER_H
#include "glwidget.h"
/** @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 <QObject>
#include <QImage>
class GLWidget;
class MonitorController : public QObject
class MonitorProxy : public QObject
{
Q_OBJECT
public:
MonitorController(GLWidget *widget);
// 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)
void setConsumerProperty(const QString &name, const QString &value);
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 p