]> git.sesse.net Git - kdenlive/blob - src/stopmotion/stopmotion.cpp
* Add preliminary support for Blackmagic HDMI capture card
[kdenlive] / src / stopmotion / stopmotion.cpp
1 /***************************************************************************
2                           stopmotion.cpp  -  description
3                              -------------------
4     begin                : Feb 28 2008
5     copyright            : (C) 2010 by Jean-Baptiste Mardelle
6     email                : jb@kdenlive.org
7  ***************************************************************************/
8
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17
18 #include "stopmotion.h"
19 #include "../blackmagic/devices.h"
20 #include "../slideshowclip.h"
21 #include "kdenlivesettings.h"
22
23
24 #include <KDebug>
25 #include <KGlobalSettings>
26 #include <KFileDialog>
27 #include <KStandardDirs>
28 #include <KMessageBox>
29 #include <kdeversion.h>
30 #include <KNotification>
31
32 #include <QComboBox>
33 #include <QVBoxLayout>
34 #include <QTimer>
35 #include <QAction>
36
37 StopmotionWidget::StopmotionWidget(KUrl projectFolder, QWidget *parent) :
38         m_projectFolder(projectFolder)
39         , QDialog(parent)
40         , Ui::Stopmotion_UI()
41         , m_sequenceFrame(0)
42 {
43     setupUi(this);
44     setWindowTitle(i18n("Stop Motion Capture"));
45     setFont(KGlobalSettings::toolBarFont());
46
47     live_button->setIcon(KIcon("camera-photo"));
48     frameoverlay_button->setIcon(KIcon("edit-paste"));
49     m_captureAction = new QAction(KIcon("media-record"), i18n("Capture frame"), this);
50     m_captureAction->setShortcut(QKeySequence(Qt::Key_Space));
51     connect(m_captureAction, SIGNAL(triggered()), this, SLOT(slotCaptureFrame()));
52     capture_button->setDefaultAction(m_captureAction);
53     
54     preview_button->setIcon(KIcon("media-playback-start"));
55     removelast_button->setIcon(KIcon("edit-delete"));
56
57     capture_button->setEnabled(false);
58     frameoverlay_button->setEnabled(false);
59     removelast_button->setEnabled(false);
60
61 #if KDE_IS_VERSION(4,4,0)
62     sequence_name->setClickMessage(i18n("Enter sequence name..."));
63 #endif
64
65     connect(sequence_name, SIGNAL(textChanged(const QString &)), this, SLOT(sequenceNameChanged(const QString &)));
66     BMInterface::getBlackMagicDeviceList(capture_device, NULL);
67     QVBoxLayout *lay = new QVBoxLayout;
68     m_bmCapture = new CaptureHandler(lay);
69     video_preview->setLayout(lay);
70     live_button->setChecked(false);
71     frameoverlay_button->setChecked(false);
72     button_addsequence->setEnabled(false);
73     connect(live_button, SIGNAL(clicked(bool)), this, SLOT(slotLive(bool)));
74     connect(frameoverlay_button, SIGNAL(clicked(bool)), this, SLOT(slotShowOverlay(bool)));
75     connect(frame_number, SIGNAL(valueChanged(int)), this, SLOT(slotShowFrame(int)));
76     connect(button_addsequence, SIGNAL(clicked(bool)), this, SLOT(slotAddSequence()));
77 }
78
79 StopmotionWidget::~StopmotionWidget()
80 {
81     m_bmCapture->stopPreview();
82 }
83
84 void StopmotionWidget::slotLive(bool isOn)
85 {
86     if (isOn) {
87         m_bmCapture->startPreview(KdenliveSettings::hdmicapturedevice(), KdenliveSettings::hdmicapturemode());
88         capture_button->setEnabled(sequence_name->text().isEmpty() == false);
89     }
90     else {
91         m_bmCapture->stopPreview();
92         capture_button->setEnabled(false);
93     }
94 }
95
96 void StopmotionWidget::slotShowOverlay(bool isOn)
97 {
98     if (isOn) {
99         if (live_button->isChecked() && m_sequenceFrame > 0) {
100             slotUpdateOverlay();
101         }
102     }
103     else {
104         m_bmCapture->hideOverlay();
105     }
106 }
107
108 void StopmotionWidget::slotUpdateOverlay()
109 {
110     QString path = getPathForFrame(m_sequenceFrame - 1);
111     if (!QFile::exists(path)) return;
112     QImage img(path);
113     if (img.isNull()) {
114         QTimer::singleShot(1000, this, SLOT(slotUpdateOverlay()));
115         return;
116     }
117     m_bmCapture->showOverlay(img);
118 }
119
120 void StopmotionWidget::sequenceNameChanged(const QString &name)
121 {
122     if (name.isEmpty()) {
123         button_addsequence->setEnabled(false);
124         capture_button->setEnabled(false);
125         frame_number->blockSignals(true);
126         frame_number->setValue(m_sequenceFrame);
127         frame_number->blockSignals(false);
128         frameoverlay_button->setEnabled(false);
129         removelast_button->setEnabled(false);
130     }
131     else {
132         // Check if we are editing an existing sequence
133         int count = 0;
134         QString pattern = SlideshowClip::selectedPath(getPathForFrame(0, sequence_name->text()), false, QString(), &count);
135         m_sequenceFrame = count;
136         if (count > 0) {
137             m_sequenceName = sequence_name->text();
138             button_addsequence->setEnabled(true);
139             frameoverlay_button->setEnabled(true);
140         }
141         else {
142             button_addsequence->setEnabled(false);
143             frameoverlay_button->setEnabled(false);
144         }
145         frame_number->setRange(0, m_sequenceFrame);
146         frame_number->blockSignals(true);
147         frame_number->setValue(m_sequenceFrame);
148         frame_number->blockSignals(false);
149         capture_button->setEnabled(true);
150     }
151 }
152
153 void StopmotionWidget::slotCaptureFrame()
154 {
155     if (m_sequenceName != sequence_name->text()) {
156         m_sequenceName = sequence_name->text();
157         m_sequenceFrame = 0;
158     }
159     
160     m_bmCapture->captureFrame(getPathForFrame(m_sequenceFrame));
161     KNotification::event("FrameCaptured");
162     frameoverlay_button->setEnabled(true);
163     m_sequenceFrame++;
164     frame_number->setRange(0, m_sequenceFrame);
165     frame_number->blockSignals(true);
166     frame_number->setValue(m_sequenceFrame);
167     frame_number->blockSignals(false);
168     button_addsequence->setEnabled(true);
169     if (frameoverlay_button->isChecked()) QTimer::singleShot(1000, this, SLOT(slotUpdateOverlay()));
170 }
171
172 QString StopmotionWidget::getPathForFrame(int ix, QString seqName)
173 {
174     if (seqName.isEmpty()) seqName = m_sequenceName;
175     return m_projectFolder.path(KUrl::AddTrailingSlash) + seqName + "_" + QString::number(ix).rightJustified(4, '0', false) + ".png";
176 }
177
178 void StopmotionWidget::slotShowFrame(int ix)
179 {
180     if (m_sequenceFrame == 0) {
181         //there are no images in sequence
182         return;
183     }
184     frameoverlay_button->blockSignals(true);
185     frameoverlay_button->setChecked(false);
186     frameoverlay_button->blockSignals(false);
187     if (ix < m_sequenceFrame) {
188         // Show previous frame
189         QImage img(getPathForFrame(ix));
190         capture_button->setEnabled(false);
191         if (!img.isNull()) m_bmCapture->showOverlay(img, false);
192     }
193     else {
194         m_bmCapture->hideOverlay();
195         capture_button->setEnabled(true);
196     }
197     
198 }
199
200 void StopmotionWidget::slotAddSequence()
201 {
202     emit addOrUpdateSequence(getPathForFrame(0));
203 }