]> git.sesse.net Git - kdenlive/blobdiff - src/monitor.cpp
Merge branch 'buildsystem' into next
[kdenlive] / src / monitor.cpp
index f84c1b0b84285d05cdfa4052db57ddc0f52e30cf..db3989406dee5d12be592f60ce96b2c36fd14ce3 100644 (file)
 
 
 #include "monitor.h"
-#include "renderer.h"
-#include "monitormanager.h"
 #include "smallruler.h"
 #include "docclipbase.h"
-#include "monitorscene.h"
 #include "abstractclipitem.h"
+#include "monitorscene.h"
+#include "monitoreditwidget.h"
 #include "kdenlivesettings.h"
 
 #include <KDebug>
 #include <QLabel>
 #include <QIntValidator>
 #include <QVBoxLayout>
-#include <QGraphicsView>
 
 
 Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget *parent) :
-    QWidget(parent),
+    AbstractMonitor(parent),
     render(NULL),
     m_name(name),
     m_monitorManager(manager),
     m_currentClip(NULL),
     m_ruler(new SmallRuler(m_monitorManager)),
     m_overlay(NULL),
-    m_isActive(false),
     m_scale(1),
     m_length(0),
     m_dragStarted(false),
     m_monitorRefresh(NULL),
-    m_effectScene(NULL),
-    m_effectView(NULL),
+    m_effectWidget(NULL),
     m_selectedClip(NULL),
-    m_loopClipTransition(true)
-
+    m_loopClipTransition(true),
+    m_editMarker(NULL)
 {
     QVBoxLayout *layout = new QVBoxLayout;
     layout->setContentsMargins(0, 0, 0, 0);
@@ -148,15 +144,6 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget
     m_volumePopup->show();
     m_volumePopup->hide();
 
-    QWidget *spacer = new QWidget(this);
-    spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
-    m_toolbar->addWidget(spacer);
-    m_timePos = new TimecodeDisplay(m_monitorManager->timecode(), this);
-    m_toolbar->addWidget(m_timePos);
-    connect(m_timePos, SIGNAL(editingFinished()), this, SLOT(slotSeek()));
-    m_toolbar->setMaximumHeight(s * 1.5);
-    layout->addWidget(m_toolbar);
-
     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
     setLayout(layout);
     setMinimumHeight(200);
@@ -168,7 +155,7 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget
     createOpenGlWidget(m_videoBox, profile);
     monitorCreated = true;
     //m_glWidget->setFixedSize(width, height);
-#elif defined (USE_OPEN_GL)
+#elif defined(USE_OPENGL)
     if (KdenliveSettings::openglmonitors()) {
         monitorCreated = createOpenGlWidget(m_videoBox, profile);
     }
@@ -181,18 +168,19 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget
         m_videoBox->setLayout(lay);
         render = new Render(m_name, (int) m_monitorRefresh->winId(), profile, this);
         m_monitorRefresh->setRenderer(render);
-    }else if (m_glWidget) {
+    }
+#ifdef USE_OPENGL
+    else if (m_glWidget) {
         lay->addWidget(m_glWidget);
         m_videoBox->setLayout(lay);
     }
+#endif
 
     connect(m_audioSlider, SIGNAL(valueChanged(int)), this, SLOT(slotSetVolume(int)));
     connect(m_ruler, SIGNAL(seekRenderer(int)), this, SLOT(slotSeek(int)));
     connect(render, SIGNAL(durationChanged(int)), this, SLOT(adjustRulerSize(int)));
     connect(render, SIGNAL(rendererStopped(int)), this, SLOT(rendererStopped(int)));
 
-    //render->createVideoXWindow(m_ui.video_frame->winId(), -1);
-
     if (name != "clip") {
         connect(render, SIGNAL(rendererPosition(int)), this, SIGNAL(renderPosition(int)));
         connect(render, SIGNAL(durationChanged(int)), this, SIGNAL(durationChanged(int)));
@@ -204,15 +192,20 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget
     if (m_monitorRefresh) m_monitorRefresh->show();
 
     if (name == "project") {
-        m_effectScene = new MonitorScene(render);
-        m_effectView = new QGraphicsView(m_effectScene, m_videoBox);
-        lay->addWidget(m_effectView);
-        m_effectView->setRenderHints(QFlags<QPainter::RenderHint>());
-        m_effectView->scale(((double) render->renderWidth()) / render->frameRenderWidth(), 1.0);
-        m_effectView->setMouseTracking(true);
-        m_effectScene->setUp();
-        m_effectView->hide();
+        m_effectWidget = new MonitorEditWidget(render, m_videoBox);
+        m_toolbar->addAction(m_effectWidget->getVisibilityAction());
+        lay->addWidget(m_effectWidget);
+        m_effectWidget->hide();
     }
+
+    QWidget *spacer = new QWidget(this);
+    spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+    m_toolbar->addWidget(spacer);
+    m_timePos = new TimecodeDisplay(m_monitorManager->timecode(), this);
+    m_toolbar->addWidget(m_timePos);
+    connect(m_timePos, SIGNAL(editingFinished()), this, SLOT(slotSeek()));
+    m_toolbar->setMaximumHeight(s * 1.5);
+    layout->addWidget(m_toolbar);
 }
 
 Monitor::~Monitor()
@@ -220,10 +213,8 @@ Monitor::~Monitor()
     delete m_ruler;
     delete m_timePos;
     delete m_overlay;
-    if (m_name == "project") {
-        delete m_effectView;
-        delete m_effectScene;
-    }
+    if (m_effectWidget)
+        delete m_effectWidget;
     delete m_monitorRefresh;
     delete render;
 }
@@ -233,12 +224,12 @@ QWidget *Monitor::container()
     return m_videoBox;
 }
 
-QString Monitor::name() const
+const QString Monitor::name() const
 {
     return m_name;
 }
 
-#if defined(Q_WS_MAC) || defined(USE_OPEN_GL)
+#ifdef USE_OPENGL
 bool Monitor::createOpenGlWidget(QWidget *parent, const QString profile)
 {
     render = new Render(m_name, 0, profile, this);
@@ -260,8 +251,16 @@ void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMe
     m_contextMenu->addMenu(m_playMenu);
     if (goMenu)
         m_contextMenu->addMenu(goMenu);
-    if (markerMenu)
+    if (markerMenu) {
         m_contextMenu->addMenu(markerMenu);
+        QList <QAction *>list = markerMenu->actions();
+        for (int i = 0; i < list.count(); i++) {
+            if (list.at(i)->data().toString() == "edit_marker") {
+                m_editMarker = list.at(i);
+                break;
+            }
+        }
+    }
 
     m_playMenu->addAction(playZone);
     m_playMenu->addAction(loopZone);
@@ -429,7 +428,7 @@ void Monitor::slotZoneMoved(int start, int end)
 
 void Monitor::slotSetZoneStart()
 {
-    m_ruler->setZone(render->seekFramePosition(), -1);
+    m_ruler->setZone(m_ruler->position(), -1);
     emit zoneUpdated(m_ruler->zone());
     checkOverlay();
     setClipZone(m_ruler->zone());
@@ -437,7 +436,7 @@ void Monitor::slotSetZoneStart()
 
 void Monitor::slotSetZoneEnd()
 {
-    m_ruler->setZone(-1, render->seekFramePosition());
+    m_ruler->setZone(-1, m_ruler->position());
     emit zoneUpdated(m_ruler->zone());
     checkOverlay();
     setClipZone(m_ruler->zone());
@@ -447,13 +446,22 @@ void Monitor::slotSetZoneEnd()
 void Monitor::mousePressEvent(QMouseEvent * event)
 {
     if (event->button() != Qt::RightButton) {
-        if (m_videoBox->underMouse()) {
+        if (m_videoBox->underMouse() && (!m_overlay || !m_overlay->underMouse())) {
             m_dragStarted = true;
             m_DragStartPosition = event->pos();
         }
-    } else m_contextMenu->popup(event->globalPos());
+    } else if (!m_effectWidget || !m_effectWidget->isVisible()) {
+        m_contextMenu->popup(event->globalPos());
+    }
+}
+
+void Monitor::resizeEvent(QResizeEvent *event)
+{
+    Q_UNUSED(event);
+    if (render && isVisible() && isActive()) render->doRefresh();
 }
 
+
 void Monitor::slotSwitchFullScreen()
 {
     m_videoBox->switchFullScreen();
@@ -463,7 +471,7 @@ void Monitor::slotSwitchFullScreen()
 void Monitor::mouseReleaseEvent(QMouseEvent * event)
 {
     if (m_dragStarted) {
-        if (m_videoBox->underMouse() && (!m_effectView || !m_effectView->isVisible())) {
+        if (m_videoBox->underMouse() && (!m_effectWidget || !m_effectWidget->isVisible())) {
             if (isActive()) slotPlay();
             else activateMonitor();
         } else QWidget::mouseReleaseEvent(event);
@@ -541,7 +549,7 @@ void Monitor::slotMouseSeek(int eventDelta, bool fast)
     if (fast) {
         int delta = m_monitorManager->timecode().fps();
         if (eventDelta > 0) delta = 0 - delta;
-        slotSeek(render->seekFramePosition() - delta);
+        slotSeek(m_ruler->position() - delta);
     } else {
         if (eventDelta >= 0) slotForwardOneFrame();
         else slotRewindOneFrame();
@@ -554,18 +562,22 @@ void Monitor::slotSetThumbFrame()
         return;
     }
     m_currentClip->setClipThumbFrame((uint) render->seekFramePosition());
-    emit refreshClipThumbnail(m_currentClip->getId());
+    emit refreshClipThumbnail(m_currentClip->getId(), true);
 }
 
 void Monitor::slotExtractCurrentFrame()
 {
-    QImage frame = render->extractFrame(render->seekFramePosition());
+    QImage frame;
+    // check if we are using a proxy
+    if (m_currentClip && !m_currentClip->getProperty("proxy").isEmpty() && m_currentClip->getProperty("proxy") != "-") {
+        // using proxy, use original clip url to get frame
+        frame = render->extractFrame(render->seekFramePosition(), m_currentClip->fileURL().path());
+    }
+    else frame = render->extractFrame(render->seekFramePosition());
     KFileDialog *fs = new KFileDialog(KUrl(), "image/png", this);
     fs->setOperationMode(KFileDialog::Saving);
     fs->setMode(KFile::File);
-#if KDE_IS_VERSION(4,2,0)
     fs->setConfirmOverwrite(true);
-#endif
     fs->setKeepLocation(true);
     fs->exec();
     QString path = fs->selectedFile();
@@ -577,14 +589,12 @@ void Monitor::slotExtractCurrentFrame()
 
 bool Monitor::isActive() const
 {
-    return m_isActive;
+    return m_monitorManager->isActive(m_name);
 }
 
-void Monitor::activateMonitor()
+bool Monitor::activateMonitor()
 {
-    if (!m_isActive) {
-        m_monitorManager->slotSwitchMonitors(m_name == "clip");
-    }
+    return m_monitorManager->activateMonitor(m_name);
 }
 
 void Monitor::setTimePos(const QString &pos)
@@ -600,15 +610,15 @@ void Monitor::slotSeek()
 
 void Monitor::slotSeek(int pos)
 {
-    activateMonitor();
     if (render == NULL) return;
+    activateMonitor();
     render->seekToFrame(pos);
 }
 
 void Monitor::checkOverlay()
 {
     if (m_overlay == NULL) return;
-    int pos = render->seekFramePosition();
+    int pos = m_ruler->position();
     QPoint zone = m_ruler->zone();
     if (pos == zone.x())
         m_overlay->setOverlayText(i18n("In Point"));
@@ -693,7 +703,7 @@ void Monitor::slotForwardOneFrame(int diff)
 
 void Monitor::seekCursor(int pos)
 {
-    activateMonitor();
+    //activateMonitor();
     if (m_ruler->slotNewValue(pos)) {
         checkOverlay();
         m_timePos->setValue(pos);
@@ -706,9 +716,6 @@ void Monitor::rendererStopped(int pos)
         checkOverlay();
         m_timePos->setValue(pos);
     }
-    disconnect(m_playAction, SIGNAL(triggered()), this, SLOT(slotPlay()));
-    //m_playAction->setChecked(false);
-    connect(m_playAction, SIGNAL(triggered()), this, SLOT(slotPlay()));
     m_playAction->setIcon(m_playIcon);
 }
 
@@ -724,29 +731,30 @@ void Monitor::adjustRulerSize(int length)
 
 void Monitor::stop()
 {
-    m_isActive = false;
     disconnect(render, SIGNAL(rendererPosition(int)), this, SLOT(seekCursor(int)));
     if (render) render->stop();
 }
 
 void Monitor::start()
 {
-    m_isActive = true;
+    if (!isVisible()) return;
     if (render) render->start();
     connect(render, SIGNAL(rendererPosition(int)), this, SLOT(seekCursor(int)));
 }
 
 void Monitor::refreshMonitor(bool visible)
 {
-    if (visible && render && !m_isActive) {
-        activateMonitor();
-        render->doRefresh(); //askForRefresh();
+    if (visible && render) {
+        if (!activateMonitor()) {
+            // the monitor was already active, simply refreshClipThumbnail
+            render->doRefresh();
+        }
     }
 }
 
 void Monitor::refreshMonitor()
 {
-    if (m_isActive) {
+    if (isActive()) {
         render->doRefresh();
     }
 }
@@ -764,14 +772,13 @@ void Monitor::slotPlay()
 {
     if (render == NULL) return;
     activateMonitor();
-    if (render->playSpeed() == 0) {
-        //m_playAction->setChecked(true);
+    if (render->playSpeed() == 0.0) {
         m_playAction->setIcon(m_pauseIcon);
+        render->switchPlay(true);
     } else {
-        //m_playAction->setChecked(false);
         m_playAction->setIcon(m_playIcon);
+        render->switchPlay(false);
     }
-    render->switchPlay();
 }
 
 void Monitor::slotPlayZone()
@@ -804,27 +811,43 @@ void Monitor::slotLoopClip()
     m_playAction->setIcon(m_pauseIcon);
 }
 
-void Monitor::slotSetXml(DocClipBase *clip, QPoint zone, const int position)
+void Monitor::updateClipProducer(Mlt::Producer *prod)
+{
+    if (render == NULL) return;
+   render->setProducer(prod, render->seekFramePosition());
+}
+
+void Monitor::slotSetClipProducer(DocClipBase *clip, QPoint zone, int position)
 {
     if (render == NULL) return;
     if (clip == NULL && m_currentClip != NULL) {
+        kDebug()<<"// SETTING NULL CLIP MONITOR";
         m_currentClip = NULL;
         m_length = -1;
         render->setProducer(NULL, -1);
         return;
     }
-    if (m_currentClip != NULL || clip != NULL) activateMonitor();
+    
     if (clip != m_currentClip) {
         m_currentClip = clip;
+        if (m_currentClip) activateMonitor();
         updateMarkers(clip);
-        if (render->setProducer(clip->producer(), position) == -1) {
+        Mlt::Producer *prod = NULL;
+        if (clip) prod = clip->getCloneProducer();
+        if (render->setProducer(prod, position) == -1) {
             // MLT CONSUMER is broken
             kDebug(QtWarningMsg) << "ERROR, Cannot start monitor";
         }
-    } else if (position != -1) render->seek(GenTime(position, m_monitorManager->timecode().fps()));
+    } else {
+        if (m_currentClip) {
+            activateMonitor();
+            if (position == -1) position = render->seekFramePosition();
+            render->seek(position);
+        }
+    }
     if (!zone.isNull()) {
         m_ruler->setZone(zone.x(), zone.y());
-        render->seek(GenTime(zone.x(), m_monitorManager->timecode().fps()));
+        render->seek(zone.x());
     }
 }
 
@@ -845,20 +868,21 @@ void Monitor::slotOpenFile(const QString &file)
 void Monitor::slotSaveZone()
 {
     if (render == NULL) return;
-    emit saveZone(render, m_ruler->zone());
+    emit saveZone(render, m_ruler->zone(), m_currentClip);
 
     //render->setSceneList(doc, 0);
 }
 
-void Monitor::resetProfile(const QString profile)
+void Monitor::resetProfile(const QString &profile)
 {
     m_timePos->updateTimeCode(m_monitorManager->timecode());
     if (render == NULL) return;
-    render->resetProfile(profile);
-    if (m_effectScene) {
-        m_effectView->scale(((double) render->renderWidth()) / render->frameRenderWidth(), 1.0);
-        m_effectScene->resetProfile();
+    if (!render->hasProfile(profile)) {
+        activateMonitor();
+        render->resetProfile(profile);
     }
+    if (m_effectWidget)
+        m_effectWidget->resetProfile(render);
 }
 
 void Monitor::saveSceneList(QString path, QDomElement info)
@@ -891,20 +915,38 @@ void Monitor::slotSwitchMonitorInfo(bool show)
         if (m_overlay) return;
         if (m_monitorRefresh == NULL) {
             // Using OpenGL display
-#if defined(Q_WS_MAC) || defined(USE_OPEN_GL)
-            m_overlay = new Overlay(m_glWidget);
+#ifdef USE_OPENGL
+            if (m_glWidget->layout()) delete m_glWidget->layout();
+            m_overlay = new Overlay();
+            connect(m_overlay, SIGNAL(editMarker()), this, SLOT(slotEditMarker()));
+            QVBoxLayout *layout = new QVBoxLayout;
+            layout->addStretch(10);
+            layout->addWidget(m_overlay);
+            m_glWidget->setLayout(layout);
 #endif
         } else {
-            m_overlay = new Overlay(m_monitorRefresh);
+            if (m_monitorRefresh->layout()) delete m_monitorRefresh->layout();
+            m_overlay = new Overlay();
+            connect(m_overlay, SIGNAL(editMarker()), this, SLOT(slotEditMarker()));
+            QVBoxLayout *layout = new QVBoxLayout;
+            layout->addStretch(10);
+            layout->addWidget(m_overlay);
+            m_monitorRefresh->setLayout(layout);
             m_overlay->raise();
             m_overlay->setHidden(true);
         }
+        checkOverlay();
     } else {
         delete m_overlay;
         m_overlay = NULL;
     }
 }
 
+void Monitor::slotEditMarker()
+{
+    if (m_editMarker) m_editMarker->trigger();
+}
+
 void Monitor::updateTimecodeFormat()
 {
     m_timePos->slotUpdateTimeCodeFormat();
@@ -953,27 +995,28 @@ void Monitor::slotEffectScene(bool show)
         if (m_monitorRefresh) {
             m_monitorRefresh->setVisible(!show);
         } else {
-#if defined(Q_WS_MAC) || defined(USE_OPEN_GL)
+#ifdef USE_OPENGL
             m_glWidget->setVisible(!show);
 #endif
         }
-        m_effectView->setVisible(show);
+        m_effectWidget->setVisible(show);
+        m_effectWidget->getVisibilityAction()->setChecked(show);
         emit requestFrameForAnalysis(show);
         if (show) {
-            render->doRefresh();
-            m_effectScene->slotZoomFit();
+            m_effectWidget->getScene()->slotZoomFit();
         }
+        render->doRefresh();
     }
 }
 
-MonitorScene * Monitor::getEffectScene()
+MonitorEditWidget* Monitor::getEffectEdit()
 {
-    return m_effectScene;
+    return m_effectWidget;
 }
 
 bool Monitor::effectSceneDisplayed()
 {
-    return m_effectView->isVisible();
+    return m_effectWidget->isVisible();
 }
 
 void Monitor::slotSetVolume(int volume)
@@ -998,6 +1041,11 @@ void Monitor::slotShowVolume()
     m_volumePopup->show();
 }
 
+AbstractRender *Monitor::abstractRender()
+{
+    return render;
+}
+
 MonitorRefresh::MonitorRefresh(QWidget* parent) :
     QWidget(parent)
     , m_renderer(NULL)
@@ -1005,6 +1053,7 @@ MonitorRefresh::MonitorRefresh(QWidget* parent) :
     // MonitorRefresh is used as container for the SDL display (it's window id is passed to SDL)
     setAttribute(Qt::WA_PaintOnScreen);
     setAttribute(Qt::WA_OpaquePaintEvent);
+    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
     //setAttribute(Qt::WA_NoSystemBackground);
 }
 
@@ -1013,20 +1062,34 @@ void MonitorRefresh::setRenderer(Render* render)
     m_renderer = render;
 }
 
-void MonitorRefresh::paintEvent(QPaintEvent *event)
-{
-    Q_UNUSED(event);
-    if (m_renderer) m_renderer->doRefresh();
-}
 
 Overlay::Overlay(QWidget* parent) :
     QLabel(parent)
 {
-    setAttribute(Qt::WA_TransparentForMouseEvents);
-    //setAttribute(Qt::WA_OpaquePaintEvent);
-    //setAttribute(Qt::WA_NoSystemBackground);
+    //setAttribute(Qt::WA_TransparentForMouseEvents);
     setAutoFillBackground(true);
     setBackgroundRole(QPalette::Base);
+    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+    setCursor(Qt::PointingHandCursor);
+}
+
+// virtual
+void Overlay::mouseReleaseEvent ( QMouseEvent * event )
+{
+    event->accept();
+}
+
+// virtual
+void Overlay::mousePressEvent( QMouseEvent * event )
+{
+    event->accept();
+}
+
+// virtual
+void Overlay::mouseDoubleClickEvent ( QMouseEvent * event )
+{
+    emit editMarker();
+    event->accept();
 }
 
 void Overlay::setOverlayText(const QString &text, bool isZone)
@@ -1098,7 +1161,7 @@ void VideoContainer::wheelEvent(QWheelEvent * event)
 
 void VideoContainer::mouseDoubleClickEvent(QMouseEvent * event)
 {
-    Q_UNUSED(event);
+    Q_UNUSED(event)
 
     if (!KdenliveSettings::openglmonitors())
         switchFullScreen();