]> git.sesse.net Git - kdenlive/blob - src/recmonitor.cpp
NEW: Kdenlive can now create screencasts.
[kdenlive] / src / recmonitor.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 <QMouseEvent>
22 #include <QStylePainter>
23 #include <QMenu>
24 #include <QToolButton>
25 #include <QFile>
26 #include <QDir>
27 #include <QDesktopWidget>
28
29 #include <KDebug>
30 #include <KLocale>
31 #include <KStandardDirs>
32 #include <KComboBox>
33
34 #include "gentime.h"
35 #include "kdenlivesettings.h"
36 #include "recmonitor.h"
37
38 RecMonitor::RecMonitor(QString name, QWidget *parent)
39         : QWidget(parent), m_name(name), m_isActive(false), m_isCapturing(false), m_isPlaying(false) {
40     ui.setupUi(this);
41
42     ui.video_frame->setAttribute(Qt::WA_PaintOnScreen);
43     ui.device_selector->setCurrentIndex(KdenliveSettings::defaultcapture());
44     connect(ui.device_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(slotVideoDeviceChanged(int)));
45
46
47
48     QToolBar *toolbar = new QToolBar(name, this);
49     QHBoxLayout *layout = new QHBoxLayout;
50
51     m_playIcon = KIcon("media-playback-start");
52     m_pauseIcon = KIcon("media-playback-pause");
53
54     m_discAction = toolbar->addAction(KIcon("network-connect"), i18n("Connect"));
55     connect(m_discAction, SIGNAL(triggered()), this, SLOT(slotDisconnect()));
56
57     m_rewAction = toolbar->addAction(KIcon("media-seek-backward"), i18n("Rewind"));
58     connect(m_rewAction, SIGNAL(triggered()), this, SLOT(slotRewind()));
59
60     m_playAction = toolbar->addAction(m_playIcon, i18n("Play"));
61     connect(m_playAction, SIGNAL(triggered()), this, SLOT(slotStartCapture()));
62
63     m_stopAction = toolbar->addAction(KIcon("media-playback-stop"), i18n("Stop"));
64     connect(m_stopAction, SIGNAL(triggered()), this, SLOT(slotStopCapture()));
65     m_stopAction->setEnabled(false);
66     m_fwdAction = toolbar->addAction(KIcon("media-seek-forward"), i18n("Forward"));
67     connect(m_fwdAction, SIGNAL(triggered()), this, SLOT(slotForward()));
68
69     m_recAction = toolbar->addAction(KIcon("media-record"), i18n("Record"));
70     connect(m_recAction, SIGNAL(triggered()), this, SLOT(slotRecord()));
71     m_recAction->setCheckable(true);
72
73     layout->addWidget(toolbar);
74     ui.control_frame_firewire->setLayout(layout);
75
76     slotVideoDeviceChanged(ui.device_selector->currentIndex());
77     displayProcess = new QProcess;
78     captureProcess = new QProcess;
79
80     connect(captureProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(slotProcessStatus(QProcess::ProcessState)));
81
82     QStringList env = QProcess::systemEnvironment();
83     env << "SDL_WINDOWID=" + QString::number(ui.video_frame->winId());
84     displayProcess->setEnvironment(env);
85
86     if (KdenliveSettings::video4capture().isEmpty()) {
87         QString captureCommand;
88         if (!KdenliveSettings::video4adevice().isEmpty()) captureCommand = "-f " + KdenliveSettings::video4aformat() + " -i " + KdenliveSettings::video4adevice();
89
90         captureCommand +=  " -f " + KdenliveSettings::video4vformat() + " -s " + KdenliveSettings::video4size() + " -r " + QString::number(KdenliveSettings::video4rate()) + " -i " + KdenliveSettings::video4vdevice() + " -f " + KdenliveSettings::video4vencoding();
91         KdenliveSettings::setVideo4capture(captureCommand);
92     }
93
94     if (KdenliveSettings::video4playback().isEmpty()) {
95         QString playbackCommand;
96         playbackCommand =  "-f " + KdenliveSettings::video4vencoding();
97         KdenliveSettings::setVideo4playback(playbackCommand);
98     }
99     kDebug() << "/////// BUILDING MONITOR, ID: " << ui.video_frame->winId();
100 }
101
102 QString RecMonitor::name() const {
103     return m_name;
104 }
105
106 void RecMonitor::slotVideoDeviceChanged(int ix) {
107         switch (ix) {
108                 case SCREENGRAB:
109                         m_discAction->setEnabled(false);
110                         m_rewAction->setEnabled(false);
111                         m_fwdAction->setEnabled(false);
112                         m_recAction->setEnabled(true);
113                         m_stopAction->setEnabled(false);
114                         m_playAction->setEnabled(false);
115                         break;
116                 case VIDEO4LINUX:
117                         m_discAction->setEnabled(false);
118                         m_rewAction->setEnabled(false);
119                         m_fwdAction->setEnabled(false);
120                         m_recAction->setEnabled(true);
121                         m_stopAction->setEnabled(false);
122                         m_playAction->setEnabled(true);
123                         break;
124                 default: // FIREWIRE
125                         m_discAction->setEnabled(true);
126                         m_recAction->setEnabled(false);
127                         m_stopAction->setEnabled(false);
128                         m_playAction->setEnabled(false);
129                         m_rewAction->setEnabled(false);
130                         m_fwdAction->setEnabled(false);
131                         break;
132     }
133 }
134
135 void RecMonitor::slotDisconnect() {
136     if (captureProcess->state() == QProcess::NotRunning) {
137         slotStartCapture(false);
138         m_discAction->setIcon(KIcon("network-disconnect"));
139         m_discAction->setText(i18n("Disonnect"));
140         m_recAction->setEnabled(true);
141         m_stopAction->setEnabled(true);
142         m_playAction->setEnabled(true);
143         m_rewAction->setEnabled(true);
144         m_fwdAction->setEnabled(true);
145     } else {
146         captureProcess->write("q", 1);
147         m_discAction->setIcon(KIcon("network-connect"));
148         m_discAction->setText(i18n("Connect"));
149         m_recAction->setEnabled(false);
150         m_stopAction->setEnabled(false);
151         m_playAction->setEnabled(false);
152         m_rewAction->setEnabled(false);
153         m_fwdAction->setEnabled(false);
154     }
155 }
156
157 void RecMonitor::slotRewind() {
158     captureProcess->write("a", 1);
159 }
160
161 void RecMonitor::slotForward() {
162     captureProcess->write("z", 1);
163 }
164
165 void RecMonitor::slotStopCapture() {
166     // stop capture
167         switch (ui.device_selector->currentIndex()) {
168     case FIREWIRE:
169         captureProcess->write("\e", 2);
170         m_playAction->setIcon(m_playIcon);
171         m_isPlaying = false;
172                 break;
173     case VIDEO4LINUX:
174         captureProcess->kill();
175         displayProcess->kill();
176                 if (m_isCapturing && ui.autoaddbox->isChecked()) emit addProjectClip(m_captureFile);
177                 break;
178     case SCREENGRAB:
179         captureProcess->kill();
180                 if (m_isCapturing && ui.autoaddbox->isChecked()) emit addProjectClip(m_captureFile);
181                 break;
182         default:
183                 break;
184         }
185 }
186
187 void RecMonitor::slotStartCapture(bool play) {
188
189     /*
190     *captureProcess<<"dvgrab";
191
192     bool isHdv = false;
193
194     switch (m_recPanel->capture_format->currentItem()){
195         case 0:
196       *captureProcess<<"--format"<<"dv1";
197      break;
198         case 1:
199       *captureProcess<<"--format"<<"dv2";
200      break;
201         case 3:
202       *captureProcess<<"--format"<<"hdv";
203      isHdv = true;
204      break;
205         default:
206             *captureProcess<<"--format"<<"raw";
207      break;
208     }
209
210     if (KdenliveSettings::autosplit()) *captureProcess<<"--autosplit";
211     if (KdenliveSettings::timestamp()) *captureProcess<<"--timestamp";
212     *captureProcess<<"-i"<<"capture"<<"-";*/
213
214     /*
215         QStringList captureArgs;
216         captureArgs<<"--format"<<"hdv"<<"-i"<<"capture"<<"-";
217         QStringList displayArgs;
218
219         displayArgs<<"-f"<<"mpegts"<<"-x"<<QString::number(ui.video_frame->width())<<"-y"<<QString::number(ui.video_frame->height())<<"-";
220
221         captureProcess->setStandardOutputProcess(displayProcess);
222         ui.video_frame->setScaledContents(false);
223         captureProcess->start("dvgrab",captureArgs);
224         displayProcess->start("ffplay",  displayArgs);*/
225
226
227     if (captureProcess->state() != QProcess::NotRunning) {
228         if (ui.device_selector->currentIndex() == FIREWIRE) {
229             if (m_isPlaying) {
230                 captureProcess->write("k", 1);
231                 //captureProcess->write("\e", 2);
232                 m_playAction->setIcon(m_playIcon);
233                 m_isPlaying = false;
234             } else {
235                 captureProcess->write("p", 1);
236                 m_playAction->setIcon(m_pauseIcon);
237                 m_isPlaying = true;
238             }
239         }
240         return;
241     }
242     m_captureArgs.clear();
243     m_displayArgs.clear();
244     m_isPlaying = false;
245
246         switch (ui.device_selector->currentIndex()) {
247     case FIREWIRE:
248         m_captureArgs << "--format" << "hdv" << "-i" << "capture" << "-";
249         m_displayArgs << "-f" << "mpegts" << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-";
250                 captureProcess->setStandardOutputProcess(displayProcess);
251         captureProcess->setWorkingDirectory(KdenliveSettings::capturefolder());
252         captureProcess->start("dvgrab", m_captureArgs);
253         if (play) captureProcess->write(" ", 1);
254         m_discAction->setEnabled(true);
255                 break;
256     case VIDEO4LINUX:
257         m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << "-";
258         m_displayArgs << KdenliveSettings::video4playback().simplified().split(' ') << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-";
259                 captureProcess->setStandardOutputProcess(displayProcess);
260                 captureProcess->start("ffmpeg", m_captureArgs);
261                 break;
262         default:
263                 break;
264     }
265
266     if (ui.device_selector->currentIndex() != SCREENGRAB) {
267                 displayProcess->start("ffplay", m_displayArgs);
268                 ui.video_frame->setText(i18n("Initialising..."));
269         } else {
270                 // do something when starting screen grab
271         }
272 }
273
274 void RecMonitor::slotRecord() {
275     if (captureProcess->state() == QProcess::NotRunning && ui.device_selector->currentIndex() == FIREWIRE) {
276         slotStartCapture();
277     }
278     if (m_isCapturing) {
279                 switch (ui.device_selector->currentIndex()) {
280                 case FIREWIRE:
281             captureProcess->write("\e", 2);
282             m_playAction->setIcon(m_playIcon);
283             m_isCapturing = false;
284             m_isPlaying = false;
285             m_recAction->setChecked(false);
286                         break;
287         case VIDEO4LINUX:
288             slotStopCapture();
289             m_isCapturing = false;
290             QTimer::singleShot(1000, this, SLOT(slotStartCapture()));
291                         break;
292         case SCREENGRAB:
293             slotStopCapture();
294             m_isCapturing = false;
295                         break;
296         }
297         return;
298     } else if (ui.device_selector->currentIndex() == FIREWIRE) {
299         m_isCapturing = true;
300         captureProcess->write("c\n", 3);
301         return;
302     }
303     if (captureProcess->state() == QProcess::NotRunning) {
304         m_recAction->setChecked(true);
305                 QString extension = "mpg";
306                 if (ui.device_selector->currentIndex() == SCREENGRAB) extension = KdenliveSettings::screengrabextension();
307         QString path = KdenliveSettings::capturefolder() + "/capture0000." + extension;
308         int i = 1;
309         while (QFile::exists(path)) {
310             QString num = QString::number(i).rightJustified(4, '0', false);
311             path = KdenliveSettings::capturefolder() + "/capture" + num + "." + extension;
312             i++;
313         }
314
315         m_captureFile = KUrl(path);
316
317         m_captureArgs.clear();
318         m_displayArgs.clear();
319                 QString args;
320
321                 switch (ui.device_selector->currentIndex()) {
322                 case FIREWIRE:
323             m_captureArgs << "--format" << "hdv" << "-i" << "capture" << "-";
324             m_displayArgs << "-f" << "mpegts" << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-";
325                         captureProcess->setStandardOutputProcess(displayProcess);
326                         captureProcess->start("dvgrab", m_captureArgs);
327                         break;
328                 case VIDEO4LINUX:
329             m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << "-y" << m_captureFile.path() << "-f" << KdenliveSettings::video4vencoding() << "-";
330             m_displayArgs << KdenliveSettings::video4playback().simplified().split(' ') << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-";
331                         captureProcess->setStandardOutputProcess(displayProcess);
332                         captureProcess->start("ffmpeg", m_captureArgs);
333                         break;
334                 case SCREENGRAB:
335                         if (KdenliveSettings::fullscreengrab()) {
336                                 const QRect rect = QApplication::desktop()->screenGeometry();
337                                 args = KdenliveSettings::screengrabcapture().replace("%size", QString::number(rect.width()) + "x" + QString::number(rect.height())).replace("%offset", QString());
338                                 kDebug()<<"// capture params: "<<args;
339                                 m_captureArgs << args.simplified().split(' ') <<KdenliveSettings::screengrabencoding().simplified().split(' ')<<m_captureFile.path();
340                                 ui.video_frame->setText(i18n("Capturing..."));
341                                 m_isCapturing = true;
342                                 captureProcess->start("ffmpeg", m_captureArgs);
343                         }
344                         else {
345                                 ui.video_frame->setText(i18n("Select region..."));
346                                 rgnGrab = new RegionGrabber();
347                                 connect( rgnGrab, SIGNAL( regionGrabbed( const QRect&) ), SLOT( slotStartGrab( const QRect & ) ) );
348                         }
349                         break;
350                 default:
351                         break;
352                 }
353
354         //ui.video_frame->setScaledContents(false);
355         if (ui.device_selector->currentIndex() != SCREENGRAB) {
356                         m_isCapturing = true;
357                         displayProcess->start("ffplay", m_displayArgs);
358                         ui.video_frame->setText(i18n("Initialising..."));
359                 }
360     } else {
361         // stop capture
362         displayProcess->kill();
363         captureProcess->kill();
364         QTimer::singleShot(1000, this, SLOT(slotRecord()));
365     }
366 }
367
368 void RecMonitor::slotStartGrab(const QRect &rect)
369 {
370         rgnGrab->deleteLater();
371         QApplication::restoreOverrideCursor();
372         show();
373         if (rect.isNull()) return;
374         int width = rect.width();
375         int height = rect.height();
376         if (width % 2 != 0) width--;
377         if (height % 2 != 0) height--;
378         QString args = KdenliveSettings::screengrabcapture().replace("%size", QString::number(width) + "x" + QString::number(height)).replace("%offset", "+" + QString::number(rect.x()) + "," + QString::number(rect.y()));
379         kDebug()<<"// capture params: "<<args;
380         m_captureArgs << args.simplified().split(' ') <<KdenliveSettings::screengrabencoding().simplified().split(' ')<<m_captureFile.path();
381         m_isCapturing = true;
382         ui.video_frame->setText(i18n("Capturing..."));
383         captureProcess->start("ffmpeg", m_captureArgs);
384 }
385
386 void RecMonitor::slotProcessStatus(QProcess::ProcessState status) {
387     if (status == QProcess::NotRunning) {
388         m_isCapturing = false;
389         m_isPlaying = false;
390         m_playAction->setIcon(m_playIcon);
391         m_recAction->setChecked(false);
392         m_stopAction->setEnabled(false);
393         ui.device_selector->setEnabled(true);
394                 /*if (captureProcess && captureProcess->exitStatus() == QProcess::CrashExit) {
395                         ui.video_frame->setText(i18n("Capture crashed, please check your parameters"));
396                 }
397         else*/ ui.video_frame->setText(i18n("Not connected"));
398     } else {
399         m_stopAction->setEnabled(true);
400         ui.device_selector->setEnabled(false);
401     }
402 }
403
404 // virtual
405 void RecMonitor::mousePressEvent(QMouseEvent * event) {
406     slotPlay();
407 }
408
409 void RecMonitor::activateRecMonitor() {
410     //if (!m_isActive) m_monitorManager->activateRecMonitor(m_name);
411 }
412
413 void RecMonitor::stop() {
414     m_isActive = false;
415
416 }
417
418 void RecMonitor::start() {
419     m_isActive = true;
420
421 }
422
423 void RecMonitor::refreshRecMonitor(bool visible) {
424     if (visible) {
425         //if (!m_isActive) m_monitorManager->activateRecMonitor(m_name);
426
427     }
428 }
429
430 void RecMonitor::slotPlay() {
431
432     //if (!m_isActive) m_monitorManager->activateRecMonitor(m_name);
433
434 }
435
436
437 #include "recmonitor.moc"