From 6e9157080b18e4f0a967ab0c3d3a72d01936678c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Sun, 16 Mar 2008 00:25:31 +0000 Subject: [PATCH] Capture monitor with video4linux support! svn path=/branches/KDE4/; revision=2061 --- src/CMakeLists.txt | 4 + src/kdenlivesettings.kcfg | 52 +++++++ src/kdenlivesettingsdialog.cpp | 10 +- src/kdenlivesettingsdialog.h | 3 + src/mainwindow.cpp | 13 ++ src/mainwindow.h | 5 + src/projectlist.h | 2 +- src/recmonitor.cpp | 221 ++++++++++++++++++++++++++++++ src/recmonitor.h | 82 ++++++++++++ src/widgets/configcapture_ui.ui | 231 ++++++++++++++++++++++++++++++++ src/widgets/recmonitor_ui.ui | 93 +++++++++++++ 11 files changed, 713 insertions(+), 3 deletions(-) create mode 100644 src/recmonitor.cpp create mode 100644 src/recmonitor.h create mode 100644 src/widgets/configcapture_ui.ui create mode 100644 src/widgets/recmonitor_ui.ui diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8c5d9588..d8e437eb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,13 +19,16 @@ ${NEPOMUK_LIBRARIES} ) + kde4_add_ui_files(kdenlive_UI widgets/timeline_ui.ui widgets/monitor_ui.ui + widgets/recmonitor_ui.ui widgets/colorclip_ui.ui widgets/configmisc_ui.ui widgets/configenv_ui.ui widgets/configdisplay_ui.ui + widgets/configcapture_ui.ui widgets/effectlist_ui.ui widgets/effectstack_ui.ui widgets/profiledialog_ui.ui @@ -89,6 +92,7 @@ set(kdenlive_SRCS renderwidget.cpp abstractclipitem.cpp transitionsettings.cpp + recmonitor.cpp ) kde4_add_kcfg_files(kdenlive_SRCS GENERATE_MOC kdenlivesettings.kcfgc ) diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg index c3580d33..6760855a 100644 --- a/src/kdenlivesettings.kcfg +++ b/src/kdenlivesettings.kcfg @@ -54,6 +54,58 @@ + + + + 0 + + + + + $HOME + + + + + 0 + + + + + m4v + + + + + /dev/video0 + + + + + oss + + + + + /dev/dsp + + + + + 320 + + + + + 240 + + + + + 15 + + + diff --git a/src/kdenlivesettingsdialog.cpp b/src/kdenlivesettingsdialog.cpp index 4e1871d9..18ee2947 100644 --- a/src/kdenlivesettingsdialog.cpp +++ b/src/kdenlivesettingsdialog.cpp @@ -30,7 +30,7 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(QWidget * parent): KConfigDialog( QWidget *p1 = new QWidget; m_configMisc.setupUi(p1); - page1 = addPage(p1, i18n("Misc"), "misc"); + page1 = addPage(p1, i18n("Misc"), "configure"); QWidget *p3 = new QWidget; m_configDisplay.setupUi(p3); @@ -43,7 +43,13 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(QWidget * parent): KConfigDialog( m_configEnv.rendererpathurl->lineEdit()->setObjectName("kcfg_rendererpath"); m_configEnv.tmppathurl->setMode(KFile::Directory); m_configEnv.tmppathurl->lineEdit()->setObjectName("kcfg_currenttmpfolder"); - page2 = addPage(p2, i18n("Environnement"), "env"); + page2 = addPage(p2, i18n("Environnement"), "terminal"); + + QWidget *p4 = new QWidget; + m_configCapture.setupUi(p4); + m_configCapture.capturefolderurl->setMode(KFile::Directory); + m_configCapture.capturefolderurl->lineEdit()->setObjectName("kcfg_capturefolder"); + page4 = addPage(p4, i18n("Capture"), "audio-card"); QStringList profilesNames = ProfilesDialog::getProfileNames(); m_configMisc.profiles_list->addItems(profilesNames); diff --git a/src/kdenlivesettingsdialog.h b/src/kdenlivesettingsdialog.h index 44bc590e..9f637155 100644 --- a/src/kdenlivesettingsdialog.h +++ b/src/kdenlivesettingsdialog.h @@ -28,6 +28,7 @@ #include "ui_configmisc_ui.h" #include "ui_configenv_ui.h" #include "ui_configdisplay_ui.h" +#include "ui_configcapture_ui.h" class KdenliveSettingsDialog : public KConfigDialog { Q_OBJECT @@ -46,9 +47,11 @@ private: KPageWidgetItem *page1; KPageWidgetItem *page2; KPageWidgetItem *page3; + KPageWidgetItem *page4; Ui::ConfigEnv_UI m_configEnv; Ui::ConfigMisc_UI m_configMisc; Ui::ConfigDisplay_UI m_configDisplay; + Ui::ConfigCapture_UI m_configCapture; QStringList m_mltProfilesList; QStringList m_customProfilesList; bool m_isCustomProfile; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9b041f45..8069ed9a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -126,6 +126,14 @@ MainWindow::MainWindow(QWidget *parent) projectMonitorDock->setWidget(m_projectMonitor); addDockWidget(Qt::TopDockWidgetArea, projectMonitorDock); + recMonitorDock = new QDockWidget(i18n("Record Monitor"), this); + recMonitorDock->setObjectName("record_monitor"); + m_recMonitor = new RecMonitor("record", this); + recMonitorDock->setWidget(m_recMonitor); + addDockWidget(Qt::TopDockWidgetArea, recMonitorDock); + + connect(m_recMonitor, SIGNAL(addProjectClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl))); + undoViewDock = new QDockWidget(i18n("Undo History"), this); undoViewDock->setObjectName("undo_history"); m_undoView = new QUndoView(this); @@ -726,6 +734,11 @@ void MainWindow::slotDeleteTimelineClip() { } } +void MainWindow::slotAddProjectClip(KUrl url) { + if (m_activeDocument) + m_activeDocument->slotAddClipFile(url, QString()); +} + void MainWindow::slotAddVideoEffect(QAction *result) { if (!result) return; QDomElement effect = m_videoEffects.getEffectByName(result->data().toString()); diff --git a/src/mainwindow.h b/src/mainwindow.h index cdf1c20a..d8cf446c 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -36,6 +36,7 @@ #include "projectlist.h" #include "monitor.h" +#include "recmonitor.h" #include "monitormanager.h" #include "kdenlivedoc.h" #include "trackview.h" @@ -86,6 +87,9 @@ private: QDockWidget *projectMonitorDock; Monitor *m_projectMonitor; + QDockWidget *recMonitorDock; + RecMonitor *m_recMonitor; + QDockWidget *undoViewDock; QUndoView *m_undoView; QUndoGroup *m_commandStack; @@ -148,6 +152,7 @@ private slots: void slotAddVideoEffect(QAction *result); void slotAddAudioEffect(QAction *result); void slotAddCustomEffect(QAction *result); + void slotAddProjectClip(KUrl url); }; #endif diff --git a/src/projectlist.h b/src/projectlist.h index fe3e6c0b..64d62887 100644 --- a/src/projectlist.h +++ b/src/projectlist.h @@ -131,7 +131,7 @@ private: KdenliveDoc *m_doc; private slots: - void slotAddClip(QUrl givenUrl = QUrl(), const QString &group = QString::null); + void slotAddClip(QUrl givenUrl = QUrl(), const QString &group = QString()); void slotRemoveClip(); void slotEditClip(); void slotClipSelected(); diff --git a/src/recmonitor.cpp b/src/recmonitor.cpp new file mode 100644 index 00000000..ad3d5dac --- /dev/null +++ b/src/recmonitor.cpp @@ -0,0 +1,221 @@ +/*************************************************************************** + * Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org) * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "gentime.h" +#include "kdenlivesettings.h" +#include "recmonitor.h" + +RecMonitor::RecMonitor(QString name, QWidget *parent) + : QWidget(parent), m_name(name), m_isActive(false), m_isCapturing(false) { + ui.setupUi(this); + + ui.video_frame->setAttribute(Qt::WA_PaintOnScreen); + connect(ui.buttonConnect, SIGNAL(clicked()), this, SLOT(slotSwitchCapture())); + connect(ui.buttonRec, SIGNAL(clicked()), this, SLOT(slotCapture())); + ui.buttonRec->setCheckable(true); + + displayProcess = new QProcess; + captureProcess = new QProcess; + + connect(displayProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(slotProcessStatus(QProcess::ProcessState))); + + QStringList env = QProcess::systemEnvironment(); + env << "SDL_WINDOWID=" + QString::number(ui.video_frame->winId()); + displayProcess->setEnvironment(env); + + kDebug() << "/////// BUILDING MONITOR, ID: " << ui.video_frame->winId(); +} + +QString RecMonitor::name() const { + return m_name; +} + +void RecMonitor::slotSwitchCapture() { + + /* + *captureProcess<<"dvgrab"; + + bool isHdv = false; + + switch (m_recPanel->capture_format->currentItem()){ + case 0: + *captureProcess<<"--format"<<"dv1"; + break; + case 1: + *captureProcess<<"--format"<<"dv2"; + break; + case 3: + *captureProcess<<"--format"<<"hdv"; + isHdv = true; + break; + default: + *captureProcess<<"--format"<<"raw"; + break; + } + + if (KdenliveSettings::autosplit()) *captureProcess<<"--autosplit"; + if (KdenliveSettings::timestamp()) *captureProcess<<"--timestamp"; + *captureProcess<<"-i"<<"capture"<<"-";*/ + + /* + QStringList captureArgs; + captureArgs<<"--format"<<"hdv"<<"-i"<<"capture"<<"-"; + QStringList displayArgs; + + displayArgs<<"-f"<<"mpegts"<<"-x"<width())<<"-y"<height())<<"-"; + + captureProcess->setStandardOutputProcess(displayProcess); + ui.video_frame->setScaledContents(false); + captureProcess->start("dvgrab",captureArgs); + displayProcess->start("ffplay", displayArgs);*/ + ui.buttonRec->setChecked(false); + m_isCapturing = false; + if (captureProcess->state() == QProcess::Starting) return; + else if (captureProcess->state() == QProcess::NotRunning) { + m_captureArgs.clear(); + m_displayArgs.clear(); + + if (KdenliveSettings::defaultcapture() == 0) { + m_captureArgs << "--format" << "hdv" << "-i" << "capture" << "-"; + m_displayArgs << "-f" << "mpegts" << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-"; + } else { + if (!KdenliveSettings::video4adevice().isEmpty()) m_captureArgs << "-f" << KdenliveSettings::video4aformat() << "-i" << KdenliveSettings::video4adevice(); + m_captureArgs << "-f" << "video4linux2" << "-s" << QString::number(KdenliveSettings::video4width()) + "x" + QString::number(KdenliveSettings::video4height()) << "-r" << QString::number(KdenliveSettings::video4rate()) << "-i" << KdenliveSettings::video4vdevice() << "-f" << KdenliveSettings::video4vformat() << "-"; + m_displayArgs << "-f" << KdenliveSettings::video4vformat() << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-"; + } + + captureProcess->setStandardOutputProcess(displayProcess); + if (KdenliveSettings::defaultcapture() == 0) captureProcess->start("dvgrab", m_captureArgs); + else captureProcess->start("ffmpeg", m_captureArgs); + displayProcess->start("ffplay", m_displayArgs); + ui.video_frame->setText(i18n("Initialising...")); + } else { + // stop capture + displayProcess->kill(); + captureProcess->kill(); + } +} + +void RecMonitor::slotCapture() { + + if (captureProcess->state() == QProcess::NotRunning) { + ui.buttonConnect->setEnabled(false); + + QString path = KdenliveSettings::capturefolder() + "/capture0000.mpg"; + int i = 1; + while (QFile::exists(path)) { + QString num = QString::number(i); + if (i < 10) num.prepend("000"); + else if (i < 100) num.prepend("00"); + else num.prepend("0"); + path = KdenliveSettings::capturefolder() + "/capture" + num + ".mpg"; + } + + m_captureFile = KUrl(path); + + m_isCapturing = true; + m_captureArgs.clear(); + m_displayArgs.clear(); + + if (KdenliveSettings::defaultcapture() == 0) { + m_captureArgs << "--format" << "hdv" << "-i" << "capture" << "-"; + m_displayArgs << "-f" << "mpegts" << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-"; + } else { + if (!KdenliveSettings::video4adevice().isEmpty()) m_captureArgs << "-f" << KdenliveSettings::video4aformat() << "-i" << KdenliveSettings::video4adevice(); + m_captureArgs << "-f" << "video4linux2" << "-s" << QString::number(KdenliveSettings::video4width()) + "x" + QString::number(KdenliveSettings::video4height()) << "-r" << QString::number(KdenliveSettings::video4rate()) << "-i" << KdenliveSettings::video4vdevice() << "-y" << "-f" << KdenliveSettings::video4vformat() << m_captureFile.path() << "-f" << KdenliveSettings::video4vformat() << "-"; + m_displayArgs << "-f" << KdenliveSettings::video4vformat() << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-"; + } + + captureProcess->setStandardOutputProcess(displayProcess); + //ui.video_frame->setScaledContents(false); + if (KdenliveSettings::defaultcapture() == 0) captureProcess->start("dvgrab", m_captureArgs); + else captureProcess->start("ffmpeg", m_captureArgs); + displayProcess->start("ffplay", m_displayArgs); + ui.video_frame->setText(i18n("Initialising...")); + ui.buttonRec->setChecked(true); + } else { + // stop capture + displayProcess->kill(); + captureProcess->kill(); + if (m_isCapturing) { + QTimer::singleShot(1000, this, SLOT(slotSwitchCapture())); + ui.buttonRec->setChecked(false); + ui.buttonConnect->setEnabled(true); + if (ui.autoaddbox->isChecked()) emit addProjectClip(m_captureFile); + } else { + QTimer::singleShot(1000, this, SLOT(slotCapture())); + ui.buttonRec->setChecked(true); + } + } +} + +void RecMonitor::slotProcessStatus(QProcess::ProcessState status) { + if (status == QProcess::Starting) ui.buttonConnect->setText(i18n("Starting...")); + else if (status == QProcess::NotRunning) { + ui.buttonConnect->setText(i18n("Connect")); + ui.video_frame->setText(i18n("Not connected")); + } else ui.buttonConnect->setText(i18n("Disconnect")); +} + +// virtual +void RecMonitor::mousePressEvent(QMouseEvent * event) { + slotPlay(); +} + +void RecMonitor::activateRecMonitor() { + //if (!m_isActive) m_monitorManager->activateRecMonitor(m_name); +} + +void RecMonitor::stop() { + m_isActive = false; + +} + +void RecMonitor::start() { + m_isActive = true; + +} + +void RecMonitor::refreshRecMonitor(bool visible) { + if (visible) { + //if (!m_isActive) m_monitorManager->activateRecMonitor(m_name); + + } +} + +void RecMonitor::slotPlay() { + + //if (!m_isActive) m_monitorManager->activateRecMonitor(m_name); + +} + + +#include "recmonitor.moc" diff --git a/src/recmonitor.h b/src/recmonitor.h new file mode 100644 index 00000000..20bba7b3 --- /dev/null +++ b/src/recmonitor.h @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org) * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + + +#ifndef RECMONITOR_H +#define RECMONITOR_H + +#include +#include +#include +#include + +#include +#include +#include + +#include "ui_recmonitor_ui.h" +#include "smallruler.h" + +class RecMonitor : public QWidget { + Q_OBJECT + +public: + RecMonitor(QString name, QWidget *parent = 0); + QString name() const; + + +protected: + virtual void mousePressEvent(QMouseEvent * event); + +private: + Ui::RecMonitor_UI ui; + QString m_tmpFolder; + QString m_name; + + bool m_isActive; + + + KUrl m_captureFile; + + QProcess *captureProcess; + QProcess *displayProcess; + QTimer *m_initTimer; + bool m_isCapturing; + QStringList m_captureArgs; + QStringList m_displayArgs; + +private slots: + void slotSwitchCapture(); + void slotCapture(); + void slotProcessStatus(QProcess::ProcessState status); + +public slots: + void refreshRecMonitor(bool visible); + void stop(); + void start(); + void activateRecMonitor(); + void slotPlay(); + +signals: + void renderPosition(int); + void durationChanged(int); + void addProjectClip(KUrl); +}; + +#endif diff --git a/src/widgets/configcapture_ui.ui b/src/widgets/configcapture_ui.ui new file mode 100644 index 00000000..a177b4fe --- /dev/null +++ b/src/widgets/configcapture_ui.ui @@ -0,0 +1,231 @@ + + ConfigCapture_UI + + + + 0 + 0 + 422 + 339 + + + + + + + Default capture device + + + + + + + + Firewire (DV / HDV) + + + + + Video4Linux (webcam) + + + + + + + + Firewire config + + + + + + Default format + + + + + + + + DV Raw + + + + + DV AVI type 1 + + + + + DV AVI type 2 + + + + + HDV + + + + + + + + + + + Video4Linux + + + + + + Video device + + + + + + + /dev/video0 + + + + + + + Format + + + + + + + m4v + + + + + + + Audio device + + + + + + + /dev/dsp + + + + + + + Format + + + + + + + oss + + + + + + + Image width + + + + + + + 2000 + + + 320 + + + + + + + Image height + + + + + + + 2000 + + + 240 + + + + + + + Frame rate + + + + + + + 15 + + + + + + + + + + Qt::Vertical + + + + 20 + 56 + + + + + + + + Capture folder + + + + + + + + + + + KComboBox + QComboBox +
kcombobox.h
+
+ + KLineEdit + QLineEdit +
klineedit.h
+
+ + KUrlRequester + QFrame +
kurlrequester.h
+
+
+ + +
diff --git a/src/widgets/recmonitor_ui.ui b/src/widgets/recmonitor_ui.ui new file mode 100644 index 00000000..90a99105 --- /dev/null +++ b/src/widgets/recmonitor_ui.ui @@ -0,0 +1,93 @@ + + RecMonitor_UI + + + + 0 + 0 + 301 + 248 + + + + + + + Not connected + + + Qt::AlignCenter + + + + + + + Connect + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Record + + + + + + + + 0 + 0 + + + + + 0 + 15 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Auto add + + + true + + + + + + + + KPushButton + QPushButton +
kpushbutton.h
+
+
+ + +
-- 2.39.2