]> git.sesse.net Git - kdenlive/blob - src/monitor.cpp
Insert Space Dialog:
[kdenlive] / src / monitor.cpp
1 /***************************************************************************
2  *   Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
18  ***************************************************************************/
19
20
21 #include "monitor.h"
22 #include "renderer.h"
23 #include "monitormanager.h"
24 #include "smallruler.h"
25 #include "docclipbase.h"
26 #include "kdenlivesettings.h"
27
28 #include <KDebug>
29 #include <KLocale>
30 #include <KFileDialog>
31 #include <KApplication>
32 #include <KMessageBox>
33
34 #include <QMouseEvent>
35 #include <QStylePainter>
36 #include <QMenu>
37 #include <QToolButton>
38 #include <QToolBar>
39 #include <QDesktopWidget>
40 #include <QLabel>
41 #include <QIntValidator>
42
43
44 Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget *parent) :
45         QWidget(parent),
46         render(NULL),
47         m_name(name),
48         m_monitorManager(manager),
49         m_currentClip(NULL),
50         m_ruler(new SmallRuler(m_monitorManager)),
51         m_overlay(NULL),
52         m_isActive(false),
53         m_scale(1),
54         m_length(0),
55         m_dragStarted(false)
56 {
57     m_ui.setupUi(this);
58     QVBoxLayout *layout = new QVBoxLayout;
59     layout->setContentsMargins(0, 0, 0, 0);
60     layout->addWidget(m_ruler);
61     m_ui.ruler_frame->setLayout(layout);
62     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
63     setMinimumHeight(200);
64     QToolBar *toolbar = new QToolBar(name, this);
65     QVBoxLayout *layout2 = new QVBoxLayout;
66     layout2->setContentsMargins(0, 0, 0, 0);
67
68     m_playIcon = KIcon("media-playback-start");
69     m_pauseIcon = KIcon("media-playback-pause");
70
71     if (name != "chapter") {
72         toolbar->addAction(KIcon("kdenlive-zone-start"), i18n("Set zone start"), this, SLOT(slotSetZoneStart()));
73         toolbar->addAction(KIcon("kdenlive-zone-end"), i18n("Set zone end"), this, SLOT(slotSetZoneEnd()));
74     } else m_ruler->setZone(-3, -2);
75
76     toolbar->addAction(KIcon("media-seek-backward"), i18n("Rewind"), this, SLOT(slotRewind()));
77     toolbar->addAction(KIcon("media-skip-backward"), i18n("Rewind 1 frame"), this, SLOT(slotRewindOneFrame()));
78
79     QToolButton *playButton = new QToolButton(toolbar);
80     m_playMenu = new QMenu(i18n("Play..."), this);
81     m_playAction = m_playMenu->addAction(m_playIcon, i18n("Play"));
82     m_playAction->setCheckable(true);
83     connect(m_playAction, SIGNAL(triggered()), this, SLOT(slotPlay()));
84
85     playButton->setMenu(m_playMenu);
86     playButton->setPopupMode(QToolButton::MenuButtonPopup);
87     toolbar->addWidget(playButton);
88
89     toolbar->addAction(KIcon("media-skip-forward"), i18n("Forward 1 frame"), this, SLOT(slotForwardOneFrame()));
90     toolbar->addAction(KIcon("media-seek-forward"), i18n("Forward"), this, SLOT(slotForward()));
91
92     playButton->setDefaultAction(m_playAction);
93
94     if (name != "chapter") {
95         QToolButton *configButton = new QToolButton(toolbar);
96         m_configMenu = new QMenu(i18n("Misc..."), this);
97         configButton->setIcon(KIcon("system-run"));
98         configButton->setMenu(m_configMenu);
99         configButton->setPopupMode(QToolButton::QToolButton::InstantPopup);
100         toolbar->addWidget(configButton);
101
102         if (name == "clip") {
103             m_markerMenu = new QMenu(i18n("Go to marker..."), this);
104             m_markerMenu->setEnabled(false);
105             m_configMenu->addMenu(m_markerMenu);
106             connect(m_markerMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotGoToMarker(QAction *)));
107         }
108         m_configMenu->addAction(KIcon("transform-scale"), i18n("Resize (100%)"), this, SLOT(slotSetSizeOneToOne()));
109         m_configMenu->addAction(KIcon("transform-scale"), i18n("Resize (50%)"), this, SLOT(slotSetSizeOneToTwo()));
110     }
111
112     QWidget *spacer = new QWidget(this);
113     spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
114     toolbar->addWidget(spacer);
115     m_timePos = new TimecodeDisplay(m_monitorManager->timecode(), this);
116     toolbar->addWidget(m_timePos);
117     connect(m_timePos, SIGNAL(editingFinished()), this, SLOT(slotSeek()));
118
119     layout2->addWidget(toolbar);
120     m_ui.button_frame->setLayout(layout2);
121     const int toolHeight = toolbar->height();
122     m_ui.button_frame->setMinimumHeight(toolHeight);
123
124     //m_ruler->setPixelPerMark(3);
125
126     if (profile.isEmpty()) profile = KdenliveSettings::current_profile();
127
128     QVBoxLayout *rendererBox = new QVBoxLayout(m_ui.video_frame);
129     rendererBox->setContentsMargins(0, 0, 0, 0);
130 #ifdef Q_WS_MAC
131     m_glWidget = new VideoGLWidget(m_ui.video_frame);
132     rendererBox->addWidget(m_glWidget);
133     render = new Render(m_name, (int) m_ui.video_frame->winId(), -1, profile, this);
134     m_glWidget->setImageAspectRatio(render->dar());
135     m_glWidget->setBackgroundColor(KdenliveSettings::window_background());
136     m_glWidget->resize(m_ui.video_frame->size());
137     connect(render, SIGNAL(showImageSignal(QImage)), m_glWidget, SLOT(showImage(QImage)));
138     m_monitorRefresh = 0;
139 #else
140     m_monitorRefresh = new MonitorRefresh(m_ui.video_frame);
141     rendererBox->addWidget(m_monitorRefresh);
142     render = new Render(m_name, (int) m_monitorRefresh->winId(), -1, profile, this);
143     m_monitorRefresh->setRenderer(render);
144 #endif
145
146     connect(m_ruler, SIGNAL(seekRenderer(int)), this, SLOT(slotSeek(int)));
147     connect(render, SIGNAL(durationChanged(int)), this, SLOT(adjustRulerSize(int)));
148     connect(render, SIGNAL(rendererStopped(int)), this, SLOT(rendererStopped(int)));
149
150     //render->createVideoXWindow(m_ui.video_frame->winId(), -1);
151
152     if (name != "clip") {
153         connect(render, SIGNAL(rendererPosition(int)), this, SIGNAL(renderPosition(int)));
154         connect(render, SIGNAL(durationChanged(int)), this, SIGNAL(durationChanged(int)));
155         connect(m_ruler, SIGNAL(zoneChanged(QPoint)), this, SIGNAL(zoneUpdated(QPoint)));
156     } else {
157         connect(m_ruler, SIGNAL(zoneChanged(QPoint)), this, SLOT(setClipZone(QPoint)));
158     }
159 #ifndef Q_WS_MAC
160     m_monitorRefresh->show();
161 #endif
162     kDebug() << "/////// BUILDING MONITOR, ID: " << m_ui.video_frame->winId();
163 }
164
165 Monitor::~Monitor()
166 {
167     delete m_ruler;
168     delete m_timePos;
169     delete m_overlay;
170     delete m_monitorRefresh;
171     delete render;
172 }
173
174 QString Monitor::name() const
175 {
176     return m_name;
177 }
178
179 void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMenu *markerMenu)
180 {
181     m_contextMenu = new QMenu(this);
182     m_contextMenu->addMenu(m_playMenu);
183     if (goMenu) m_contextMenu->addMenu(goMenu);
184     if (markerMenu) m_contextMenu->addMenu(markerMenu);
185
186     m_playMenu->addAction(playZone);
187     m_playMenu->addAction(loopZone);
188
189     //TODO: add save zone to timeline monitor when fixed
190     if (m_name == "clip") {
191         m_contextMenu->addMenu(m_markerMenu);
192         m_contextMenu->addAction(KIcon("document-save"), i18n("Save zone"), this, SLOT(slotSaveZone()));
193     }
194     QAction *extractFrame = m_configMenu->addAction(KIcon("document-new"), i18n("Extract frame"), this, SLOT(slotExtractCurrentFrame()));
195     m_contextMenu->addAction(extractFrame);
196
197     if (m_name != "clip") {
198 #ifndef Q_WS_MAC
199         QAction *splitView = m_contextMenu->addAction(KIcon("view-split-left-right"), i18n("Split view"), render, SLOT(slotSplitView(bool)));
200         splitView->setCheckable(true);
201         m_configMenu->addAction(splitView);
202 #endif
203     } else {
204         QAction *setThumbFrame = m_contextMenu->addAction(KIcon("document-new"), i18n("Set current image as thumbnail"), this, SLOT(slotSetThumbFrame()));
205         m_configMenu->addAction(setThumbFrame);
206     }
207
208     QAction *showTips = m_contextMenu->addAction(KIcon("help-hint"), i18n("Monitor overlay infos"));
209     showTips->setCheckable(true);
210     connect(showTips, SIGNAL(toggled(bool)), this, SLOT(slotSwitchMonitorInfo(bool)));
211     showTips->setChecked(KdenliveSettings::displayMonitorInfo());
212
213     QAction *dropFrames = m_contextMenu->addAction(KIcon(), i18n("Real time (drop frames)"));
214     dropFrames->setCheckable(true);
215     dropFrames->setChecked(true);
216     connect(dropFrames, SIGNAL(toggled(bool)), this, SLOT(slotSwitchDropFrames(bool)));
217
218     m_configMenu->addAction(showTips);
219     m_configMenu->addAction(dropFrames);
220
221 }
222
223 void Monitor::slotGoToMarker(QAction *action)
224 {
225     int pos = action->data().toInt();
226     slotSeek(pos);
227 }
228
229 void Monitor::slotSetSizeOneToOne()
230 {
231     QRect r = QApplication::desktop()->screenGeometry();
232     const int maxWidth = r.width() - 20;
233     const int maxHeight = r.height() - 20;
234     int width = render->renderWidth();
235     int height = render->renderHeight();
236     kDebug() << "// render info: " << width << "x" << height;
237     while (width >= maxWidth || height >= maxHeight) {
238         width = width * 0.8;
239         height = height * 0.8;
240     }
241     kDebug() << "// MONITOR; set SIZE: " << width << ", " << height;
242     m_ui.video_frame->setFixedSize(width, height);
243     updateGeometry();
244     adjustSize();
245     //m_ui.video_frame->setMinimumSize(0, 0);
246     emit adjustMonitorSize();
247 }
248
249 void Monitor::slotSetSizeOneToTwo()
250 {
251     QRect r = QApplication::desktop()->screenGeometry();
252     const int maxWidth = r.width() - 20;
253     const int maxHeight = r.height() - 20;
254     int width = render->renderWidth() / 2;
255     int height = render->renderHeight() / 2;
256     kDebug() << "// render info: " << width << "x" << height;
257     while (width >= maxWidth || height >= maxHeight) {
258         width = width * 0.8;
259         height = height * 0.8;
260     }
261     kDebug() << "// MONITOR; set SIZE: " << width << ", " << height;
262     m_ui.video_frame->setFixedSize(width, height);
263     updateGeometry();
264     adjustSize();
265     //m_ui.video_frame->setMinimumSize(0, 0);
266     emit adjustMonitorSize();
267 }
268
269 void Monitor::resetSize()
270 {
271     m_ui.video_frame->setMinimumSize(0, 0);
272 }
273
274 DocClipBase *Monitor::activeClip()
275 {
276     return m_currentClip;
277 }
278
279 void Monitor::updateMarkers(DocClipBase *source)
280 {
281     if (source == m_currentClip && source != NULL) {
282         m_markerMenu->clear();
283         QList <CommentedTime> markers = m_currentClip->commentedSnapMarkers();
284         if (!markers.isEmpty()) {
285             QList <int> marks;
286             for (int i = 0; i < markers.count(); i++) {
287                 int pos = (int) markers.at(i).time().frames(m_monitorManager->timecode().fps());
288                 marks.append(pos);
289                 QString position = m_monitorManager->timecode().getTimecode(markers.at(i).time()) + ' ' + markers.at(i).comment();
290                 QAction *go = m_markerMenu->addAction(position);
291                 go->setData(pos);
292             }
293             m_ruler->setMarkers(marks);
294         } else m_ruler->setMarkers(QList <int>());
295         m_markerMenu->setEnabled(!m_markerMenu->isEmpty());
296     }
297 }
298
299 void Monitor::slotSeekToPreviousSnap()
300 {
301     if (m_currentClip) slotSeek(getSnapForPos(true).frames(m_monitorManager->timecode().fps()));
302 }
303
304 void Monitor::slotSeekToNextSnap()
305 {
306     if (m_currentClip) slotSeek(getSnapForPos(false).frames(m_monitorManager->timecode().fps()));
307 }
308
309 GenTime Monitor::position()
310 {
311     return render->seekPosition();
312 }
313
314 GenTime Monitor::getSnapForPos(bool previous)
315 {
316     QList <GenTime> snaps;
317     QList < GenTime > markers = m_currentClip->snapMarkers();
318     for (int i = 0; i < markers.size(); ++i) {
319         GenTime t = markers.at(i);
320         snaps.append(t);
321     }
322     QPoint zone = m_ruler->zone();
323     snaps.append(GenTime(zone.x(), m_monitorManager->timecode().fps()));
324     snaps.append(GenTime(zone.y(), m_monitorManager->timecode().fps()));
325     snaps.append(GenTime());
326     snaps.append(m_currentClip->duration());
327     qSort(snaps);
328
329     const GenTime pos = render->seekPosition();
330     for (int i = 0; i < snaps.size(); ++i) {
331         if (previous && snaps.at(i) >= pos) {
332             if (i == 0) i = 1;
333             return snaps.at(i - 1);
334         } else if (!previous && snaps.at(i) > pos) {
335             return snaps.at(i);
336         }
337     }
338     return GenTime();
339 }
340
341 void Monitor::slotZoneMoved(int start, int end)
342 {
343     m_ruler->setZone(start, end);
344     checkOverlay();
345     setClipZone(m_ruler->zone());
346 }
347
348 void Monitor::slotSetZoneStart()
349 {
350     m_ruler->setZone(render->seekFramePosition(), -1);
351     emit zoneUpdated(m_ruler->zone());
352     checkOverlay();
353     setClipZone(m_ruler->zone());
354 }
355
356 void Monitor::slotSetZoneEnd()
357 {
358     m_ruler->setZone(-1, render->seekFramePosition());
359     emit zoneUpdated(m_ruler->zone());
360     checkOverlay();
361     setClipZone(m_ruler->zone());
362 }
363
364 // virtual
365 void Monitor::mousePressEvent(QMouseEvent * event)
366 {
367     if (event->button() != Qt::RightButton) {
368         if (m_ui.video_frame->underMouse()) {
369             m_dragStarted = true;
370             m_DragStartPosition = event->pos();
371         }
372     } else m_contextMenu->popup(event->globalPos());
373 }
374
375 // virtual
376 void Monitor::mouseReleaseEvent(QMouseEvent * event)
377 {
378     if (m_dragStarted) {
379         if (m_ui.video_frame->underMouse()) {
380             if (isActive()) slotPlay();
381             else activateMonitor();
382         } else QWidget::mouseReleaseEvent(event);
383         m_dragStarted = false;
384     }
385 }
386
387 // virtual
388 void Monitor::mouseMoveEvent(QMouseEvent *event)
389 {
390     // kDebug() << "// DRAG STARTED, MOUSE MOVED: ";
391     if (!m_dragStarted || m_currentClip == NULL) return;
392
393     if ((event->pos() - m_DragStartPosition).manhattanLength()
394             < QApplication::startDragDistance())
395         return;
396
397     {
398         QDrag *drag = new QDrag(this);
399         QMimeData *mimeData = new QMimeData;
400
401         QStringList list;
402         list.append(m_currentClip->getId());
403         QPoint p = m_ruler->zone();
404         list.append(QString::number(p.x()));
405         list.append(QString::number(p.y()));
406         QByteArray data;
407         data.append(list.join(";").toUtf8());
408         mimeData->setData("kdenlive/clip", data);
409         drag->setMimeData(mimeData);
410         QPixmap pix = m_currentClip->thumbnail();
411         drag->setPixmap(pix);
412         drag->setHotSpot(QPoint(0, 50));
413         drag->start(Qt::MoveAction);
414
415         //Qt::DropAction dropAction;
416         //dropAction = drag->start(Qt::CopyAction | Qt::MoveAction);
417
418         //Qt::DropAction dropAction = drag->exec();
419
420     }
421     //event->accept();
422 }
423
424 /*void Monitor::dragMoveEvent(QDragMoveEvent * event) {
425     event->setDropAction(Qt::IgnoreAction);
426     event->setDropAction(Qt::MoveAction);
427     if (event->mimeData()->hasText()) {
428         event->acceptProposedAction();
429     }
430 }
431
432 Qt::DropActions Monitor::supportedDropActions() const {
433     // returns what actions are supported when dropping
434     return Qt::MoveAction;
435 }*/
436
437 QStringList Monitor::mimeTypes() const
438 {
439     QStringList qstrList;
440     // list of accepted mime types for drop
441     qstrList.append("kdenlive/clip");
442     return qstrList;
443 }
444
445 // virtual
446 void Monitor::wheelEvent(QWheelEvent * event)
447 {
448     if (event->modifiers() == Qt::ControlModifier) {
449         int delta = m_monitorManager->timecode().fps();
450         if (event->delta() > 0) delta = 0 - delta;
451         slotSeek(render->seekFramePosition() - delta);
452     } else {
453         if (event->delta() >= 0) slotForwardOneFrame();
454         else slotRewindOneFrame();
455     }
456 }
457
458 void Monitor::slotSetThumbFrame()
459 {
460     if (m_currentClip == NULL) {
461         return;
462     }
463     m_currentClip->setClipThumbFrame((uint) render->seekFramePosition());
464     emit refreshClipThumbnail(m_currentClip->getId());
465 }
466
467 void Monitor::slotExtractCurrentFrame()
468 {
469     QImage frame = render->extractFrame(render->seekFramePosition());
470     KFileDialog *fs = new KFileDialog(KUrl(), "image/png", this);
471     fs->setOperationMode(KFileDialog::Saving);
472     fs->setMode(KFile::File);
473 #if KDE_IS_VERSION(4,2,0)
474     fs->setConfirmOverwrite(true);
475 #endif
476     fs->setKeepLocation(true);
477     fs->exec();
478     QString path = fs->selectedFile();
479     delete fs;
480     if (!path.isEmpty()) {
481         frame.save(path);
482     }
483 }
484
485 bool Monitor::isActive() const
486 {
487     return m_isActive;
488 }
489
490 void Monitor::activateMonitor()
491 {
492     if (!m_isActive) {
493         m_monitorManager->slotSwitchMonitors(m_name == "clip");
494     }
495 }
496
497 void Monitor::setTimePos(const QString &pos)
498 {
499     m_timePos->setValue(pos);
500     slotSeek();
501 }
502
503 void Monitor::slotSeek()
504 {
505     slotSeek(m_timePos->value());
506 }
507
508 void Monitor::slotSeek(int pos)
509 {
510     activateMonitor();
511     if (render == NULL) return;
512     render->seekToFrame(pos);
513     emit renderPosition(render->seekFramePosition());
514 }
515
516 void Monitor::checkOverlay()
517 {
518     if (m_overlay == NULL) return;
519     int pos = render->seekFramePosition();
520     QPoint zone = m_ruler->zone();
521     if (pos == zone.x()) m_overlay->setOverlayText(i18n("In Point"));
522     else if (pos == zone.y()) m_overlay->setOverlayText(i18n("Out Point"));
523     else {
524         if (m_currentClip) {
525             QString markerComment = m_currentClip->markerComment(GenTime(pos, m_monitorManager->timecode().fps()));
526             if (markerComment.isEmpty()) m_overlay->setHidden(true);
527             else m_overlay->setOverlayText(markerComment, false);
528         } else m_overlay->setHidden(true);
529     }
530 }
531
532 void Monitor::slotStart()
533 {
534     activateMonitor();
535     render->play(0);
536     render->seekToFrame(0);
537     //emit renderPosition(0);
538 }
539
540 void Monitor::slotEnd()
541 {
542     activateMonitor();
543     render->play(0);
544     render->seekToFrame(render->getLength());
545     //emit renderPosition(render->seekFramePosition());
546 }
547
548 void Monitor::slotZoneStart()
549 {
550     activateMonitor();
551     render->play(0);
552     render->seekToFrame(m_ruler->zone().x());
553     emit renderPosition(render->seekFramePosition());
554 }
555
556 void Monitor::slotZoneEnd()
557 {
558     activateMonitor();
559     render->play(0);
560     render->seekToFrame(m_ruler->zone().y());
561     emit renderPosition(render->seekFramePosition());
562 }
563
564 void Monitor::slotRewind(double speed)
565 {
566     activateMonitor();
567     if (speed == 0) {
568         double currentspeed = render->playSpeed();
569         if (currentspeed >= 0) render->play(-2);
570         else render->play(currentspeed * 2);
571     } else render->play(speed);
572     m_playAction->setChecked(true);
573     m_playAction->setIcon(m_pauseIcon);
574 }
575
576 void Monitor::slotForward(double speed)
577 {
578     activateMonitor();
579     if (speed == 0) {
580         double currentspeed = render->playSpeed();
581         if (currentspeed <= 1) render->play(2);
582         else render->play(currentspeed * 2);
583     } else render->play(speed);
584     m_playAction->setChecked(true);
585     m_playAction->setIcon(m_pauseIcon);
586 }
587
588 void Monitor::slotRewindOneFrame(int diff)
589 {
590     activateMonitor();
591     render->play(0);
592     render->seekToFrameDiff(-diff);
593     emit renderPosition(render->seekFramePosition());
594 }
595
596 void Monitor::slotForwardOneFrame(int diff)
597 {
598     activateMonitor();
599     render->play(0);
600     render->seekToFrameDiff(diff);
601     emit renderPosition(render->seekFramePosition());
602 }
603
604 void Monitor::seekCursor(int pos)
605 {
606     activateMonitor();
607     if (m_ruler->slotNewValue(pos)) {
608         checkOverlay();
609         m_timePos->setValue(pos);
610     }
611 }
612
613 void Monitor::rendererStopped(int pos)
614 {
615     if (m_ruler->slotNewValue(pos)) {
616         checkOverlay();
617         m_timePos->setValue(pos);
618     }
619     disconnect(m_playAction, SIGNAL(triggered()), this, SLOT(slotPlay()));
620     m_playAction->setChecked(false);
621     connect(m_playAction, SIGNAL(triggered()), this, SLOT(slotPlay()));
622     m_playAction->setIcon(m_playIcon);
623 }
624
625 void Monitor::initMonitor()
626 {
627     kDebug() << "/////// INITING MONITOR, ID: " << m_ui.video_frame->winId();
628 }
629
630 // virtual
631 /*void Monitor::resizeEvent(QResizeEvent * event) {
632     QWidget::resizeEvent(event);
633     adjustRulerSize(-1);
634     if (render && m_isActive) render->doRefresh();
635     //
636 }*/
637
638 void Monitor::adjustRulerSize(int length)
639 {
640     if (length > 0) m_length = length;
641     m_ruler->adjustScale(m_length);
642     if (m_currentClip != NULL) {
643         QPoint zone = m_currentClip->zone();
644         m_ruler->setZone(zone.x(), zone.y());
645     }
646 }
647
648 void Monitor::stop()
649 {
650     m_isActive = false;
651     disconnect(render, SIGNAL(rendererPosition(int)), this, SLOT(seekCursor(int)));
652     if (render) render->stop();
653 }
654
655 void Monitor::start()
656 {
657     m_isActive = true;
658     if (render) render->start();
659     connect(render, SIGNAL(rendererPosition(int)), this, SLOT(seekCursor(int)));
660 }
661
662 void Monitor::refreshMonitor(bool visible)
663 {
664     if (visible && render && !m_isActive) {
665         activateMonitor();
666         render->doRefresh(); //askForRefresh();
667     }
668 }
669
670 void Monitor::pause()
671 {
672     if (render == NULL) return;
673     activateMonitor();
674     render->pause();
675     //m_playAction->setChecked(true);
676     //m_playAction->setIcon(m_pauseIcon);
677 }
678
679 void Monitor::slotPlay()
680 {
681     if (render == NULL) return;
682     activateMonitor();
683     if (render->playSpeed() == 0) {
684         m_playAction->setChecked(true);
685         m_playAction->setIcon(m_pauseIcon);
686     } else {
687         m_playAction->setChecked(false);
688         m_playAction->setIcon(m_playIcon);
689     }
690     render->switchPlay();
691 }
692
693 void Monitor::slotPlayZone()
694 {
695     if (render == NULL) return;
696     activateMonitor();
697     QPoint p = m_ruler->zone();
698     render->playZone(GenTime(p.x(), m_monitorManager->timecode().fps()), GenTime(p.y(), m_monitorManager->timecode().fps()));
699     m_playAction->setChecked(true);
700     m_playAction->setIcon(m_pauseIcon);
701 }
702
703 void Monitor::slotLoopZone()
704 {
705     if (render == NULL) return;
706     activateMonitor();
707     QPoint p = m_ruler->zone();
708     render->loopZone(GenTime(p.x(), m_monitorManager->timecode().fps()), GenTime(p.y(), m_monitorManager->timecode().fps()));
709     m_playAction->setChecked(true);
710     m_playAction->setIcon(m_pauseIcon);
711 }
712
713 void Monitor::slotSetXml(DocClipBase *clip, QPoint zone, const int position)
714 {
715     if (render == NULL) return;
716     if (clip == NULL && m_currentClip != NULL) {
717         m_currentClip = NULL;
718         m_length = -1;
719         render->setProducer(NULL, -1);
720         return;
721     }
722     if (m_currentClip != NULL) activateMonitor();
723     if (clip != m_currentClip) {
724         m_currentClip = clip;
725         updateMarkers(clip);
726         if (render->setProducer(clip->producer(), position) == -1) {
727             // MLT CONSUMER is broken
728             kDebug(QtWarningMsg) << "ERROR, Cannot start monitor";
729         }
730     } else if (position != -1) render->seek(GenTime(position, m_monitorManager->timecode().fps()));
731     if (!zone.isNull()) {
732         m_ruler->setZone(zone.x(), zone.y());
733         render->seek(GenTime(zone.x(), m_monitorManager->timecode().fps()));
734     }
735 }
736
737 void Monitor::slotOpenFile(const QString &file)
738 {
739     if (render == NULL) return;
740     activateMonitor();
741     QDomDocument doc;
742     QDomElement mlt = doc.createElement("mlt");
743     doc.appendChild(mlt);
744     QDomElement prod = doc.createElement("producer");
745     mlt.appendChild(prod);
746     prod.setAttribute("mlt_service", "avformat");
747     prod.setAttribute("resource", file);
748     render->setSceneList(doc, 0);
749 }
750
751 void Monitor::slotSaveZone()
752 {
753     if (render == NULL) return;
754     emit saveZone(render, m_ruler->zone());
755
756     //render->setSceneList(doc, 0);
757 }
758
759 void Monitor::resetProfile(const QString profile)
760 {
761     if (render == NULL) return;
762     render->resetProfile(profile);
763 }
764
765 void Monitor::saveSceneList(QString path, QDomElement info)
766 {
767     if (render == NULL) return;
768     render->saveSceneList(path, info);
769 }
770
771 const QString Monitor::sceneList()
772 {
773     if (render == NULL) return QString();
774     return render->sceneList();
775 }
776
777 void Monitor::setClipZone(QPoint pos)
778 {
779     if (m_currentClip == NULL) return;
780     m_currentClip->setZone(pos);
781 }
782
783 void Monitor::slotSwitchDropFrames(bool show)
784 {
785     render->setDropFrames(show);
786 }
787
788 void Monitor::slotSwitchMonitorInfo(bool show)
789 {
790     KdenliveSettings::setDisplayMonitorInfo(show);
791     if (show) {
792         if (m_overlay) return;
793 #ifndef Q_WS_MAC
794         m_overlay = new Overlay(m_monitorRefresh);
795         m_overlay->raise();
796         m_overlay->setHidden(true);
797 #else
798         m_overlay = new Overlay(m_glWidget);
799 #endif
800     } else {
801         delete m_overlay;
802         m_overlay = NULL;
803     }
804 }
805
806 void Monitor::updateTimecodeFormat()
807 {
808     m_timePos->slotUpdateTimeCodeFormat();
809 }
810
811 QStringList Monitor::getZoneInfo() const
812 {
813     QStringList result;
814     if (m_currentClip == NULL) return result;
815     result << m_currentClip->getId();
816     QPoint zone = m_ruler->zone();
817     result << QString::number(zone.x()) << QString::number(zone.y());
818     return result;
819 }
820
821 MonitorRefresh::MonitorRefresh(QWidget* parent) : \
822         QWidget(parent),
823         m_renderer(NULL)
824 {
825     setAttribute(Qt::WA_PaintOnScreen);
826     setAttribute(Qt::WA_OpaquePaintEvent);
827     //setAttribute(Qt::WA_NoSystemBackground);
828 }
829
830 void MonitorRefresh::setRenderer(Render* render)
831 {
832     m_renderer = render;
833 }
834
835 void MonitorRefresh::paintEvent(QPaintEvent * /*event*/)
836 {
837     if (m_renderer) m_renderer->doRefresh();
838 }
839
840 Overlay::Overlay(QWidget* parent) :
841         QLabel(parent)
842 {
843     setAttribute(Qt::WA_TransparentForMouseEvents);
844     //setAttribute(Qt::WA_OpaquePaintEvent);
845     //setAttribute(Qt::WA_NoSystemBackground);
846     setAutoFillBackground(true);
847     setBackgroundRole(QPalette::Base);
848 }
849
850 void Overlay::setOverlayText(const QString &text, bool isZone)
851 {
852     setHidden(true);
853     m_isZone = isZone;
854     QPalette p;
855     p.setColor(QPalette::Text, Qt::white);
856     if (m_isZone) p.setColor(QPalette::Base, QColor(200, 0, 0));
857     else p.setColor(QPalette::Base, QColor(0, 0, 200));
858     setPalette(p);
859     setText(' ' + text + ' ');
860     setHidden(false);
861     update();
862 }
863
864 #include "monitor.moc"