]> git.sesse.net Git - kdenlive/commitdiff
Complete rewrite of the video4linux capture to use MLT, in progress.
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Wed, 25 May 2011 13:11:23 +0000 (13:11 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Wed, 25 May 2011 13:11:23 +0000 (13:11 +0000)
Breaks Decklink capture for a few days...

svn path=/trunk/kdenlive/; revision=5607

44 files changed:
src/CMakeLists.txt
src/abstractmonitor.cpp [new file with mode: 0644]
src/abstractmonitor.h [new file with mode: 0644]
src/colorscopes/abstractgfxscopewidget.cpp
src/colorscopes/abstractgfxscopewidget.h
src/colorscopes/histogram.cpp
src/colorscopes/histogram.h
src/colorscopes/rgbparade.cpp
src/colorscopes/rgbparade.h
src/colorscopes/vectorscope.cpp
src/colorscopes/vectorscope.h
src/colorscopes/waveform.cpp
src/colorscopes/waveform.h
src/kdenlivedoc.h
src/kdenlivesettings.kcfg
src/kdenlivesettingsdialog.cpp
src/kdenlivesettingsdialog.h
src/mainwindow.cpp
src/mainwindow.h
src/mltdevicecapture.cpp [new file with mode: 0644]
src/mltdevicecapture.h [new file with mode: 0644]
src/monitor.cpp
src/monitor.h
src/monitormanager.cpp
src/monitormanager.h
src/profilesdialog.cpp
src/profilesdialog.h
src/recmonitor.cpp
src/recmonitor.h
src/renderer.cpp
src/renderer.h
src/stopmotion/stopmotion.cpp
src/stopmotion/stopmotion.h
src/v4l/src.c
src/v4l/src.h
src/v4l/src_v4l2.c
src/v4l/v4lcapture.cpp
src/v4l/v4lcapture.h
src/v4l/videodev2.h
src/widgets/configcapture_ui.ui
src/widgets/stopmotion_ui.ui
src/widgets/wizardcapture_ui.ui
src/wizard.cpp
src/wizard.h

index 9cb5093db6a872cdc19547985fa12fdadd41991b..4be9af3512ad3f7fb58c92383b8f2033a0a16519 100644 (file)
@@ -282,6 +282,8 @@ set(kdenlive_SRCS
   simplekeyframes/simplekeyframewidget.cpp
   noteswidget.cpp
   archivewidget.cpp
+  mltdevicecapture.cpp
+  abstractmonitor.cpp
 )
 
 add_definitions(${KDE4_DEFINITIONS})
@@ -302,13 +304,6 @@ if(NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
     ${kdenlive_SRCS}
     v4l/v4lcapture.cpp
     v4l/src.c
-    v4l/src_v4l2.c
-    v4l/dec_bayer.c
-    v4l/dec_grey.c
-    v4l/dec_jpeg.c
-    v4l/dec_rgb.c
-    v4l/dec_s561.c
-    v4l/dec_yuv.c
   )
 endif(NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
 
diff --git a/src/abstractmonitor.cpp b/src/abstractmonitor.cpp
new file mode 100644 (file)
index 0000000..b83765e
--- /dev/null
@@ -0,0 +1,64 @@
+/***************************************************************************
+ *   Copyright (C) 2011 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 "abstractmonitor.h"
+
+
+VideoPreviewContainer::VideoPreviewContainer(QWidget *parent) :
+    QFrame(parent),
+    m_image(new QImage())
+{
+    setFrameShape(QFrame::NoFrame);
+    setFocusPolicy(Qt::ClickFocus);
+    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+}
+
+
+void VideoPreviewContainer::setImage(QImage img)
+{
+        if (m_image) delete m_image;
+        m_image = new QImage(img);
+        update();
+}
+
+// virtual
+void VideoPreviewContainer::paintEvent(QPaintEvent */*event*/)
+{
+        if (m_image->isNull()) return;
+        QPainter painter(this);
+        double ar = (double) m_image->width() / m_image->height();
+        QRect rect = this->frameRect();
+        int paintW = rect.height() * ar + 0.5;
+        if (paintW > rect.width()) {
+            paintW = rect.width() / ar + 0.5;
+            int diff = (rect.height() - paintW)  / 2;
+            rect.adjust(0, diff, 0, 0);
+            rect.setHeight(paintW);
+        }
+        else {
+            int diff = (rect.width() - paintW)  / 2;
+            rect.adjust(diff, 0, 0, 0);
+            rect.setWidth(paintW);
+        }
+
+        painter.drawImage(rect, *m_image);
+}
+
+
diff --git a/src/abstractmonitor.h b/src/abstractmonitor.h
new file mode 100644 (file)
index 0000000..2f56ac4
--- /dev/null
@@ -0,0 +1,88 @@
+/***************************************************************************
+ *   Copyright (C) 2011 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 ABSTRACTMONITOR_H
+#define ABSTRACTMONITOR_H
+
+#include <QObject>
+#include <QVector>
+#include <QWidget>
+#include <QImage>
+#include <QPainter>
+#include <QFrame>
+
+class VideoPreviewContainer : public QFrame
+{
+    Q_OBJECT
+public:
+    VideoPreviewContainer(QWidget *parent = 0);
+    
+    void setImage(QImage img);
+
+protected:
+    virtual void paintEvent(QPaintEvent */*event*/);
+
+private:
+    QImage *m_image;
+};
+
+
+
+class AbstractRender: public QObject
+{
+Q_OBJECT public:
+
+    /** @brief Build an abstract MLT Renderer
+     *  @param rendererName A unique identifier for this renderer
+     *  @param winid The parent widget identifier (required for SDL display). Set to 0 for OpenGL rendering
+     *  @param profile The MLT profile used for the renderer (default one will be used if empty). */
+    AbstractRender(QWidget *parent = 0):QObject(parent),sendFrameForAnalysis(false) {};
+
+    /** @brief Destroy the MLT Renderer. */
+    virtual ~AbstractRender() {};
+
+    /** @brief This property is used to decide if the renderer should convert it's frames to QImage for use in other Kdenlive widgets. */
+    bool sendFrameForAnalysis;
+
+    /** @brief Someone needs us to send again a frame. */
+    virtual void sendFrameUpdate() = 0;
+
+signals:
+    /** @brief The renderer refreshed the current frame. */
+    void frameUpdated(QImage);
+
+    /** @brief This signal contains the audio of the current frame. */
+    void audioSamplesSignal(QVector<int16_t>, int, int, int);
+};
+
+class AbstractMonitor : public QWidget
+{
+    Q_OBJECT
+public:
+    AbstractMonitor(QWidget *parent = 0): QWidget(parent) {};
+    virtual ~AbstractMonitor() {};
+    virtual AbstractRender *abstractRender() = 0;
+    virtual const QString name() const = 0;
+
+public slots:
+    virtual void stop() = 0;
+    virtual void start() = 0;
+};
+
+#endif
index 275be135610540a8132f086e442a0bdcf17be4d9..43a7d81569e5f09be756dc8152cab65ae702ab0f 100644 (file)
@@ -12,7 +12,7 @@
 
 #include "abstractgfxscopewidget.h"
 #include "renderer.h"
-#include "monitor.h"
+#include "monitormanager.h"
 
 #include <QFuture>
 #include <QColor>
 
 const int REALTIME_FPS = 30;
 
-AbstractGfxScopeWidget::AbstractGfxScopeWidget(Monitor *projMonitor, Monitor *clipMonitor, bool trackMouse, QWidget *parent) :
+AbstractGfxScopeWidget::AbstractGfxScopeWidget(MonitorManager *manager, bool trackMouse, QWidget *parent) :
         AbstractScopeWidget(trackMouse, parent),
-        m_projMonitor(projMonitor),
-        m_clipMonitor(clipMonitor)
-
+        m_manager(manager)
 {
-    m_activeRender = (m_clipMonitor->isActive()) ? m_clipMonitor->render : m_projMonitor->render;
+    m_activeRender = m_manager->activeRenderer();
 
     bool b = true;
-    b &= connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
+    if (m_activeRender != NULL)
+        b &= connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
     Q_ASSERT(b);
 }
+
 AbstractGfxScopeWidget::~AbstractGfxScopeWidget() { }
 
 QImage AbstractGfxScopeWidget::renderScope(uint accelerationFactor)
@@ -50,7 +50,7 @@ QImage AbstractGfxScopeWidget::renderScope(uint accelerationFactor)
 
 void AbstractGfxScopeWidget::mouseReleaseEvent(QMouseEvent *event)
 {
-    if (!m_aAutoRefresh->isChecked()) {
+    if (!m_aAutoRefresh->isChecked() && m_activeRender) {
         m_activeRender->sendFrameUpdate();
     }
     AbstractScopeWidget::mouseReleaseEvent(event);
@@ -59,20 +59,23 @@ void AbstractGfxScopeWidget::mouseReleaseEvent(QMouseEvent *event)
 
 ///// Slots /////
 
-void AbstractGfxScopeWidget::slotActiveMonitorChanged(bool isClipMonitor)
+void AbstractGfxScopeWidget::slotActiveMonitorChanged()
 {
+    if (m_activeRender) {
+        bool b = m_activeRender->disconnect(this);
+        Q_ASSERT(b);
+    }
+
+    m_activeRender = m_manager->activeRenderer();
 #ifdef DEBUG_AGSW
-    qDebug() << "Active monitor has changed in " << widgetName() << ". Is the clip monitor active now? " << isClipMonitor;
+    qDebug() << "Active monitor has changed in " << widgetName() << ". Is the clip monitor active now? " << m_activeRender->name();
 #endif
 
-    bool b = m_activeRender->disconnect(this);
-    Q_ASSERT(b);
-
-    m_activeRender = (isClipMonitor) ? m_clipMonitor->render : m_projMonitor->render;
-
     //b &= connect(m_activeRender, SIGNAL(rendererPosition(int)), this, SLOT(slotRenderZoneUpdated()));
-    b &= connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
-    Q_ASSERT(b);
+    if (m_activeRender) {
+        bool b = connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
+        Q_ASSERT(b);
+    }
 
     // Update the scope for the new monitor.
     forceUpdate(true);
@@ -86,7 +89,7 @@ void AbstractGfxScopeWidget::slotRenderZoneUpdated(QImage frame)
 
 void AbstractGfxScopeWidget::slotAutoRefreshToggled(bool autoRefresh)
 {
-    if (autoRefresh) {
+    if (autoRefresh && m_activeRender) {
         m_activeRender->sendFrameUpdate();
     }
 }
index 49c48d67ac1d8699492a745dd51c5fce2b1f5feb..0dc59eb255d2e23e3393559aa51887c811acff3c 100644 (file)
 #ifndef ABSTRACTGFXSCOPEWIDGET_H
 #define ABSTRACTGFXSCOPEWIDGET_H
 
-
 #include <QtCore>
 #include <QWidget>
 
 #include "abstractscopewidget.h"
+#include "renderer.h"
 
 class QMenu;
 
-class Monitor;
-class Render;
+class MonitorManager;
 
 class AbstractGfxScopeWidget : public AbstractScopeWidget
 {
     Q_OBJECT
 
 public:
-    AbstractGfxScopeWidget(Monitor *projMonitor, Monitor *clipMonitor, bool trackMouse = false, QWidget *parent = 0);
+    AbstractGfxScopeWidget(MonitorManager *manager, bool trackMouse = false, QWidget *parent = 0);
     virtual ~AbstractGfxScopeWidget(); // Must be virtual because of inheritance, to avoid memory leaks
 
 protected:
     ///// Variables /////
 
-    Monitor *m_projMonitor;
-    Monitor *m_clipMonitor;
-    Render *m_activeRender;
+    MonitorManager *m_manager;
+    AbstractRender *m_activeRender;
 
     /** @brief Scope renderer. Must emit signalScopeRenderingFinished()
         when calculation has finished, to allow multi-threading.
@@ -53,7 +51,7 @@ public slots:
     /** @brief Must be called when the active monitor has shown a new frame.
       This slot must be connected in the implementing class, it is *not*
       done in this abstract class. */
-    void slotActiveMonitorChanged(bool isClipMonitor);
+    void slotActiveMonitorChanged();
 
 protected slots:
     virtual void slotAutoRefreshToggled(bool autoRefresh);
index d0042b6da68df67a9ae8a220bd4455461ca4f800..60b32a1298936c10319c9a866986367d895b1fd1 100644 (file)
@@ -14,8 +14,8 @@
 #include "histogram.h"
 #include "renderer.h"
 
-Histogram::Histogram(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
-    AbstractGfxScopeWidget(projMonitor, clipMonitor, false, parent)
+Histogram::Histogram(MonitorManager *manager, QWidget *parent) :
+    AbstractGfxScopeWidget(manager, false, parent)
 {
     ui = new Ui::Histogram_UI();
     ui->setupUi(this);
index 81849a36699492ad348cb2820fded164336edb78..19b86da2011838ebacc9424e74c50bd115180436 100644 (file)
@@ -20,7 +20,7 @@ class Histogram : public AbstractGfxScopeWidget {
     Q_OBJECT
 
 public:
-    Histogram(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
+    Histogram(MonitorManager *manager, QWidget *parent = 0);
     ~Histogram();
     QString widgetName() const;
 
index 2586cff8753d36dbfa25b9cb09fabb8f0d38b8db..396697fcea6a1dfdd594950724983736ea70b221 100644 (file)
@@ -16,8 +16,8 @@
 #include "rgbparade.h"
 #include "rgbparadegenerator.h"
 
-RGBParade::RGBParade(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
-        AbstractGfxScopeWidget(projMonitor, clipMonitor, true, parent)
+RGBParade::RGBParade(MonitorManager *manager, QWidget *parent) :
+        AbstractGfxScopeWidget(manager, true, parent)
 {
     ui = new Ui::RGBParade_UI();
     ui->setupUi(this);
index a51b0453d43f08efa8530d4686e9605150ef29f1..db178b20df9860bd2b9d5c390e5a4cb417d6f5ca 100644 (file)
@@ -23,7 +23,7 @@ class RGBParadeGenerator;
 class RGBParade : public AbstractGfxScopeWidget
 {
 public:
-    RGBParade(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
+    RGBParade(MonitorManager *manager, QWidget *parent = 0);
     ~RGBParade();
     QString widgetName() const;
 
index 9bf50aff7033e4f146d099a0b52f5aed63b13774..2802a5d4c5afbcf84a04c724a84460a80695f305 100644 (file)
@@ -42,8 +42,8 @@ const QPointF YPbPr_Mg(.331, .419);
 const QPointF YPbPr_Yl(-.5, .081);
 
 
-Vectorscope::Vectorscope(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
-    AbstractGfxScopeWidget(projMonitor, clipMonitor, true, parent),
+Vectorscope::Vectorscope(MonitorManager *manager, QWidget *parent) :
+    AbstractGfxScopeWidget(manager, true, parent),
     m_gain(1)
 {
     ui = new Ui::Vectorscope_UI();
index 38fa5a94698004b80ebd42a6c6582ecaf2c16fbc..de54440d5c5e5cde29d804aaf01446ab299afc98 100644 (file)
@@ -28,7 +28,7 @@ class Vectorscope : public AbstractGfxScopeWidget {
     Q_OBJECT
 
 public:
-    Vectorscope(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
+    Vectorscope(MonitorManager *manager, QWidget *parent = 0);
     ~Vectorscope();
 
     QString widgetName() const;
index 47597ac301db6cb43b547f6cbb0118fcbe896271..bf09234bfeb9174ec7c3ae645539629879e11d65 100644 (file)
@@ -25,8 +25,8 @@
 const QSize Waveform::m_textWidth(35,0);
 const int Waveform::m_paddingBottom(20);
 
-Waveform::Waveform(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
-    AbstractGfxScopeWidget(projMonitor, clipMonitor, true, parent)
+Waveform::Waveform(MonitorManager *manager, QWidget *parent) :
+    AbstractGfxScopeWidget(manager, true, parent)
   ,ui(NULL)
 {
     ui = new Ui::Waveform_UI();
index f1d648ab62f9fb3bc420ff9e01b3962a2893e3cb..ce0313979cc556575793b5343b34d6333526be8d 100644 (file)
@@ -22,7 +22,7 @@ class Waveform : public AbstractGfxScopeWidget {
     Q_OBJECT
 
 public:
-    Waveform(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
+    Waveform(MonitorManager *manager, QWidget *parent = 0);
     ~Waveform();
 
     virtual QString widgetName() const;
index 1e06519340c4e06a71490e95f150fd01eb69275b..5577a9f4fde8bef216887dbff92e29056a391343 100644 (file)
@@ -224,7 +224,6 @@ signals:
     void addProjectClip(DocClipBase *, bool getInfo = true);
     void signalDeleteProjectClip(const QString &);
     void updateClipDisplay(const QString&);
-    void deleteTimelineClip(const QString&);
     void progressInfo(const QString &, int);
 
     /** @brief Informs that the document status has been changed.
index 7c9db250e551dc0ecebd24c107a9d768bbb71294..a365044383791e86811e2f25fc11bddf207aec69 100644 (file)
       <default>0</default>
     </entry>
 
-    <entry name="video4vformat" type="String">
-      <label>Default video4linux capture format.</label>
-      <default>video4linux2</default>
-    </entry>
-
     <entry name="video4vdevice" type="String">
       <label>Default video4linux capture format.</label>
       <default>/dev/video0</default>
     </entry>
 
-    <entry name="video4vcodec" type="String">
-      <label>Default video4linux video codec.</label>
-      <default>mjpeg</default>
+    <entry name="v4l_alsadevice" type="UInt">
+      <label>Audio device for v4l capture.</label>
+      <default></default>
     </entry>
 
-    <entry name="video4acodec" type="String">
-      <label>Default video4linux audio codec.</label>
-      <default>mp2</default>
+    <entry name="v4l_alsadevicename" type="String">
+      <label>Audio device for v4l capture.</label>
+      <default>hw:0,0</default>
     </entry>
 
-    <entry name="video4container" type="String">
+    <entry name="v4l_parameters" type="String">
       <label>Default video4linux format.</label>
-      <default>avi</default>
+      <default>f=mpeg acodec=mp2 ab=128k ar=48000 vcodec=mpeg2video minrate=0 b=4000k bf=2 b_strategy=1 trellis=1</default>
     </entry>
 
-    <entry name="video4extension" type="String">
+    <entry name="v4l_extension" type="String">
       <label>Default video4linux file extension.</label>
-      <default>avi</default>
-    </entry>
-
-    <entry name="video4aformat" type="String">
-      <label>Default video4linux capture format.</label>
-      <default>oss</default>
-    </entry>
-
-    <entry name="video4adevice" type="String">
-      <label>Default video4linux capture format.</label>
-      <default>/dev/dsp</default>
+      <default>mpeg</default>
     </entry>
 
-    <entry name="video4size" type="String">
-      <label>Default video4linux capture format.</label>
-      <default>320x240</default>
-    </entry>
-
-    <entry name="video4rate" type="Int">
-      <label>Default video4linux capture format.</label>
-      <default>15</default>
-    </entry>
-
-    <entry name="video4capture" type="String">
-      <label>ffmpeg arguments for video capture.</label>
-      <default></default>
+    <entry name="v4l_format" type="UInt">
+      <label>Selected capture format.</label>
+      <default>0</default>
     </entry>
 
-    <entry name="video4encoding" type="String">
-      <label>ffmpeg encoding arguments.</label>
-      <default>-qscale 1 -ab 224k</default>
+    <entry name="v4l_captureaudio" type="Bool">
+      <label>Should we also capture audio.</label>
+      <default>false</default>
     </entry>
 
     <entry name="rmd_capture_audio" type="Bool">
index 36a6d645d2404fa4fa9602b43c20a3f74d2b997d..c87fe9ca2f841b590d83468b7d9c569b6b05a820 100644 (file)
@@ -53,7 +53,7 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(const QMap<QString, QString>& map
     m_shuttleModified(false),
     m_mappable_actions(mappable_actions)
 {
-
+    KdenliveSettings::setV4l_format(0);
     QWidget *p1 = new QWidget;
     m_configMisc.setupUi(p1);
     m_page1 = addPage(p1, i18n("Misc"), "configure");
@@ -94,12 +94,13 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(const QMap<QString, QString>& map
     m_configCapture.setupUi(p4);
 
 #if !defined(Q_WS_MAC) && !defined(Q_OS_FREEBSD)
-    V4lCaptureHandler v4l(NULL);
+    m_configCapture.kcfg_v4l_parameters->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 4);
+
     // Video 4 Linux device detection
     for (int i = 0; i < 10; i++) {
         QString path = "/dev/video" + QString::number(i);
         if (QFile::exists(path)) {
-            QStringList deviceInfo = v4l.getDeviceName(path);
+            QStringList deviceInfo = V4lCaptureHandler::getDeviceName(path.toUtf8().constData());
             if (!deviceInfo.isEmpty()) {
                 m_configCapture.kcfg_detectedv4ldevices->addItem(deviceInfo.at(0), path);
                 m_configCapture.kcfg_detectedv4ldevices->setItemData(m_configCapture.kcfg_detectedv4ldevices->count() - 1, deviceInfo.at(1), Qt::UserRole + 1);
@@ -107,6 +108,10 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(const QMap<QString, QString>& map
         }
     }
     connect(m_configCapture.kcfg_detectedv4ldevices, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatev4lDevice()));
+    connect(m_configCapture.kcfg_v4l_format, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatev4lCaptureProfile()));
+    connect(m_configCapture.kcfg_v4l_captureaudio, SIGNAL(toggled(bool)), m_configCapture.kcfg_v4l_alsadevice, SLOT(setEnabled(bool)));
+
+    slotUpdatev4lDevice();
 #endif
 
     m_page4 = addPage(p4, i18n("Capture"), "media-record");
@@ -181,15 +186,6 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(const QMap<QString, QString>& map
     connect(m_configTranscode.button_delete, SIGNAL(clicked()), this, SLOT(slotDeleteTranscode()));
     connect(m_configTranscode.profiles_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotDialogModified()));
     
-    connect(m_configCapture.kcfg_video4vdevice, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
-    connect(m_configCapture.kcfg_video4adevice, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
-    connect(m_configCapture.kcfg_video4vcodec, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
-    connect(m_configCapture.kcfg_video4acodec, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
-    connect(m_configCapture.kcfg_video4vformat, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
-    connect(m_configCapture.kcfg_video4aformat, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
-    connect(m_configCapture.kcfg_video4size, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
-    connect(m_configCapture.kcfg_video4rate, SIGNAL(editingFinished()), this, SLOT(rebuildVideo4Commands()));
-
     connect(m_configCapture.kcfg_rmd_capture_audio, SIGNAL(clicked(bool)), m_configCapture.audio_group, SLOT(setVisible(bool)));
 
     m_configCapture.audio_group->setVisible(KdenliveSettings::rmd_capture_audio());
@@ -356,6 +352,7 @@ void KdenliveSettingsDialog::initDevices()
                 if (line.contains("capture")) {
                     deviceId = line.section(':', 0, 0);
                     m_configCapture.kcfg_rmd_alsa_device->addItem(line.section(':', 1, 1), "plughw:" + QString::number(deviceId.section('-', 0, 0).toInt()) + ',' + QString::number(deviceId.section('-', 1, 1).toInt()));
+                    m_configCapture.kcfg_v4l_alsadevice->addItem(line.section(':', 1, 1), "hw:" + QString::number(deviceId.section('-', 0, 0).toInt()) + ',' + QString::number(deviceId.section('-', 1, 1).toInt()));
                 }
             }
             file.close();
@@ -367,12 +364,22 @@ void KdenliveSettingsDialog::initDevices()
         m_configSdl.kcfg_audio_device->setCurrentIndex(ix);
         KdenliveSettings::setAudio_device(ix);
     }
+    
     if (!KdenliveSettings::rmd_alsadevicename().isEmpty()) {
         // Select correct alsa device
         int ix = m_configCapture.kcfg_rmd_alsa_device->findData(KdenliveSettings::rmd_alsadevicename());
         m_configCapture.kcfg_rmd_alsa_device->setCurrentIndex(ix);
         KdenliveSettings::setRmd_alsa_device(ix);
     }
+
+    if (!KdenliveSettings::v4l_alsadevicename().isEmpty()) {
+        // Select correct alsa device
+        int ix = m_configCapture.kcfg_v4l_alsadevice->findData(KdenliveSettings::v4l_alsadevicename());
+        m_configCapture.kcfg_v4l_alsadevice->setCurrentIndex(ix);
+        KdenliveSettings::setV4l_alsadevice(ix);
+    }
+
+    loadCurrentV4lProfileInfo();
 }
 
 
@@ -389,6 +396,7 @@ void KdenliveSettingsDialog::slotReadAudioDevices()
             QString device = data.section(':', 1, 1).section(' ', -1);
             m_configSdl.kcfg_audio_device->addItem(data.section(':', -1), "plughw:" + card + ',' + device);
             m_configCapture.kcfg_rmd_alsa_device->addItem(data.section(':', -1), "plughw:" + card + ',' + device);
+            m_configCapture.kcfg_v4l_alsadevice->addItem(data.section(':', -1), "hw:" + card + ',' + device);
         }
     }
 }
@@ -488,14 +496,6 @@ void KdenliveSettingsDialog::slotUpdateShuttleDevice(int ix)
 
 #endif /* NO_JOGSHUTTLE */
 
-void KdenliveSettingsDialog::rebuildVideo4Commands()
-{
-    QString captureCommand;
-    if (!m_configCapture.kcfg_video4adevice->text().isEmpty()) captureCommand = "-f " + m_configCapture.kcfg_video4aformat->text() + " -i " + m_configCapture.kcfg_video4adevice->text() + " -acodec " + m_configCapture.kcfg_video4acodec->text();
-
-    captureCommand +=  " -f " + m_configCapture.kcfg_video4vformat->text() + " -s " + m_configCapture.kcfg_video4size->text() + " -r " + QString::number(m_configCapture.kcfg_video4rate->value()) + " -i " + m_configCapture.kcfg_video4vdevice->text() + " -vcodec " + m_configCapture.kcfg_video4vcodec->text();
-    m_configCapture.kcfg_video4capture->setText(captureCommand);
-}
 void KdenliveSettingsDialog::updateWidgets()
 {
     // Revert widgets to last saved state (for example when user pressed "Cancel")
@@ -569,6 +569,12 @@ void KdenliveSettingsDialog::updateSettings()
         updateCapturePath = true;
     }
 
+    if ((uint) m_configCapture.kcfg_v4l_format->currentIndex() != KdenliveSettings::v4l_format()) {
+        saveCurrentV4lProfile();
+        KdenliveSettings::setV4l_format(0);
+    }
+    
+
     if (updateCapturePath) emit updateCaptureFolder();
 
     QString value = m_configCapture.kcfg_rmd_alsa_device->itemData(m_configCapture.kcfg_rmd_alsa_device->currentIndex()).toString();
@@ -576,6 +582,11 @@ void KdenliveSettingsDialog::updateSettings()
         KdenliveSettings::setRmd_alsadevicename(value);
     }
 
+    value = m_configCapture.kcfg_v4l_alsadevice->itemData(m_configCapture.kcfg_v4l_alsadevice->currentIndex()).toString();
+    if (value != KdenliveSettings::v4l_alsadevicename()) {
+        KdenliveSettings::setV4l_alsadevicename(value);
+    }
+
     value = m_configCapture.kcfg_rmd_audio_freq->itemText(m_configCapture.kcfg_rmd_audio_freq->currentIndex());
     kDebug() << "// AUDIO FREQ VALUE: " << value << ", CURRENT: " << KdenliveSettings::rmd_freq() << ", IX: " << m_configCapture.kcfg_rmd_audio_freq->currentIndex();
     if (value != KdenliveSettings::rmd_freq()) {
@@ -767,11 +778,97 @@ void KdenliveSettingsDialog::slotUpdatev4lDevice()
 {
     QString device = m_configCapture.kcfg_detectedv4ldevices->itemData(m_configCapture.kcfg_detectedv4ldevices->currentIndex()).toString();
     if (!device.isEmpty()) m_configCapture.kcfg_video4vdevice->setText(device);
-    QString size = m_configCapture.kcfg_detectedv4ldevices->itemData(m_configCapture.kcfg_detectedv4ldevices->currentIndex(), Qt::UserRole + 1).toString();
-    if (!size.isEmpty()) m_configCapture.kcfg_video4size->setText(size);
-    rebuildVideo4Commands();
+    QString info = m_configCapture.kcfg_detectedv4ldevices->itemData(m_configCapture.kcfg_detectedv4ldevices->currentIndex(), Qt::UserRole + 1).toString();
+
+    m_configCapture.kcfg_v4l_format->blockSignals(true);
+    m_configCapture.kcfg_v4l_format->clear();
+
+    QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+    if (QFile::exists(vl4ProfilePath)) m_configCapture.kcfg_v4l_format->addItem(i18n("Current settings"));
+    
+    QStringList pixelformats = info.split(">", QString::SkipEmptyParts);
+    QString itemSize;
+    QString pixelFormat;
+    QStringList itemRates;
+    for (int i = 0; i < pixelformats.count(); i++) {
+        QString format = pixelformats.at(i).section(':', 0, 0);
+        QStringList sizes = pixelformats.at(i).split(":", QString::SkipEmptyParts);
+        pixelFormat = sizes.takeFirst();
+        for (int j = 0; j < sizes.count(); j++) {
+            itemSize = sizes.at(j).section("=", 0, 0);
+            itemRates = sizes.at(j).section("=", 1, 1).split(",", QString::SkipEmptyParts);
+            for (int k = 0; k < itemRates.count(); k++) {
+                m_configCapture.kcfg_v4l_format->addItem("[" + format + "] " + itemSize + " (" + itemRates.at(k) + ")", QStringList() << format << itemSize.section('x', 0, 0) << itemSize.section('x', 1, 1) << itemRates.at(k).section('/', 0, 0) << itemRates.at(k).section('/', 1, 1));
+            }
+        }
+    }
+    m_configCapture.kcfg_v4l_format->blockSignals(false);
+    slotUpdatev4lCaptureProfile();
 }
 
+void KdenliveSettingsDialog::slotUpdatev4lCaptureProfile()
+{
+    QStringList info = m_configCapture.kcfg_v4l_format->itemData(m_configCapture.kcfg_v4l_format->currentIndex(), Qt::UserRole).toStringList();
+    if (info.isEmpty()) {
+        // No auto info, display the current ones
+        loadCurrentV4lProfileInfo();
+        return;
+    }
+    m_configCapture.p_size->setText(info.at(1) + 'x' + info.at(2));
+    m_configCapture.p_fps->setText(info.at(3) + '/' + info.at(4));
+    m_configCapture.p_aspect->setText("1/1");
+    m_configCapture.p_display->setText(info.at(1) + '/' + info.at(2));
+    m_configCapture.p_colorspace->setText(ProfilesDialog::getColorspaceDescription(601));
+    m_configCapture.p_progressive->setText(i18n("Progressive"));
+
+    QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+    if (!QFile::exists(vl4ProfilePath)) saveCurrentV4lProfile();
+}
+
+void KdenliveSettingsDialog::loadCurrentV4lProfileInfo()
+{
+    QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+    MltVideoProfile prof;
+    if (!QFile::exists(vl4ProfilePath)) {
+        // No default formats found, build one
+        prof.width = 320;
+        prof.height = 200;
+        prof.frame_rate_num = 15;
+        prof.frame_rate_den = 1;
+        prof.display_aspect_num = 4;
+        prof.display_aspect_den = 3;
+        prof.sample_aspect_num = 1;
+        prof.sample_aspect_den = 1;
+        prof.progressive = 1;
+        prof.colorspace = 601;
+        ProfilesDialog::saveProfile(prof, vl4ProfilePath);
+    }
+    else prof = ProfilesDialog::getVideoProfile(vl4ProfilePath);
+    m_configCapture.p_size->setText(QString::number(prof.width) + 'x' + QString::number(prof.height));
+    m_configCapture.p_fps->setText(QString::number(prof.frame_rate_num) + '/' + QString::number(prof.frame_rate_den));
+    m_configCapture.p_aspect->setText(QString::number(prof.sample_aspect_num) + '/' + QString::number(prof.sample_aspect_den));
+    m_configCapture.p_display->setText(QString::number(prof.display_aspect_num) + '/' + QString::number(prof.display_aspect_den));
+    m_configCapture.p_colorspace->setText(ProfilesDialog::getColorspaceDescription(prof.colorspace));
+    if (prof.progressive) m_configCapture.p_progressive->setText(i18n("Progressive"));
+}
+
+void KdenliveSettingsDialog::saveCurrentV4lProfile()
+{
+    MltVideoProfile profile;
+    profile.description = "Video4Linux capture";
+    profile.colorspace = ProfilesDialog::getColorspaceFromDescription(m_configCapture.p_colorspace->text());
+    profile.width = m_configCapture.p_size->text().section('x', 0, 0).toInt();
+    profile.height = m_configCapture.p_size->text().section('x', 1, 1).toInt();
+    profile.sample_aspect_num = m_configCapture.p_aspect->text().section('/', 0, 0).toInt();
+    profile.sample_aspect_den = m_configCapture.p_aspect->text().section('/', 1, 1).toInt();
+    profile.display_aspect_num = m_configCapture.p_display->text().section('/', 0, 0).toInt();
+    profile.display_aspect_den = m_configCapture.p_display->text().section('/', 1, 1).toInt();
+    profile.frame_rate_num = m_configCapture.p_fps->text().section('/', 0, 0).toInt();
+    profile.frame_rate_den = m_configCapture.p_fps->text().section('/', 1, 1).toInt();
+    profile.progressive = m_configCapture.p_progressive->text() == i18n("Progressive");
+    QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+    ProfilesDialog::saveProfile(profile, vl4ProfilePath);
+}
 
 #include "kdenlivesettingsdialog.moc"
 
index 1f06efc7648ee845c9adcfed6aab66b6890aa1f5..e305d8701a78d176f433b760fff7e8152870fd45 100644 (file)
@@ -53,7 +53,6 @@ protected slots:
 
 private slots:
     void slotUpdateDisplay();
-    void rebuildVideo4Commands();
 #ifndef NO_JOGSHUTTLE
     void slotCheckShuttle(int state = 0);
     void slotUpdateShuttleDevice(int ix = 0);
@@ -71,6 +70,7 @@ private slots:
     void slotEnableCaptureFolder();
     void slotUpdateHDMIModes();
     void slotUpdatev4lDevice();
+    void slotUpdatev4lCaptureProfile();
 
 private:
     KPageWidgetItem *m_page1;
@@ -99,6 +99,8 @@ private:
     void initDevices();
     void loadTranscodeProfiles();
     void saveTranscodeProfiles();
+    void loadCurrentV4lProfileInfo();
+    void saveCurrentV4lProfile();
 
 signals:
     void customChanged();
index 65a39cd5dec2f76dcf5d85281a341cbaed4a0bc2..d94135d1a1c73c339ca1fee0659e5d22b93da45b 100644 (file)
@@ -139,6 +139,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     KXmlGuiWindow(parent),
     m_activeDocument(NULL),
     m_activeTimeline(NULL),
+    m_recMonitor(NULL),
     m_renderWidget(NULL),
 #ifndef NO_JOGSHUTTLE
     m_jogProcess(NULL),
@@ -208,11 +209,12 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
 #ifndef Q_WS_MAC
     m_recMonitorDock = new QDockWidget(i18n("Record Monitor"), this);
     m_recMonitorDock->setObjectName("record_monitor");
-    m_recMonitor = new RecMonitor("record");
+    m_recMonitor = new RecMonitor("record", m_monitorManager);
     m_recMonitorDock->setWidget(m_recMonitor);
     connect(m_recMonitor, SIGNAL(addProjectClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl)));
     connect(m_recMonitor, SIGNAL(showConfigDialog(int, int)), this, SLOT(slotPreferences(int, int)));
 #endif
+    m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor, m_recMonitor);
 
     m_notesDock = new QDockWidget(i18n("Project Notes"), this);
     m_notesDock->setObjectName("notes_widget");
@@ -245,7 +247,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_effectListDock->setWidget(m_effectList);
     addDockWidget(Qt::TopDockWidgetArea, m_effectListDock);
 
-    m_vectorscope = new Vectorscope(m_projectMonitor, m_clipMonitor);
+    m_vectorscope = new Vectorscope(m_monitorManager);
     m_vectorscopeDock = new QDockWidget(i18n("Vectorscope"), this);
     m_vectorscopeDock->setObjectName(m_vectorscope->widgetName());
     m_vectorscopeDock->setWidget(m_vectorscope);
@@ -255,7 +257,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     connect(m_vectorscope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
     m_gfxScopesList.append(m_vectorscopeDock);
 
-    m_waveform = new Waveform(m_projectMonitor, m_clipMonitor);
+    m_waveform = new Waveform(m_monitorManager);
     m_waveformDock = new QDockWidget(i18n("Waveform"), this);
     m_waveformDock->setObjectName(m_waveform->widgetName());
     m_waveformDock->setWidget(m_waveform);
@@ -265,7 +267,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     connect(m_waveform, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
     m_gfxScopesList.append(m_waveformDock);
 
-    m_RGBParade = new RGBParade(m_projectMonitor, m_clipMonitor);
+    m_RGBParade = new RGBParade(m_monitorManager);
     m_RGBParadeDock = new QDockWidget(i18n("RGB Parade"), this);
     m_RGBParadeDock->setObjectName(m_RGBParade->widgetName());
     m_RGBParadeDock->setWidget(m_RGBParade);
@@ -275,7 +277,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     connect(m_RGBParade, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
     m_gfxScopesList.append(m_RGBParadeDock);
 
-    m_histogram = new Histogram(m_projectMonitor, m_clipMonitor);
+    m_histogram = new Histogram(m_monitorManager);
     m_histogramDock = new QDockWidget(i18n("Histogram"), this);
     m_histogramDock->setObjectName(m_histogram->widgetName());
     m_histogramDock->setWidget(m_histogram);
@@ -561,12 +563,11 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     connect(m_projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool)));
     connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool)));
     //connect(m_monitorManager, SIGNAL(connectMonitors()), this, SLOT(slotConnectMonitors()));
-    connect(m_monitorManager, SIGNAL(raiseClipMonitor(bool)), this, SLOT(slotRaiseMonitor(bool)));
+    connect(m_monitorManager, SIGNAL(raiseMonitor(AbstractMonitor *)), this, SLOT(slotRaiseMonitor(AbstractMonitor *)));
     connect(m_monitorManager, SIGNAL(checkColorScopes()), this, SLOT(slotUpdateColorScopes()));
     connect(m_effectList, SIGNAL(addEffect(const QDomElement)), this, SLOT(slotAddEffect(const QDomElement)));
     connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects()));
 
-    m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor);
     slotConnectMonitors();
 
     // Open or create a file.  Command line argument passed in Url has
@@ -824,10 +825,10 @@ void MainWindow::slotAddEffect(const QDomElement effect)
     else m_activeTimeline->projectView()->slotAddEffect(effectToAdd, GenTime(), -1);
 }
 
-void MainWindow::slotRaiseMonitor(bool clipMonitor)
+void MainWindow::slotRaiseMonitor(AbstractMonitor *monitor)
 {
-    if (clipMonitor) m_clipMonitorDock->raise();
-    else m_projectMonitorDock->raise();
+    if (monitor == m_clipMonitor) m_clipMonitorDock->raise();
+    else if (monitor == m_projectMonitor) m_projectMonitorDock->raise();
 }
 
 void MainWindow::slotUpdateClip(const QString &id)
@@ -2394,7 +2395,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
             disconnect(m_activeDocument, SIGNAL(signalDeleteProjectClip(const QString &)), this, SLOT(slotDeleteClip(const QString &)));
             disconnect(m_activeDocument, SIGNAL(updateClipDisplay(const QString &)), m_projectList, SLOT(slotUpdateClip(const QString &)));
             disconnect(m_activeDocument, SIGNAL(selectLastAddedClip(const QString &)), m_projectList, SLOT(slotSelectClip(const QString &)));
-            disconnect(m_activeDocument, SIGNAL(deleteTimelineClip(const QString &)), m_activeTimeline, SLOT(slotDeleteClip(const QString &)));
             disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_effectStack, SLOT(slotClipItemSelected(ClipItem*, int)));
             disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), this, SLOT(slotActivateEffectStackView(ClipItem*, int, bool)));
             disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*)));
@@ -2450,7 +2450,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     connect(m_projectList, SIGNAL(findInTimeline(const QString&)), this, SLOT(slotClipInTimeline(const QString&)));
 
 
-    connect(trackView, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
+    //connect(trackView, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
     connect(trackView, SIGNAL(insertTrack(int)), this, SLOT(slotInsertTrack(int)));
     connect(trackView, SIGNAL(deleteTrack(int)), this, SLOT(slotDeleteTrack(int)));
     connect(trackView, SIGNAL(configTrack(int)), this, SLOT(slotConfigTrack(int)));
@@ -2471,7 +2471,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     connect(doc, SIGNAL(updateClipDisplay(const QString &)), m_projectList, SLOT(slotUpdateClip(const QString &)));
     connect(doc, SIGNAL(selectLastAddedClip(const QString &)), m_projectList, SLOT(slotSelectClip(const QString &)));
 
-    connect(doc, SIGNAL(deleteTimelineClip(const QString &)), trackView, SLOT(slotDeleteClip(const QString &)));
     connect(doc, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool)));
     connect(doc, SIGNAL(guidesUpdated()), this, SLOT(slotGuidesUpdated()));
     connect(m_notesWidget, SIGNAL(textChanged()), doc, SLOT(setModified()));
@@ -4178,9 +4177,11 @@ void MainWindow::slotDoUpdateGfxScopeFrameRequest()
             m_projectMonitor->render->sendFrameForAnalysis = false;
         }
         m_clipMonitor->render->sendFrameForAnalysis = false;
+        m_recMonitor->analyseFrames(false);
     } else {
         m_projectMonitor->render->sendFrameForAnalysis = true;
         m_clipMonitor->render->sendFrameForAnalysis = true;
+        m_recMonitor->analyseFrames(true);
     }
 }
 
@@ -4214,28 +4215,28 @@ void MainWindow::slotDoUpdateAudioScopeFrameRequest()
 void MainWindow::slotUpdateColorScopes()
 {
     bool request = false;
+    kDebug()<<"// UPDATE SCOPES";
     for (int i = 0; i < m_gfxScopesList.count(); i++) {
         // Check if we need the renderer to send a new frame for update
         if (!m_gfxScopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled())) request = true;
-        static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->slotActiveMonitorChanged(m_clipMonitor->isActive());
+        static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->slotActiveMonitorChanged();
     }
     if (request) {
-        if (m_clipMonitor->isActive()) m_clipMonitor->render->sendFrameUpdate();
-        else m_projectMonitor->render->sendFrameUpdate();
+        m_monitorManager->activeRenderer()->sendFrameUpdate();
     }
 }
 
 void MainWindow::slotOpenStopmotion()
 {
     if (m_stopmotion == NULL) {
-        m_stopmotion = new StopmotionWidget(m_activeDocument->projectFolder(), m_stopmotion_actions->actions(), this);
+        m_stopmotion = new StopmotionWidget(m_monitorManager, m_activeDocument->projectFolder(), m_stopmotion_actions->actions(), this);
         connect(m_stopmotion, SIGNAL(addOrUpdateSequence(const QString)), m_projectList, SLOT(slotAddOrUpdateSequence(const QString)));
-        for (int i = 0; i < m_gfxScopesList.count(); i++) {
+        //for (int i = 0; i < m_gfxScopesList.count(); i++) {
             // Check if we need the renderer to send a new frame for update
             /*if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast<AbstractScopeWidget *>(m_scopesList.at(i)->widget())->autoRefreshEnabled())) request = true;*/
-            connect(m_stopmotion, SIGNAL(gotFrame(QImage)), static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget()), SLOT(slotRenderZoneUpdated(QImage)));
+            //connect(m_stopmotion, SIGNAL(gotFrame(QImage)), static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget()), SLOT(slotRenderZoneUpdated(QImage)));
             //static_cast<AbstractScopeWidget *>(m_scopesList.at(i)->widget())->slotMonitorCapture();
-        }
+        //}
     }
     m_stopmotion->show();
 }
index 703fc625cd0ef08b695bde47b21c03f207fd089d..523bfc9ae10c7a62c06c388675f260bb3abba69e 100644 (file)
@@ -345,7 +345,7 @@ private slots:
     /** @brief Reflects setting changes to the GUI. */
     void updateConfiguration();
     void slotConnectMonitors();
-    void slotRaiseMonitor(bool clipMonitor);
+    void slotRaiseMonitor(AbstractMonitor *monitor);
     void slotUpdateClip(const QString &id);
     void slotUpdateMousePosition(int pos);
     void slotAddEffect(const QDomElement effect);
diff --git a/src/mltdevicecapture.cpp b/src/mltdevicecapture.cpp
new file mode 100644 (file)
index 0000000..f36fda0
--- /dev/null
@@ -0,0 +1,406 @@
+/***************************************************************************
+                        mltdevicecapture.cpp  -  description
+                           -------------------
+   begin                : Sun May 21 2011
+   copyright            : (C) 2011 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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+
+#include "mltdevicecapture.h"
+#include "kdenlivesettings.h"
+#include "definitions.h"
+//#include "recmonitor.h"
+//#include "renderer.h"
+#include "blackmagic/devices.h"
+
+#include <mlt++/Mlt.h>
+
+#include <KDebug>
+#include <KStandardDirs>
+#include <KMessageBox>
+#include <KLocale>
+#include <KTemporaryFile>
+
+#include <QTimer>
+#include <QDir>
+#include <QString>
+#include <QApplication>
+
+#include <cstdlib>
+#include <cstdarg>
+
+#include <QDebug>
+
+
+
+static void consumer_gl_frame_show(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
+{
+    // detect if the producer has finished playing. Is there a better way to do it?
+    Mlt::Frame frame(frame_ptr);
+    self->showFrame(frame);
+}
+
+static void rec_consumer_frame_show(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
+{
+    Mlt::Frame frame(frame_ptr);
+    if (!frame.is_valid()) return;
+    self->gotCapturedFrame(frame);
+}
+
+static void rec_consumer_frame_preview(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
+{
+    Mlt::Frame frame(frame_ptr);
+    if (!frame.is_valid()) return;
+    if (self->sendFrameForAnalysis && frame_ptr->convert_image) {
+        self->emitFrameUpdated(frame);
+    }
+    if (self->doCapture) {
+        self->doCapture = false;
+        self->saveFrame(frame);
+    }
+
+/*    if (self->analyseAudio) {
+        self->showAudio(frame);
+    }
+    if (frame.get_double("_speed") == 0.0) {
+        self->emitConsumerStopped();
+    } else if (frame.get_double("_speed") < 0.0 && mlt_frame_get_position(frame_ptr) <= 0) {
+        self->pause();
+        self->emitConsumerStopped();
+    }*/
+}
+
+
+MltDeviceCapture::MltDeviceCapture(QString profile, VideoPreviewContainer *surface, QWidget *parent) :
+    AbstractRender(parent),
+    doCapture(false),
+    sendFrameForAnalysis(false),
+    m_mltConsumer(NULL),
+    m_mltProducer(NULL),
+    m_mltProfile(NULL),
+    m_captureDisplayWidget(surface),
+    m_winid((int) surface->winId()),
+    m_analyseAudio(KdenliveSettings::monitor_audio())
+{
+    if (profile.isEmpty()) profile = KdenliveSettings::current_profile();
+    buildConsumer(profile);
+}
+
+MltDeviceCapture::~MltDeviceCapture()
+{
+    if (m_mltConsumer) delete m_mltConsumer;
+    if (m_mltProducer) delete m_mltProducer;
+    if (m_mltProfile) delete m_mltProfile;
+}
+
+void MltDeviceCapture::buildConsumer(const QString &profileName)
+{
+    if (!profileName.isEmpty()) m_activeProfile = profileName;
+
+    if (m_mltProfile) delete m_mltProfile;
+
+    char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
+    setenv("MLT_PROFILE", tmp, 1);
+    m_mltProfile = new Mlt::Profile(tmp);
+    m_mltProfile->get_profile()->is_explicit = 1;
+    delete[] tmp;
+
+    QString videoDriver = KdenliveSettings::videodrivername();
+    if (!videoDriver.isEmpty()) {
+        if (videoDriver == "x11_noaccel") {
+            setenv("SDL_VIDEO_YUV_HWACCEL", "0", 1);
+            videoDriver = "x11";
+        } else {
+            unsetenv("SDL_VIDEO_YUV_HWACCEL");
+        }
+    }
+    setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 1);
+
+    if (m_winid == 0) {
+        // OpenGL monitor
+        m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_audio");
+        m_mltConsumer->set("preview_off", 1);
+        m_mltConsumer->set("preview_format", mlt_image_rgb24a);
+        m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_gl_frame_show);
+    } else {
+        m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_preview");
+        m_mltConsumer->set("window_id", m_winid);
+    }
+    m_mltConsumer->set("resize", 1);
+    //m_mltConsumer->set("terminate_on_pause", 1);
+    m_mltConsumer->set("window_background", KdenliveSettings::window_background().name().toUtf8().constData());
+    m_mltConsumer->set("rescale", "nearest");
+    
+    m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) rec_consumer_frame_preview);
+
+    QString audioDevice = KdenliveSettings::audiodevicename();
+    if (!audioDevice.isEmpty())
+        m_mltConsumer->set("audio_device", audioDevice.toUtf8().constData());
+
+    if (!videoDriver.isEmpty())
+        m_mltConsumer->set("video_driver", videoDriver.toUtf8().constData());
+
+    QString audioDriver = KdenliveSettings::audiodrivername();
+
+    if (!audioDriver.isEmpty())
+        m_mltConsumer->set("audio_driver", audioDriver.toUtf8().constData());
+
+    //m_mltConsumer->set("progressive", 1);
+    //m_mltConsumer->set("buffer", 1);
+    //m_mltConsumer->set("real_time", 0);
+}
+
+void MltDeviceCapture::stop()
+{
+    if (m_mltConsumer) {
+        m_mltConsumer->stop();
+        //if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
+        delete m_mltConsumer;
+        m_mltConsumer = NULL;
+    }
+    kDebug()<<"STOPPING cap";
+    if (m_mltProducer) {
+        QList <Mlt::Producer *> prods;
+        Mlt::Service service(m_mltProducer->parent().get_service());
+        mlt_service_lock(service.get_service());
+kDebug()<<"STOPPING cap 2";
+        if (service.type() == tractor_type) {
+            kDebug()<<"STOPPING cap 3";
+            Mlt::Tractor tractor(service);
+            mlt_tractor_close(tractor.get_tractor());
+            Mlt::Field *field = tractor.field();
+            mlt_service nextservice = mlt_service_get_producer(service.get_service());
+            mlt_service nextservicetodisconnect;
+            mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
+            QString mlt_type = mlt_properties_get(properties, "mlt_type");
+            QString resource = mlt_properties_get(properties, "mlt_service");
+            // Delete all transitions
+            while (mlt_type == "transition") {
+                nextservicetodisconnect = nextservice;
+                nextservice = mlt_service_producer(nextservice);
+                mlt_field_disconnect_service(field->get_field(), nextservicetodisconnect);
+                if (nextservice == NULL) break;
+                properties = MLT_SERVICE_PROPERTIES(nextservice);
+                mlt_type = mlt_properties_get(properties, "mlt_type");
+                resource = mlt_properties_get(properties, "mlt_service");
+            }
+            for (int trackNb = tractor.count() - 1; trackNb >= 0; --trackNb) {
+                Mlt::Producer trackProducer(tractor.track(trackNb));
+                Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+                if (trackPlaylist.type() == playlist_type) {
+                    for (int i = 0; i < trackPlaylist.count();i++) {
+                        // We need to manually decrease the ref count and close the producer, otherwise
+                        // the video4linux device stays open, seems like a bug in MLT that is not cleaning properly
+                        mlt_properties props = MLT_PRODUCER_PROPERTIES(trackPlaylist.get_clip(i)->get_parent());
+                        while (mlt_properties_ref_count(props) > 0) mlt_properties_dec_ref(props);
+                        mlt_producer_close(trackPlaylist.get_clip(i)->get_parent());
+                    }
+                    mlt_playlist_close(trackPlaylist.get_playlist());
+                    //trackPlaylist.clear();
+                }
+            }
+            delete field;
+            field = NULL;
+        }
+        mlt_service_unlock(service.get_service());
+        delete m_mltProducer;
+        kDebug()<<"/// STOP REC PROD";
+        m_mltProducer = NULL;
+    }
+}
+
+
+void MltDeviceCapture::doRefresh()
+{
+    if (m_mltConsumer) m_mltConsumer->set("refresh", 1);
+}
+
+
+void MltDeviceCapture::emitFrameUpdated(Mlt::Frame& frame)
+{
+    mlt_image_format format = mlt_image_rgb24a;
+    int width = 0;
+    int height = 0;
+    const uchar* image = frame.get_image(format, width, height);
+    QImage qimage(width, height, QImage::Format_ARGB32);
+    memcpy(qimage.bits(), image, width * height * 4);
+    emit frameUpdated(qimage.rgbSwapped());
+}
+
+void MltDeviceCapture::showFrame(Mlt::Frame& frame)
+{
+    mlt_image_format format = mlt_image_rgb24a;
+    int width = 0;
+    int height = 0;
+    const uchar* image = frame.get_image(format, width, height);
+    QImage qimage(width, height, QImage::Format_ARGB32_Premultiplied);
+    memcpy(qimage.scanLine(0), image, width * height * 4);
+    emit showImageSignal(qimage);
+    if (m_analyseAudio) showAudio(frame);
+    if (sendFrameForAnalysis && frame.get_frame()->convert_image) {
+        emit frameUpdated(qimage.rgbSwapped());
+    }
+}
+
+void MltDeviceCapture::showAudio(Mlt::Frame& frame)
+{
+    if (!frame.is_valid() || frame.get_int("test_audio") != 0) {
+        return;
+    }
+    mlt_audio_format audio_format = mlt_audio_s16;
+    int freq = 0;
+    int num_channels = 0;
+    int samples = 0;
+    int16_t* data = (int16_t*)frame.get_audio(audio_format, freq, num_channels, samples);
+
+    if (!data) {
+        return;
+    }
+
+    // Data format: [ c00 c10 c01 c11 c02 c12 c03 c13 ... c0{samples-1} c1{samples-1} for 2 channels.
+    // So the vector is of size samples*channels.
+    QVector<int16_t> sampleVector(samples*num_channels);
+    memcpy(sampleVector.data(), data, samples*num_channels*sizeof(int16_t));
+
+    if (samples > 0) {
+        emit audioSamplesSignal(sampleVector, freq, num_channels, samples);
+    }
+}
+
+bool MltDeviceCapture::slotStartPreview(const QString &producer)
+{
+    //stop();
+    if (m_mltConsumer == NULL) buildConsumer();
+    /*if (m_mltConsumer) delete m_mltConsumer;
+    if (m_mltProducer) delete m_mltProducer;
+    if (m_mltProfile) delete m_mltProfile;
+    
+    char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
+    setenv("MLT_PROFILE", tmp, 1);
+    m_mltProfile = new Mlt::Profile(tmp);
+    delete[] tmp;
+    m_mltProfile->get_profile()->is_explicit = 1;
+
+    m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_preview");
+
+    m_mltConsumer->set("window_id", m_winid);
+    m_mltConsumer->set("real_time", 0);
+//    m_mltConsumer->set("buffer", 1);
+    m_mltConsumer->set("resize", 1);
+    m_mltConsumer->set("progressive", 1);
+    m_mltConsumer->set("rescale", "nearest");*/
+    
+    //char *tmp = qstrdup(QString("avformat-novalidate:video4linux2:%1?frame_rate:%2&width:%3&height:%4").arg(KdenliveSettings::video4vdevice()).arg(m_mltProfile->fps()).arg(m_mltProfile->width()).arg(m_mltProfile->height()).toUtf8().constData());
+
+    char *tmp = qstrdup(producer.toUtf8().constData());
+    
+    m_mltProducer = new Mlt::Producer(*m_mltProfile, tmp);
+    delete[] tmp;
+    if (m_mltProducer == NULL || !m_mltProducer->is_valid()) {
+        kDebug()<<"//// ERROR CREATRING PROD";
+        return false;
+    }
+    m_mltConsumer->connect(*m_mltProducer);
+    if (m_mltConsumer->start() == -1) {
+        delete m_mltConsumer;
+        m_mltConsumer = NULL;
+        return 0;
+    }
+    return 1;
+}
+
+void MltDeviceCapture::gotCapturedFrame(Mlt::Frame& frame)
+{
+    mlt_image_format format = mlt_image_rgb24a;
+    int width = 0;
+    int height = 0;
+    const uchar* image = frame.get_image(format, width, height);
+    QImage qimage(width, height, QImage::Format_ARGB32);
+    memcpy(qimage.bits(), image, width * height * 4);
+    m_captureDisplayWidget->setImage(qimage.rgbSwapped());
+}
+
+void MltDeviceCapture::saveFrame(Mlt::Frame& frame)
+{
+    mlt_image_format format = mlt_image_rgb24a;
+    int width = 0;
+    int height = 0;
+    const uchar* image = frame.get_image(format, width, height);
+    QImage qimage(width, height, QImage::Format_ARGB32);
+    memcpy(qimage.bits(), image, width * height * 4);
+    qimage.rgbSwapped().save(m_capturePath);
+    emit frameSaved(m_capturePath);
+    m_capturePath.clear();
+}
+
+void MltDeviceCapture::captureFrame(const QString &path)
+{
+    m_capturePath = path;
+    doCapture = true;
+}
+
+bool MltDeviceCapture::slotStartCapture(const QString &params, const QString &path, const QString &playlist)
+{
+    stop();
+    if (m_mltProfile) delete m_mltProfile;
+    char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
+    m_mltProfile = new Mlt::Profile(tmp);
+    delete[] tmp;
+    m_mltProfile->get_profile()->is_explicit = 1;
+    kDebug()<<"-- CREATING CAP: "<<params<<", PATH: "<<path;
+    tmp = qstrdup(QString("avformat:" + path).toUtf8().constData());
+    m_mltConsumer = new Mlt::Consumer(*m_mltProfile, tmp);
+    m_mltConsumer->set("terminate_on_pause", 1);
+    delete[] tmp;
+
+    QStringList paramList = params.split(" ", QString::SkipEmptyParts);
+    char *tmp2;
+    for (int i = 0; i < paramList.count(); i++) {
+        tmp = qstrdup(paramList.at(i).section("=", 0, 0).toUtf8().constData());
+        tmp2 = qstrdup(paramList.at(i).section("=", 1, 1).toUtf8().constData());
+        m_mltConsumer->set(tmp, tmp2);
+        delete[] tmp;
+        delete[] tmp2;
+    }
+    
+    if (m_mltConsumer == NULL || !m_mltConsumer->is_valid()) {
+        if (m_mltConsumer) {
+            delete m_mltConsumer;
+            m_mltConsumer = NULL;
+        }
+        return false;
+    }
+    
+    // FIXME: the event object returned by the listen gets leaked...
+    m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) rec_consumer_frame_show);
+
+    //tmp = qstrdup(QString("avformat-novalidate:video4linux2:%1?frame_rate:%2&width:%3&height:%4").arg(KdenliveSettings::video4vdevice()).arg(m_mltProfile->fps()).arg(m_mltProfile->width()).arg(m_mltProfile->height()).toUtf8().constData());
+    tmp = qstrdup(playlist.toUtf8().constData());
+    m_mltProducer = new Mlt::Producer(*m_mltProfile, "xml-string", tmp);
+    delete[] tmp;
+
+    if (m_mltProducer == NULL || !m_mltProducer->is_valid()) {
+        kDebug()<<"//// ERROR CREATRING PROD";
+        return false;
+    }
+
+    m_mltConsumer->connect(*m_mltProducer);
+    if (m_mltConsumer->start() == -1) {
+        delete m_mltConsumer;
+        m_mltConsumer = NULL;
+        return 0;
+    }
+    return 1;
+}
+
+
diff --git a/src/mltdevicecapture.h b/src/mltdevicecapture.h
new file mode 100644 (file)
index 0000000..461c829
--- /dev/null
@@ -0,0 +1,127 @@
+/***************************************************************************
+                         mltdevicecapture.h  -  description
+                            -------------------
+   begin                : Sun May 21 2011
+   copyright            : (C) 2011 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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+/**
+ * @class MltDeviceCapture
+ * @brief Interface for MLT capture.
+ */
+
+#ifndef MLTDEVICECAPTURE_H
+#define MLTDEVICECAPTURE_H
+
+#include "gentime.h"
+#include "definitions.h"
+#include "abstractmonitor.h"
+#include "mlt/framework/mlt_types.h"
+
+namespace Mlt
+{
+class Consumer;
+class Playlist;
+class Tractor;
+class Transition;
+class Frame;
+class Field;
+class Producer;
+class Filter;
+class Profile;
+class Service;
+};
+
+class MltDeviceCapture: public AbstractRender
+{
+Q_OBJECT public:
+
+    enum FailStates { OK = 0,
+                      APP_NOEXIST
+                    };
+    /** @brief Build a MLT Renderer
+     *  @param winid The parent widget identifier (required for SDL display). Set to 0 for OpenGL rendering
+     *  @param profile The MLT profile used for the capture (default one will be used if empty). */
+    MltDeviceCapture(QString profile, VideoPreviewContainer *surface, QWidget *parent = 0);
+
+    /** @brief Destroy the MLT Renderer. */
+    ~MltDeviceCapture();
+
+    bool doCapture;
+
+    /** @brief This property is used to decide if the renderer should convert it's frames to QImage for use in other Kdenlive widgets. */
+    bool sendFrameForAnalysis;
+
+    /** @brief Someone needs us to send again a frame. */
+    void sendFrameUpdate() {};
+    
+    void emitFrameUpdated(Mlt::Frame&);
+    void emitFrameNumber(double position);
+    void emitConsumerStopped();
+    void showFrame(Mlt::Frame&);
+    void showAudio(Mlt::Frame&);
+
+    void saveFrame(Mlt::Frame& frame);
+
+    /** @brief Starts the MLT Video4Linux process.
+     * @param surface The widget onto which the frame should be painted
+     */
+    bool slotStartCapture(const QString &params, const QString &path, const QString &playlist);
+    bool slotStartPreview(const QString &producer);
+    /** @brief A frame arrived from the MLT Video4Linux process. */
+    void gotCapturedFrame(Mlt::Frame& frame);
+    /** @brief Save current frame to file. */
+    void captureFrame(const QString &path);
+    void doRefresh();
+
+private:
+    Mlt::Consumer * m_mltConsumer;
+    Mlt::Producer * m_mltProducer;
+    Mlt::Profile *m_mltProfile;
+    QString m_activeProfile;
+
+    /** @brief The surface onto which the captured frames should be painted. */
+    VideoPreviewContainer *m_captureDisplayWidget;
+
+    /** @brief A human-readable description of this renderer. */
+    int m_winid;
+
+    /** @brief This property is used to decide if the renderer should send audio data for monitoring. */
+    bool m_analyseAudio;
+
+    QString m_capturePath;
+
+    /** @brief Build the MLT Consumer object with initial settings.
+     *  @param profileName The MLT profile to use for the consumer */
+    void buildConsumer(const QString &profileName = QString());
+
+private slots:
+
+signals:
+    /** @brief A frame's image has to be shown.
+     *
+     * Used in Mac OS X. */
+    void showImageSignal(QImage);
+    
+    /** @brief This signal contains the audio of the current frame. */
+    void audioSamplesSignal(const QVector<int16_t>&, int freq, int num_channels, int num_samples);
+
+    void frameSaved(const QString);
+
+public slots:
+
+    /** @brief Stops the consumer. */
+    void stop();
+};
+
+#endif
index 96be7c035602ef7976de92fe4342f945b33481cb..efc1d036ada17f7037f73a1a89c3e67cb9187fc2 100644 (file)
@@ -19,8 +19,6 @@
 
 
 #include "monitor.h"
-#include "renderer.h"
-#include "monitormanager.h"
 #include "smallruler.h"
 #include "docclipbase.h"
 #include "abstractclipitem.h"
 
 
 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),
@@ -185,8 +182,6 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget
     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)));
@@ -230,7 +225,7 @@ QWidget *Monitor::container()
     return m_videoBox;
 }
 
-QString Monitor::name() const
+const QString Monitor::name() const
 {
     return m_name;
 }
@@ -590,14 +585,12 @@ void Monitor::slotExtractCurrentFrame()
 
 bool Monitor::isActive() const
 {
-    return m_isActive;
+    return m_monitorManager->isActive(m_name);
 }
 
 void Monitor::activateMonitor()
 {
-    if (!m_isActive) {
-        m_monitorManager->slotSwitchMonitors(m_name == "clip");
-    }
+    m_monitorManager->activateMonitor(m_name);
 }
 
 void Monitor::setTimePos(const QString &pos)
@@ -613,7 +606,7 @@ void Monitor::slotSeek()
 
 void Monitor::slotSeek(int pos)
 {
-    activateMonitor();
+    //activateMonitor();
     if (render == NULL) return;
     render->seekToFrame(pos);
 }
@@ -706,7 +699,7 @@ void Monitor::slotForwardOneFrame(int diff)
 
 void Monitor::seekCursor(int pos)
 {
-    activateMonitor();
+    //activateMonitor();
     if (m_ruler->slotNewValue(pos)) {
         checkOverlay();
         m_timePos->setValue(pos);
@@ -737,21 +730,19 @@ 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 (render) render->start();
     connect(render, SIGNAL(rendererPosition(int)), this, SLOT(seekCursor(int)));
 }
 
 void Monitor::refreshMonitor(bool visible)
 {
-    if (visible && render && !m_isActive) {
+    if (visible && render) {
         activateMonitor();
         render->doRefresh(); //askForRefresh();
     }
@@ -759,7 +750,7 @@ void Monitor::refreshMonitor(bool visible)
 
 void Monitor::refreshMonitor()
 {
-    if (m_isActive) {
+    if (isActive()) {
         render->doRefresh();
     }
 }
@@ -1028,6 +1019,11 @@ void Monitor::slotShowVolume()
     m_volumePopup->show();
 }
 
+AbstractRender *Monitor::abstractRender()
+{
+    return render;
+}
+
 MonitorRefresh::MonitorRefresh(QWidget* parent) :
     QWidget(parent)
     , m_renderer(NULL)
index ff959c809c2d9d688ecb4ffc82c6f50022a0fdea..6e06f685bf08f9ec8558b92179643f55571fc39c 100644 (file)
@@ -22,7 +22,9 @@
 
 
 #include "gentime.h"
+#include "renderer.h"
 #include "timecodedisplay.h"
+#include "abstractmonitor.h"
 #if defined(Q_WS_MAC) || defined(USE_OPEN_GL)
 #include "videoglwidget.h"
 #endif
 #include <KAction>
 #include <KRestrictedLine>
 
-
-class MonitorManager;
-class Render;
 class SmallRuler;
 class DocClipBase;
 class AbstractClipItem;
 class Transition;
 class ClipItem;
 class MonitorEditWidget;
-
 class Monitor;
+class MonitorManager;
 
 class VideoContainer : public QFrame
 {
@@ -106,16 +105,17 @@ signals:
     void editMarker();
 };
 
-class Monitor : public QWidget
+class Monitor : public AbstractMonitor
 {
     Q_OBJECT
 
 public:
     Monitor(QString name, MonitorManager *manager, QString profile = QString(), QWidget *parent = 0);
-    virtual ~Monitor();
+    ~Monitor();
     Render *render;
+    AbstractRender *abstractRender();
     void resetProfile(const QString profile);
-    QString name() const;
+    const QString name() const;
     void resetSize();
     bool isActive() const;
     void pause();
@@ -154,7 +154,6 @@ private:
     DocClipBase *m_currentClip;
     SmallRuler *m_ruler;
     Overlay *m_overlay;
-    bool m_isActive;
     double m_scale;
     int m_length;
     bool m_dragStarted;
index 09eb326f91d1e8c8b37eb8eddd8406cbb3ce1a97..af5a14cd39e2f539e98d6afc8b132c1890d6e19b 100644 (file)
@@ -32,6 +32,7 @@ MonitorManager::MonitorManager(QWidget *parent) :
         QObject(parent),
         m_clipMonitor(NULL),
         m_projectMonitor(NULL),
+        m_activeMonitor(NULL),
         m_blocked(false)
 {
 }
@@ -41,31 +42,51 @@ Timecode MonitorManager::timecode()
     return m_timecode;
 }
 
-void MonitorManager::initMonitors(Monitor *clipMonitor, Monitor *projectMonitor)
+void MonitorManager::initMonitors(Monitor *clipMonitor, Monitor *projectMonitor, RecMonitor *recMonitor)
 {
     m_clipMonitor = clipMonitor;
     m_projectMonitor = projectMonitor;
+
+    m_monitorsList.append(clipMonitor);
+    m_monitorsList.append(projectMonitor);
+    m_monitorsList.append(recMonitor);
+}
+
+void MonitorManager::appendMonitor(AbstractMonitor *monitor)
+{
+    if (!m_monitorsList.contains(monitor)) m_monitorsList.append(monitor);
+}
+
+void MonitorManager::removeMonitor(AbstractMonitor *monitor)
+{
+    m_monitorsList.removeAll(monitor);
 }
 
 void MonitorManager::activateMonitor(QString name)
 {
+    kDebug()<<"//ACTIVATING MON: "<<name;
     if (m_blocked || m_clipMonitor == NULL || m_projectMonitor == NULL)
         return;
-    if (m_activeMonitor == name)
+    if (m_activeMonitor && m_activeMonitor->name() == name)
         return;
-    if (name == "clip") {
-        m_projectMonitor->stop();
-        m_clipMonitor->start();
-        emit raiseClipMonitor(true);
-    } else {
-        m_clipMonitor->stop();
-        m_projectMonitor->start();
-        emit raiseClipMonitor(false);
+    m_activeMonitor = NULL;
+    for (int i = 0; i < m_monitorsList.count(); i++) {
+        kDebug()<<"PARSING: "<<m_monitorsList.at(i)->name();
+        if (m_monitorsList.at(i)->name() == name) {
+            m_activeMonitor = m_monitorsList.at(i);
+            emit raiseMonitor(m_activeMonitor);
+        }
+        else m_monitorsList.at(i)->stop();
     }
-    m_activeMonitor = name;
+    if (m_activeMonitor) m_activeMonitor->start();
     emit checkColorScopes();
 }
 
+bool MonitorManager::isActive(const QString name) const
+{
+    return m_activeMonitor ? m_activeMonitor->name() == name: false;
+}
+
 void MonitorManager::slotSwitchMonitors(bool activateClip)
 {
     if (activateClip)
@@ -77,78 +98,78 @@ void MonitorManager::slotSwitchMonitors(bool activateClip)
 void MonitorManager::stopActiveMonitor()
 {
     if (m_blocked) return;
-    if (m_clipMonitor->isActive()) m_clipMonitor->pause();
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->pause();
     else m_projectMonitor->pause();
 }
 
 void MonitorManager::slotPlay()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotPlay();
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotPlay();
     else m_projectMonitor->slotPlay();
 }
 
 void MonitorManager::slotPause()
 {
-  stopActiveMonitor();
+    stopActiveMonitor();
 }
 
 void MonitorManager::slotPlayZone()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotPlayZone();
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotPlayZone();
     else m_projectMonitor->slotPlayZone();
 }
 
 void MonitorManager::slotLoopZone()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotLoopZone();
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotLoopZone();
     else m_projectMonitor->slotLoopZone();
 }
 
 void MonitorManager::slotRewind(double speed)
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotRewind(speed);
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotRewind(speed);
     else m_projectMonitor->slotRewind(speed);
 }
 
 void MonitorManager::slotForward(double speed)
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotForward(speed);
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotForward(speed);
     else m_projectMonitor->slotForward(speed);
 }
 
 void MonitorManager::slotRewindOneFrame()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotRewindOneFrame();
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotRewindOneFrame();
     else m_projectMonitor->slotRewindOneFrame();
 }
 
 void MonitorManager::slotForwardOneFrame()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotForwardOneFrame();
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotForwardOneFrame();
     else m_projectMonitor->slotForwardOneFrame();
 }
 
 void MonitorManager::slotRewindOneSecond()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotRewindOneFrame(m_timecode.fps());
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotRewindOneFrame(m_timecode.fps());
     else m_projectMonitor->slotRewindOneFrame(m_timecode.fps());
 }
 
 void MonitorManager::slotForwardOneSecond()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotForwardOneFrame(m_timecode.fps());
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotForwardOneFrame(m_timecode.fps());
     else m_projectMonitor->slotForwardOneFrame(m_timecode.fps());
 }
 
 void MonitorManager::slotStart()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotStart();
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotStart();
     else m_projectMonitor->slotStart();
 }
 
 void MonitorManager::slotEnd()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->slotEnd();
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->slotEnd();
     else m_projectMonitor->slotEnd();
 }
 
@@ -164,7 +185,7 @@ void MonitorManager::slotResetProfiles()
 {
     if (m_blocked) return;
     if (m_projectMonitor == NULL || m_clipMonitor == NULL) return;
-    QString active = m_activeMonitor;
+    QString active = m_activeMonitor ? m_activeMonitor->name() : QString();
     activateMonitor("clip");
     m_clipMonitor->resetProfile(KdenliveSettings::current_profile());
     m_clipMonitor->updateTimecodeFormat();
@@ -172,12 +193,12 @@ void MonitorManager::slotResetProfiles()
     m_projectMonitor->resetProfile(KdenliveSettings::current_profile());
     m_projectMonitor->updateTimecodeFormat();
     //m_projectMonitor->refreshMonitor(true);
-    activateMonitor(active);
+    if (!active.isEmpty()) activateMonitor(active);
 }
 
 void MonitorManager::slotRefreshCurrentMonitor()
 {
-    if (m_clipMonitor->isActive()) m_clipMonitor->refreshMonitor();
+    if (m_activeMonitor == m_clipMonitor) m_clipMonitor->refreshMonitor();
     else m_projectMonitor->refreshMonitor();
 }
 
@@ -192,4 +213,15 @@ void MonitorManager::slotUpdateAudioMonitoring()
     }
 }
 
+void MonitorManager::updateScopeSource()
+{
+    emit checkColorScopes();
+}
+
+AbstractRender *MonitorManager::activeRenderer()
+{
+    if (m_activeMonitor) return m_activeMonitor->abstractRender();
+    return NULL;
+}
+
 #include "monitormanager.moc"
index 625bc6bfc98197ea5d2d6b1b5dbb4e2b02129564..9352f4d70356c74bbba4968bf17650502b25554b 100644 (file)
@@ -22,9 +22,9 @@
 #define MONITORMANAGER_H
 
 #include "monitor.h"
+#include "recmonitor.h"
 #include "timecode.h"
 
-class Monitor;
 
 class MonitorManager : public QObject
 {
@@ -32,16 +32,21 @@ class MonitorManager : public QObject
 
 public:
     MonitorManager(QWidget *parent = 0);
-    void initMonitors(Monitor *clipMonitor, Monitor *projectMonitor);
+    void initMonitors(Monitor *clipMonitor, Monitor *projectMonitor, RecMonitor *recMonitor);
+    void appendMonitor(AbstractMonitor *monitor);
+    void removeMonitor(AbstractMonitor *monitor);
     Timecode timecode();
     void resetProfiles(Timecode tc);
     void stopActiveMonitor();
+    AbstractRender *activeRenderer();
+    void updateScopeSource();
 
 public slots:
 
     /** @brief Activates a monitor.
      * @param name name of the monitor to activate */
     void activateMonitor(QString name = QString());
+    bool isActive(const QString name) const;
     void slotPlay();
     void slotPause();
     void slotPlayZone();
@@ -68,13 +73,14 @@ private slots:
 private:
     Monitor *m_clipMonitor;
     Monitor *m_projectMonitor;
-    QString m_activeMonitor;
     Timecode m_timecode;
+    AbstractMonitor *m_activeMonitor;
     bool m_blocked;
+    QList <AbstractMonitor *>m_monitorsList;
 
 signals:
     /** @brief Emitted when the active monitor changes */
-    void raiseClipMonitor(bool);
+    void raiseMonitor(AbstractMonitor *);
     /** @brief When the monitor changed, update the visible color scopes */
     void checkColorScopes();
 
index 557f6f7cdb4352b0cc7f552f0d09f1d4915e20eb..c9aa53c29f53d02588d7f7c357910ade2a2df235 100644 (file)
@@ -490,15 +490,17 @@ QString ProfilesDialog::getPathFromDescription(const QString profileDesc)
 }
 
 // static
-void ProfilesDialog::saveProfile(MltVideoProfile &profile)
+void ProfilesDialog::saveProfile(MltVideoProfile &profile, QString profilePath)
 {
-    int i = 0;
-    QString customName = "profiles/customprofile";
-    QString profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
-    kDebug() << " TYING PROFILE FILE: " << profilePath;
-    while (KIO::NetAccess::exists(KUrl(profilePath), KIO::NetAccess::SourceSide, 0)) {
-        i++;
+    if (profilePath.isEmpty()) {
+        int i = 0;
+        QString customName = "profiles/customprofile";
         profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
+        kDebug() << " TYING PROFILE FILE: " << profilePath;
+        while (KIO::NetAccess::exists(KUrl(profilePath), KIO::NetAccess::SourceSide, 0)) {
+            i++;
+            profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
+        }
     }
     QFile file(profilePath);
     if (!file.open(QIODevice::WriteOnly)) {
@@ -569,6 +571,15 @@ QString ProfilesDialog::getColorspaceDescription(int colorspace)
     }
 }
 
+//static
+int ProfilesDialog::getColorspaceFromDescription(const QString &description)
+{
+    //TODO: should the descriptions be translated?
+    if (description == "SMPTE240M") return 240;
+    if (description == "ITU-R 709") return 709;
+    return 601;
+}
+
 #include "profilesdialog.moc"
 
 
index a9927babaa901bfda785a0054e3cc248a7cc3885..ada0736a6fc0642d92ca16085f7b91a1b961bae1 100644 (file)
@@ -38,7 +38,7 @@ public:
     static QString getPathFromDescription(const QString profileDesc);
     static MltVideoProfile getVideoProfile(QString name);
     static QMap <QString, QString> getProfilesInfo();
-    static void saveProfile(MltVideoProfile &profile);
+    static void saveProfile(MltVideoProfile &profile, QString profilePath = QString());
     static QString existingProfile(MltVideoProfile profile);
     static bool existingProfileDescription(const QString &desc);
 
@@ -72,6 +72,11 @@ public:
      *  @return The string description */
     static QString getColorspaceDescription(int colorspace);
 
+    /** @brief Get the colorspace code (defined by MLT) from a descriptive text
+     *  @param desctiption A string description as defined in getColorspaceDescription(int colorspace)
+     *  @return The int code */
+    static int getColorspaceFromDescription(const QString &description);
+
 protected:
     virtual void closeEvent(QCloseEvent *event);
 
index 51e9b1bf202df2d50989b20e5f2a2ff851bfb0a1..ba38afcbe1a262ebf0706c8709ca30fac3a3ce03 100644 (file)
 
 #include "recmonitor.h"
 #include "gentime.h"
+#include "mltdevicecapture.h"
 #include "kdenlivesettings.h"
 #include "managecapturesdialog.h"
+#include "monitormanager.h"
+#include "monitor.h"
+#include "profilesdialog.h"
 
 #include <KDebug>
 #include <KLocale>
-#include <QPainter>
 #include <KStandardDirs>
 #include <KComboBox>
 #include <KIO/NetAccess>
 #include <QDir>
 
 
-RecMonitor::RecMonitor(QString name, QWidget *parent) :
-    QWidget(parent),
+RecMonitor::RecMonitor(QString name, MonitorManager *manager, QWidget *parent) :
+    AbstractMonitor(parent),
     m_name(name),
-    m_isActive(false),
     m_isCapturing(false),
     m_didCapture(false),
     m_isPlaying(false),
     m_bmCapture(NULL),
-    m_blackmagicCapturing(false)
+    m_blackmagicCapturing(false),
+    m_manager(manager),
+    m_captureDevice(NULL),
+    m_analyse(false)
 {
     setupUi(this);
 
@@ -60,6 +65,16 @@ RecMonitor::RecMonitor(QString name, QWidget *parent) :
     device_selector->setCurrentIndex(KdenliveSettings::defaultcapture());
     connect(device_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(slotVideoDeviceChanged(int)));
 
+    // Video widget holder
+    QVBoxLayout *l = new QVBoxLayout;
+    l->setContentsMargins(0, 0, 0, 0);
+    l->setSpacing(0);
+    m_videoBox = new VideoPreviewContainer();
+    m_videoBox->setContentsMargins(0, 0, 0, 0);
+    m_videoBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+    l->addWidget(m_videoBox);
+    video_frame->setLayout(l);
+
     QToolBar *toolbar = new QToolBar(this);
     QHBoxLayout *layout = new QHBoxLayout;
     layout->setContentsMargins(0, 0, 0, 0);
@@ -134,14 +149,6 @@ RecMonitor::RecMonitor(QString name, QWidget *parent) :
 
     m_displayProcess->setEnvironment(env);
 
-    if (KdenliveSettings::video4capture().isEmpty()) {
-        QString captureCommand;
-        if (!KdenliveSettings::video4adevice().isEmpty()) captureCommand = "-f " + KdenliveSettings::video4aformat() + " -i " + KdenliveSettings::video4adevice() + " -acodec " + KdenliveSettings::video4acodec();
-
-        captureCommand +=  " -f " + KdenliveSettings::video4vformat() + " -s " + KdenliveSettings::video4size() + " -r " + QString::number(KdenliveSettings::video4rate()) + " -i " + KdenliveSettings::video4vdevice() + " -vcodec " + KdenliveSettings::video4vcodec();;
-        KdenliveSettings::setVideo4capture(captureCommand);
-    }
-
     kDebug() << "/////// BUILDING MONITOR, ID: " << video_frame->winId();
 }
 
@@ -152,13 +159,23 @@ RecMonitor::~RecMonitor()
 #endif
     delete m_captureProcess;
     delete m_displayProcess;
+    if (m_captureDevice) delete m_captureDevice;
 }
 
-QString RecMonitor::name() const
+const QString RecMonitor::name() const
 {
     return m_name;
 }
 
+void RecMonitor::stop()
+{
+    slotStopCapture();
+}
+
+void RecMonitor::start()
+{
+}
+
 void RecMonitor::slotConfigure()
 {
     emit showConfigDialog(4, device_selector->currentIndex());
@@ -187,10 +204,16 @@ void RecMonitor::slotVideoDeviceChanged(int ix)
     QString capturename;
     video_capture->setHidden(true);
     video_frame->setHidden(false);
-    m_fwdAction->setVisible(ix != BLACKMAGIC);
-    m_discAction->setVisible(ix != BLACKMAGIC);
-    m_rewAction->setVisible(ix != BLACKMAGIC);
+    m_fwdAction->setVisible(ix == FIREWIRE);
+    m_discAction->setVisible(ix == FIREWIRE);
+    m_rewAction->setVisible(ix == FIREWIRE);
     m_logger.setVisible(ix == BLACKMAGIC);
+    if (m_captureDevice) {
+        // MLT capture still running, abort
+        m_captureDevice->stop();
+        //delete m_captureDevice;
+        //m_captureDevice = NULL;
+    }
     switch (ix) {
     case SCREENGRAB:
         m_discAction->setEnabled(false);
@@ -365,6 +388,12 @@ void RecMonitor::slotStopCapture()
         m_isPlaying = false;
         break;
     case VIDEO4LINUX:
+        if (m_captureDevice) {
+            m_captureDevice->stop();
+        }
+        m_playAction->setEnabled(true);
+        m_stopAction->setEnabled(false);
+        break;
     case SCREENGRAB:
         m_captureProcess->write("q\n", 3);
         QTimer::singleShot(1000, m_captureProcess, SLOT(kill()));
@@ -401,6 +430,9 @@ void RecMonitor::slotStartCapture(bool play)
     m_displayArgs.clear();
     m_isPlaying = false;
     QString capturename = KdenliveSettings::dvgrabfilename();
+    QString path;
+    MltVideoProfile profile;
+    QString producer;
     QStringList dvargs = KdenliveSettings::dvgrabextra().simplified().split(" ", QString::SkipEmptyParts);
     video_capture->setVisible(device_selector->currentIndex() == BLACKMAGIC);
     video_frame->setHidden(device_selector->currentIndex() == BLACKMAGIC);
@@ -449,11 +481,32 @@ void RecMonitor::slotStartCapture(bool play)
         m_discAction->setEnabled(true);
         break;
     case VIDEO4LINUX:
-        m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << KdenliveSettings::video4encoding().simplified().split(' ') << "-f" << KdenliveSettings::video4container() << "-";
+        path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+        m_manager->activateMonitor("record");
+        if (m_captureDevice == NULL) {
+            m_captureDevice = new MltDeviceCapture(path, m_videoBox, this);
+            m_captureDevice->sendFrameForAnalysis = m_analyse;
+            m_manager->updateScopeSource();
+        }
+        profile = ProfilesDialog::getVideoProfile(path);
+        producer = QString("avformat-novalidate:video4linux2:%1?width:%2&height:%3&frame_rate:%4").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) profile.frame_rate_num / profile.frame_rate_den);
+        kDebug()<< "PROD: "<<producer;
+        if (!m_captureDevice->slotStartPreview(producer)) {
+            // v4l capture failed to start
+            video_frame->setText(i18n("Failed to start Video4Linux,\ncheck your parameters..."));
+            m_videoBox->setHidden(true);
+            
+        } else {
+            m_videoBox->setHidden(false);
+            m_playAction->setEnabled(false);
+            m_stopAction->setEnabled(true);
+        }
+        
+        /*m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << KdenliveSettings::video4encoding().simplified().split(' ') << "-f" << KdenliveSettings::video4container() << "-";
         m_displayArgs << "-f" << KdenliveSettings::video4container() << "-x" << QString::number(video_frame->width()) << "-y" << QString::number(video_frame->height()) << "-";
         m_captureProcess->setStandardOutputProcess(m_displayProcess);
         kDebug() << "Capture: Running ffmpeg " << m_captureArgs.join(" ");
-        m_captureProcess->start("ffmpeg", m_captureArgs);
+        m_captureProcess->start("ffmpeg", m_captureArgs);*/
         break;
     case BLACKMAGIC:
         m_bmCapture->startPreview(KdenliveSettings::hdmi_capturedevice(), KdenliveSettings::hdmi_capturemode());
@@ -465,7 +518,7 @@ void RecMonitor::slotStartCapture(bool play)
         break;
     }
 
-    if (device_selector->currentIndex() == FIREWIRE || device_selector->currentIndex() == VIDEO4LINUX) {
+    if (device_selector->currentIndex() == FIREWIRE) {
         kDebug() << "Capture: Running ffplay " << m_displayArgs.join(" ");
         m_displayProcess->start("ffplay", m_displayArgs);
         video_frame->setText(i18n("Initialising..."));
@@ -505,10 +558,11 @@ void RecMonitor::slotRecord()
             m_recAction->setChecked(false);
             break;
         case VIDEO4LINUX:
-            m_captureProcess->terminate();
             slotStopCapture();
-            //m_isCapturing = false;
-            QTimer::singleShot(1000, this, SLOT(slotStartCapture()));
+            m_isCapturing = false;
+            m_recAction->setChecked(false);
+            if (autoaddbox->isChecked() && QFile::exists(m_captureFile.path())) emit addProjectClip(m_captureFile);
+            //QTimer::singleShot(1000, this, SLOT(slotStartCapture()));
             break;
         case SCREENGRAB:
             //captureProcess->write("q\n", 3);
@@ -532,12 +586,12 @@ void RecMonitor::slotRecord()
         m_recAction->setChecked(true);
         QString extension = "mp4";
         if (device_selector->currentIndex() == SCREENGRAB) extension = "ogv"; //KdenliveSettings::screengrabextension();
-        else if (device_selector->currentIndex() == VIDEO4LINUX) extension = KdenliveSettings::video4extension();
-        QString path = m_capturePath + "/capture0000." + extension;
+        else if (device_selector->currentIndex() == VIDEO4LINUX) extension = KdenliveSettings::v4l_extension();
+        QString path = KUrl(m_capturePath).path(KUrl::AddTrailingSlash) + "capture0000." + extension;
         int i = 1;
         while (QFile::exists(path)) {
             QString num = QString::number(i).rightJustified(4, '0', false);
-            path = m_capturePath + "/capture" + num + '.' + extension;
+            path = KUrl(m_capturePath).path(KUrl::AddTrailingSlash) + "capture" + num + '.' + extension;
             i++;
         }
         m_captureFile = KUrl(path);
@@ -545,16 +599,57 @@ void RecMonitor::slotRecord()
         m_captureArgs.clear();
         m_displayArgs.clear();
         QString args;
+        QString playlist;
+        MltVideoProfile profile;
         QString capturename = KdenliveSettings::dvgrabfilename();
         if (capturename.isEmpty()) capturename = "capture";
 
         switch (device_selector->currentIndex()) {
         case VIDEO4LINUX:
+            path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+            profile = ProfilesDialog::getVideoProfile(path);
+            if (m_captureDevice == NULL) {
+                m_captureDevice = new MltDeviceCapture(path, m_videoBox, this);
+                m_captureDevice->sendFrameForAnalysis = m_analyse;
+                m_manager->updateScopeSource();
+            }
+            playlist = QString("<mlt title=\"capture\"><producer id=\"producer0\" in=\"0\" out=\"99999\"><property name=\"mlt_type\">producer</property><property name=\"length\">100000</property><property name=\"eof\">pause</property><property name=\"resource\">video4linux2:%1?width:%2&amp;height:%3&amp;frame_rate:%4</property><property name=\"mlt_service\">avformat-novalidate</property></producer><playlist id=\"playlist0\"><entry producer=\"producer0\" in=\"0\" out=\"99999\"/></playlist>").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) profile.frame_rate_num / profile.frame_rate_den);
+
+            // Add alsa audio capture
+            if (KdenliveSettings::v4l_captureaudio()) {
+                playlist.append(QString("<producer id=\"producer1\" in=\"0\" out=\"99999\"><property name=\"mlt_type\">producer</property><property name=\"length\">100000</property><property name=\"eof\">pause</property><property name=\"resource\">alsa:%5</property><property name=\"audio_index\">0</property><property name=\"video_index\">-1</property><property name=\"mlt_service\">avformat</property></producer><playlist id=\"playlist1\"><entry producer=\"producer1\" in=\"0\" out=\"99999\"/></playlist>").arg(KdenliveSettings::v4l_alsadevicename()));
+            }
+            
+
+            playlist.append("<tractor id=\"tractor0\" title=\"video0\" global_feed=\"1\" in=\"0\" out=\"99999\">");
+
+            playlist.append("<track producer=\"playlist0\"/>");            
+
+            // Audio mix
+            if (KdenliveSettings::v4l_captureaudio()) {
+                playlist.append("<track producer=\"playlist1\"/>");
+                playlist.append("<transition id=\"transition0\" in=\"0\" out=\"0\"><property name=\"a_track\">0</property><property name=\"b_track\">1</property><property name=\"mlt_type\">transition</property><property name=\"mlt_service\">mix</property></transition>");
+            }
+
+            playlist.append("</tractor></mlt>");
+
+            if (m_captureDevice->slotStartCapture(KdenliveSettings::v4l_parameters(), m_captureFile.path(), playlist)) {
+                m_videoBox->setHidden(false);
+                m_isCapturing = true;
+            }
+            else {
+                video_frame->setText(i18n("Failed to start Video4Linux,\ncheck your parameters..."));                
+                m_videoBox->setHidden(true);
+                m_isCapturing = false;
+                m_recAction->setChecked(false);
+            }
+
+            /*
             m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << KdenliveSettings::video4encoding().simplified().split(' ') << "-y" << m_captureFile.path() << "-f" << KdenliveSettings::video4container() << "-acodec" << KdenliveSettings::video4acodec() << "-vcodec" << KdenliveSettings::video4vcodec() << "-";
             m_displayArgs << "-f" << KdenliveSettings::video4container() << "-x" << QString::number(video_frame->width()) << "-y" << QString::number(video_frame->height()) << "-";
             m_captureProcess->setStandardOutputProcess(m_displayProcess);
             kDebug() << "Capture: Running ffmpeg " << m_captureArgs.join(" ");
-            m_captureProcess->start("ffmpeg", m_captureArgs);
+            m_captureProcess->start("ffmpeg", m_captureArgs);*/
             break;
         case SCREENGRAB:
             switch (KdenliveSettings::rmd_capture_type()) {
@@ -606,7 +701,7 @@ void RecMonitor::slotRecord()
         }
 
 
-        if (device_selector->currentIndex() != SCREENGRAB) {
+        if (device_selector->currentIndex() == FIREWIRE) {
             m_isCapturing = true;
             kDebug() << "Capture: Running ffplay " << m_displayArgs.join(" ");
             m_displayProcess->start("ffplay", m_displayArgs);
@@ -759,23 +854,6 @@ void RecMonitor::slotUpdateFreeSpace()
 #endif
 }
 
-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) {
@@ -799,5 +877,18 @@ void RecMonitor::slotReadDvgrabInfo()
     m_dvinfo.updateGeometry();
 }
 
+AbstractRender *RecMonitor::abstractRender()
+{
+    return m_captureDevice;
+}
+
+
+void RecMonitor::analyseFrames(bool analyse)
+{
+    m_analyse = analyse;
+    if (m_captureDevice) m_captureDevice->sendFrameForAnalysis = analyse;
+}
+
+
 #include "recmonitor.moc"
 
index 79befd52336e2ba931917ddc05068c8e0602bdfc..c61b8041f6eb2dc8c3f88ac3a1e42d116a6d6773 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef RECMONITOR_H
 #define RECMONITOR_H
 
+#include "abstractmonitor.h"
 #include "blackmagic/capture.h"
 #include "ui_recmonitor_ui.h"
 
 #include <kcapacitybar.h>
 #endif
 
-class RecMonitor : public QWidget, public Ui::RecMonitor_UI
+class MonitorManager;
+class MltDeviceCapture;
+class AbstractRender;
+
+class RecMonitor : public AbstractMonitor, public Ui::RecMonitor_UI
 {
     Q_OBJECT
 
 public:
-    explicit RecMonitor(QString name, QWidget *parent = 0);
+    explicit RecMonitor(QString name, MonitorManager *manager, QWidget *parent = 0);
     virtual ~RecMonitor();
 
-    QString name() const;
-
+    const QString name() const;
+    AbstractRender *abstractRender();
+    void analyseFrames(bool analyse);
     enum CAPTUREDEVICE {FIREWIRE = 0, VIDEO4LINUX = 1, SCREENGRAB = 2, BLACKMAGIC = 3};
 
 protected:
@@ -62,7 +68,6 @@ protected:
 
 private:
     QString m_name;
-    bool m_isActive;
     KDateTime m_captureTime;
     /** @brief Provide feedback about dvgrab operations */
     QLabel m_dvinfo;
@@ -95,17 +100,22 @@ private:
     QAction *m_rewAction;
     QAction *m_stopAction;
     QAction *m_discAction;
-    void checkDeviceAvailability();
-    QPixmap mergeSideBySide(const QPixmap& pix, const QString txt);
-    void manageCapturedFiles();
+
+
     CaptureHandler *m_bmCapture;
     /** @brief Indicates whether we are currently capturing from BLACKMAGIC. */
     bool m_blackmagicCapturing;
+    MonitorManager *m_manager;
+    MltDeviceCapture *m_captureDevice;
+    VideoPreviewContainer *m_videoBox;
+    bool m_analyse;
+    void checkDeviceAvailability();
+    QPixmap mergeSideBySide(const QPixmap& pix, const QString txt);
+    void manageCapturedFiles();
     void createBlackmagicDevice();
 
 private slots:
     void slotStartCapture(bool play = true);
-    void slotStopCapture();
     void slotRecord();
     void slotProcessStatus(QProcess::ProcessState status);
     void slotVideoDeviceChanged(int ix);
@@ -121,10 +131,10 @@ private slots:
 
 public slots:
     void refreshRecMonitor(bool visible);
+    void slotPlay();
     void stop();
     void start();
-    void activateRecMonitor();
-    void slotPlay();
+    void slotStopCapture();
     void slotUpdateCaptureFolder(const QString currentProjectFolder);
 
 signals:
index e9f2dc6ea897a8781da4f26915a6be4532e5be81..e6324a1f4d01a3201271f9a41557c1f0a67d5044 100644 (file)
@@ -94,10 +94,9 @@ static void consumer_gl_frame_show(mlt_consumer, Render * self, mlt_frame frame_
 }
 
 Render::Render(const QString & rendererName, int winid, QString profile, QWidget *parent) :
-    QObject(parent),
+    AbstractRender(parent),
     m_isBlocked(0),
     analyseAudio(KdenliveSettings::monitor_audio()),
-    sendFrameForAnalysis(false),
     m_name(rendererName),
     m_mltConsumer(NULL),
     m_mltProducer(NULL),
@@ -1267,7 +1266,6 @@ void Render::stop()
     if (m_mltProducer == NULL) return;
     if (m_mltConsumer && !m_mltConsumer->is_stopped()) {
         kDebug() << "/////////////   RENDER STOPPED: " << m_name;
-        m_isBlocked = true;
         //m_mltConsumer->set("refresh", 0);
         m_mltConsumer->stop();
         // delete m_mltConsumer;
index b20afea559e09d92264e583824bed2cc51ade133..2d0a2189f389fae649e827934785a71ecfdccb5b 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "gentime.h"
 #include "definitions.h"
+#include "abstractmonitor.h"
 #include "mlt/framework/mlt_types.h"
 
 #include <kurl.h>
@@ -42,8 +43,6 @@
 #include <QEvent>
 
 
-class Render;
-
 class QTimer;
 class QPixmap;
 
@@ -73,7 +72,8 @@ private:
     QString m_message;
 };
 
-class Render: public QObject
+
+class Render: public AbstractRender
 {
 Q_OBJECT public:
 
@@ -87,7 +87,7 @@ Q_OBJECT public:
     Render(const QString & rendererName, int winid, QString profile = QString(), QWidget *parent = 0);
 
     /** @brief Destroy the MLT Renderer. */
-    ~Render();
+    virtual ~Render();
 
     /** @brief Seeks the renderer clip to the given time. */
     void seek(GenTime time);
@@ -260,8 +260,7 @@ Q_OBJECT public:
     void showAudio(Mlt::Frame&);
     /** @brief This property is used to decide if the renderer should send audio data for monitoring. */
     bool analyseAudio;
-    /** @brief This property is used to decide if the renderer should convert it's frames to QImage for use in other Kdenlive widgets. */
-    bool sendFrameForAnalysis;
+    
     QList <int> checkTrackSequence(int);
     void sendFrameUpdate();
 
@@ -364,10 +363,6 @@ signals:
      * Used in Mac OS X. */
     void showImageSignal(QImage);
     void showAudioSignal(const QByteArray);
-    /** @brief The renderer refreshed the current frame, but no seeking was done. */
-    void frameUpdated(QImage);
-    /** @brief This signal contains the audio of the current frame. */
-    void audioSamplesSignal(const QVector<int16_t>&, int freq, int num_channels, int num_samples);
 
 public slots:
 
index 6c8f535e286ed54db9e6a27ab48188d13fd880d8..c93a15acae959f0dde0656cabfe7f2d8027844e0 100644 (file)
 #include "../blackmagic/devices.h"
 #include "../v4l/v4lcapture.h"
 #include "../slideshowclip.h"
+#include "../profilesdialog.h"
+#include "../mltdevicecapture.h"
+#include "../recmonitor.h"
+#include "../monitormanager.h"
 #include "ui_smconfig_ui.h"
 #include "kdenlivesettings.h"
 
@@ -90,16 +94,58 @@ void MyLabel::paintEvent(QPaintEvent* event)
 }
 
 
-StopmotionWidget::StopmotionWidget(KUrl projectFolder, QList< QAction* > actions, QWidget* parent) :
+StopmotionMonitor::StopmotionMonitor(QWidget *parent) :
+    AbstractMonitor(parent),
+    m_captureDevice(NULL)
+{
+}
+
+StopmotionMonitor::~StopmotionMonitor()
+{
+}
+
+void StopmotionMonitor::setRender(MltDeviceCapture *render)
+{
+    m_captureDevice = render;
+}
+
+AbstractRender *StopmotionMonitor::abstractRender()
+{
+    return m_captureDevice;
+}
+
+const QString StopmotionMonitor::name() const
+{
+    return QString("stopmotion");
+}
+
+
+void StopmotionMonitor::stop()
+{
+    if (m_captureDevice) m_captureDevice->stop();
+    emit stopCapture();
+}
+
+void StopmotionMonitor::start()
+{
+}
+
+StopmotionWidget::StopmotionWidget(MonitorManager *manager, KUrl projectFolder, QList< QAction* > actions, QWidget* parent) :
     QDialog(parent)
     , Ui::Stopmotion_UI()
     , m_projectFolder(projectFolder)
-    , m_bmCapture(NULL)
+    , m_captureDevice(NULL)
     , m_sequenceFrame(0)
     , m_animatedIndex(-1)
     , m_animate(false)
+    , m_manager(manager)
+    , m_monitor(new StopmotionMonitor(this))
 {
     //setAttribute(Qt::WA_DeleteOnClose);
+    //HACK: the monitor widget is hidden, it is just used to control the capturedevice from monitormanager
+    m_monitor->setHidden(true);
+    connect(m_monitor, SIGNAL(stopCapture()), this, SLOT(slotStopCapture()));
+    m_manager->appendMonitor(m_monitor);
     QAction* analyse = new QAction(i18n("Send frames to color scopes"), this);
     analyse->setCheckable(true);
     analyse->setChecked(KdenliveSettings::analyse_stopmotion());
@@ -192,20 +238,30 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, QList< QAction* > actions
     connect(sequence_name, SIGNAL(textChanged(const QString&)), this, SLOT(sequenceNameChanged(const QString&)));
     connect(sequence_name, SIGNAL(currentIndexChanged(int)), live_button, SLOT(setFocus()));
 
-    m_layout = new QVBoxLayout;
+    // Video widget holder
+    QVBoxLayout *layout = new QVBoxLayout;
+    layout->setContentsMargins(0, 0, 0, 0);
+    layout->setSpacing(0);
+    m_videoBox = new VideoPreviewContainer();
+    m_videoBox->setContentsMargins(0, 0, 0, 0);
+    m_videoBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+    //m_videoBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+    m_videoBox->setLineWidth(4);
+    layout->addWidget(m_videoBox);
+    
+    
     if (BMInterface::getBlackMagicDeviceList(capture_device, NULL)) {
         // Found a BlackMagic device
-        m_bmCapture = new BmdCaptureHandler(m_layout);
-        connect(m_bmCapture, SIGNAL(gotMessage(const QString&)), this, SLOT(slotGotHDMIMessage(const QString&)));
+        //m_bmCapture = new BmdCaptureHandler(m_layout);
+        //connect(m_bmCapture, SIGNAL(gotMessage(const QString&)), this, SLOT(slotGotHDMIMessage(const QString&)));
     }
     if (QFile::exists(KdenliveSettings::video4vdevice())) {
 #if !defined(Q_WS_MAC) && !defined(Q_OS_FREEBSD)
-        V4lCaptureHandler v4l(NULL);
         // Video 4 Linux device detection
         for (int i = 0; i < 10; i++) {
             QString path = "/dev/video" + QString::number(i);
             if (QFile::exists(path)) {
-                QStringList deviceInfo = v4l.getDeviceName(path);
+                QStringList deviceInfo = V4lCaptureHandler::getDeviceName(path);
                 if (!deviceInfo.isEmpty()) {
                     capture_device->addItem(deviceInfo.at(0), "v4l");
                     capture_device->setItemData(capture_device->count() - 1, path, Qt::UserRole + 1);
@@ -215,28 +271,36 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, QList< QAction* > actions
             }
         }
 
-        /*V4lCaptureHandler v4lhandler(NULL);
-        QStringList deviceInfo = v4lhandler.getDeviceName(KdenliveSettings::video4vdevice());
-            capture_device->addItem(deviceInfo.at(0), "v4l");
-        capture_device->setItemData(capture_device->count() - 1, deviceInfo.at(3), Qt::UserRole + 1);*/
-        if (m_bmCapture == NULL) {
-            m_bmCapture = new V4lCaptureHandler(m_layout);
-            m_bmCapture->setDevice(capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 1).toString(), capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 2).toString());
-        }
+        //if (m_bmCapture == NULL) {
+            
+            //m_captureDevice->sendFrameForAnalysis = m_analyse;
+            /*m_bmCapture = new V4lCaptureHandler(m_layout);
+            m_bmCapture->setDevice(capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 1).toString(), capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 2).toString());*/
+        //}
 #endif
     }
 
     connect(capture_device, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateHandler()));
-    if (m_bmCapture) {
+    /*if (m_bmCapture) {
         connect(m_bmCapture, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
         connect(m_bmCapture, SIGNAL(gotFrame(QImage)), this, SIGNAL(gotFrame(QImage)));
-    } else live_button->setEnabled(false);
+    } else live_button->setEnabled(false);*/
+    
     m_frame_preview = new MyLabel(this);
     connect(m_frame_preview, SIGNAL(seek(bool)), this, SLOT(slotSeekFrame(bool)));
     connect(m_frame_preview, SIGNAL(switchToLive()), this, SLOT(slotSwitchLive()));
-    m_layout->addWidget(m_frame_preview);
+    layout->addWidget(m_frame_preview);
     m_frame_preview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-    video_preview->setLayout(m_layout);
+    video_preview->setLayout(layout);
+
+    //kDebug()<<video_preview->winId();
+    
+    QString path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+    m_captureDevice = new MltDeviceCapture(path, m_videoBox, this);
+    m_captureDevice->sendFrameForAnalysis = KdenliveSettings::analyse_stopmotion();
+    m_monitor->setRender(m_captureDevice);
+    connect(m_captureDevice, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
+    
     live_button->setChecked(false);
     button_addsequence->setEnabled(false);
     connect(live_button, SIGNAL(toggled(bool)), this, SLOT(slotLive(bool)));
@@ -258,8 +322,15 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, QList< QAction* > actions
 
 StopmotionWidget::~StopmotionWidget()
 {
-    if (m_bmCapture)
-        m_bmCapture->stopPreview();
+    /*if (m_bmCapture)
+        m_bmCapture->stopPreview();*/
+    if (m_captureDevice) {
+        m_captureDevice->stop();
+        delete m_captureDevice;
+        m_captureDevice = NULL;
+    }
+
+    delete m_monitor;
 }
 
 void StopmotionWidget::slotUpdateOverlayEffect(QAction* act)
@@ -318,7 +389,7 @@ void StopmotionWidget::slotShowThumbs(bool show)
 
 void StopmotionWidget::slotUpdateHandler()
 {
-    QString data = capture_device->itemData(capture_device->currentIndex()).toString();
+    /*QString data = capture_device->itemData(capture_device->currentIndex()).toString();
     slotLive(false);
     if (m_bmCapture) {
         delete m_bmCapture;
@@ -334,7 +405,7 @@ void StopmotionWidget::slotUpdateHandler()
         if (m_bmCapture) connect(m_bmCapture, SIGNAL(gotMessage(const QString&)), this, SLOT(slotGotHDMIMessage(const QString&)));
     }
     live_button->setEnabled(m_bmCapture != NULL);
-    m_layout->addWidget(m_frame_preview);
+    m_layout->addWidget(m_frame_preview);*/
 }
 
 void StopmotionWidget::slotGotHDMIMessage(const QString& message)
@@ -360,20 +431,72 @@ void StopmotionWidget::parseExistingSequences()
 void StopmotionWidget::slotSwitchLive()
 {
     setUpdatesEnabled(false);
-    if (m_frame_preview->isHidden()) {
-        if (m_bmCapture) m_bmCapture->hidePreview(true);
+    slotLive(!live_button->isChecked());
+    /*if (m_frame_preview->isHidden()) {
+        //if (m_bmCapture) m_bmCapture->hidePreview(true);
+        m_videoBox->setHidden(true);
         m_frame_preview->setHidden(false);
     } else {
         m_frame_preview->setHidden(true);
-        if (m_bmCapture) m_bmCapture->hidePreview(false);
+        //if (m_bmCapture) m_bmCapture->hidePreview(false);
+        m_videoBox->setHidden(false);
         capture_button->setEnabled(true);
-    }
+    }*/
     setUpdatesEnabled(true);
 }
 
+void StopmotionWidget::slotStopCapture()
+{
+    slotLive(false);
+}
+
 void StopmotionWidget::slotLive(bool isOn)
 {
     live_button->blockSignals(true);
+    capture_button->setEnabled(false);
+    if (isOn) {
+        m_frame_preview->setHidden(true);
+        m_videoBox->setHidden(false);
+        QString path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+
+        kDebug()<<"SURFACE; "<<m_videoBox->width()<<"x"<<m_videoBox->height();
+        if (m_captureDevice == NULL) {
+            m_captureDevice = new MltDeviceCapture(path, m_videoBox, this);
+            m_captureDevice->sendFrameForAnalysis = KdenliveSettings::analyse_stopmotion();
+            m_monitor->setRender(m_captureDevice);
+            connect(m_captureDevice, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
+        }
+
+        MltVideoProfile profile = ProfilesDialog::getVideoProfile(path);
+        m_manager->activateMonitor("stopmotion");
+        QString producer = QString("avformat-novalidate:video4linux2:%1?width:%2&height:%3&frame_rate:%4").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) profile.frame_rate_num / profile.frame_rate_den);
+        if (m_captureDevice->slotStartPreview(producer)) {
+            kDebug()<<"// STARt CAPTURE GO";
+            capture_button->setEnabled(true);
+            live_button->setChecked(true);
+            log_box->insertItem(-1, i18n("Playing %1x%2 (%3 fps)", profile.width, profile.height, QString::number((double)profile.frame_rate_num/profile.frame_rate_den).rightJustified(2, '0')));
+            log_box->setCurrentIndex(0);
+        }
+        else {
+            kDebug()<<"// problem starting stopmo";
+            log_box->insertItem(-1, i18n("Failed to start device"));
+            log_box->setCurrentIndex(0);
+        }
+    }
+    else {
+        m_frame_preview->setHidden(false);
+        live_button->setChecked(false);
+        if (m_captureDevice) {
+            m_captureDevice->stop();
+            m_videoBox->setHidden(true);
+            log_box->insertItem(-1, i18n("Stopped"));
+            log_box->setCurrentIndex(0);
+            //delete m_captureDevice;
+            //m_captureDevice = NULL;
+        }
+    }
+            
+    /*
     if (isOn && m_bmCapture) {
         //m_frame_preview->setImage(QImage());
         m_frame_preview->setHidden(true);
@@ -385,24 +508,24 @@ void StopmotionWidget::slotLive(bool isOn)
         m_frame_preview->setHidden(false);
         capture_button->setEnabled(false);
         live_button->setChecked(false);
-    }
+    }*/
     live_button->blockSignals(false);
 }
 
-void StopmotionWidget::slotShowOverlay(bool isOn)
+void StopmotionWidget::slotShowOverlay(bool /*isOn*/)
 {
-    if (isOn) {
+/*    if (isOn) {
         if (live_button->isChecked() && m_sequenceFrame > 0) {
             slotUpdateOverlay();
         }
     } else if (m_bmCapture) {
         m_bmCapture->hideOverlay();
-    }
+    }*/
 }
 
 void StopmotionWidget::slotUpdateOverlay()
 {
-    if (m_bmCapture == NULL) return;
+    if (m_captureDevice == NULL) return;
     QString path = getPathForFrame(m_sequenceFrame - 1);
     if (!QFile::exists(path)) return;
     QImage img(path);
@@ -435,7 +558,7 @@ void StopmotionWidget::slotUpdateOverlay()
 
     }
 #endif
-    m_bmCapture->showOverlay(img);
+    //m_bmCapture->showOverlay(img);
 }
 
 void StopmotionWidget::sequenceNameChanged(const QString& name)
@@ -467,7 +590,7 @@ void StopmotionWidget::sequenceNameChanged(const QString& name)
 
 void StopmotionWidget::slotCaptureFrame()
 {
-    if (m_bmCapture == NULL) return;
+    if (m_captureDevice == NULL) return;
     if (sequence_name->currentText().isEmpty()) {
         QString seqName = QInputDialog::getText(this, i18n("Create New Sequence"), i18n("Enter sequence name"));
         if (seqName.isEmpty()) {
@@ -489,7 +612,7 @@ void StopmotionWidget::slotCaptureFrame()
         return;
     }
     QString currentPath = getPathForFrame(m_sequenceFrame);
-    m_bmCapture->captureFrame(currentPath);
+    m_captureDevice->captureFrame(currentPath);
     KNotification::event("FrameCaptured", i18n("Frame Captured"), QPixmap(), this);
     m_sequenceFrame++;
     button_addsequence->setEnabled(true);
@@ -562,7 +685,8 @@ void StopmotionWidget::slotShowFrame(const QString& path)
     capture_button->setEnabled(false);
     slotLive(false);
     if (!img.isNull()) {
-        if (m_bmCapture) m_bmCapture->hidePreview(true);
+        //m_videoBox->setHidden(true);
+        
         m_frame_preview->setImage(img);
         m_frame_preview->setHidden(false);
         m_frame_preview->update();
@@ -714,7 +838,8 @@ void StopmotionWidget::slotRemoveFrame()
 void StopmotionWidget::slotSwitchAnalyse(bool isOn)
 {
     KdenliveSettings::setAnalyse_stopmotion(isOn);
-    m_bmCapture->setAnalyse(isOn);
+    if (m_captureDevice) m_captureDevice->sendFrameForAnalysis = isOn;
+    //m_bmCapture->setAnalyse(isOn);
 }
 
 
index 9e82f28f2401fd20a20c6ae15e805dda7cd82581..dcdfa39e79124948b67041af7e755b563b9fd93e 100644 (file)
 #include <QFuture>
 #include <QVBoxLayout>
 #include <QTimer>
+#include <abstractmonitor.h>
+
+class MltDeviceCapture;
+class MonitorManager;
+class VideoPreviewContainer;
 
 class MyLabel : public QLabel
 {
@@ -51,7 +56,30 @@ signals:
     void switchToLive();
 };
 
-class StopmotionWidget : public QDialog , public Ui::Stopmotion_UI
+
+class StopmotionMonitor : public AbstractMonitor
+{
+    Q_OBJECT
+public:
+    StopmotionMonitor(QWidget *parent);
+    ~StopmotionMonitor();
+    AbstractRender *abstractRender();
+    const QString name() const;
+    void setRender(MltDeviceCapture *render);
+
+private:
+    MltDeviceCapture *m_captureDevice;
+
+public slots:
+    virtual void stop();
+    virtual void start();
+
+signals:
+    void stopCapture();
+};
+
+
+class StopmotionWidget : public QDialog, public Ui::Stopmotion_UI
 {
     Q_OBJECT
 
@@ -61,21 +89,22 @@ public:
      * @param projectFolder The current project folder, where captured files will be stored.
      * @param actions The actions for this widget that can have a keyboard shortcut.
      * @param parent (optional) parent widget */
-    StopmotionWidget(KUrl projectFolder, QList< QAction* > actions, QWidget* parent = 0);
+    StopmotionWidget(MonitorManager *manager, KUrl projectFolder, QList< QAction* > actions, QWidget* parent = 0);
     virtual ~StopmotionWidget();
 
 protected:
     virtual void closeEvent(QCloseEvent* e);
 
 private:
-    /** @brief Widget layout holding video and frame preview. */
-    QVBoxLayout* m_layout;
-
     /** @brief Current project folder (where the captured frames will be saved). */
     KUrl m_projectFolder;
 
     /** @brief Capture holder that will handle all video operation. */
-    CaptureHandler* m_bmCapture;
+    MltDeviceCapture *m_captureDevice;
+
+    VideoPreviewContainer *m_videoBox;
+    
+    //CaptureHandler* m_bmCapture;
 
     /** @brief Holds the name of the current sequence.
      * Files will be saved in project folder with name: sequence001.png */
@@ -119,6 +148,10 @@ private:
     /** @brief Timer for interval capture. */
     QTimer m_intervalTimer;
 
+    MonitorManager *m_manager;
+
+    StopmotionMonitor *m_monitor;
+
 
 #ifdef QIMAGEBLITZ
     int m_effectIndex;
@@ -128,6 +161,7 @@ public slots:
     /** @brief Display the live feed from capture device.
      @param isOn enable or disable the feature */
     void slotLive(bool isOn = true);
+    void slotStopCapture();
 
 private slots:
 
index 9cbc27fbc2d1cf5b055fc73c1995e182e227db7a..f7278236e54e9eaaf8beb8e6c6776e289ad39ba0 100644 (file)
 #include <string.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <sys/mman.h>
 #include "src.h"
 
-#ifdef HAVE_V4L2
-extern src_mod_t src_v4l2;
-#endif
-#ifdef HAVE_V4L1
-extern src_mod_t src_v4l1;
-#endif
+#include <sys/ioctl.h>
+
 
 /* Supported palette types. */
 src_palette_t src_palette[] = {
@@ -50,223 +47,141 @@ src_palette_t src_palette[] = {
 };
 
 
-int src_open(src_t *src, char *source)
-{
-       int i = 0;
-       struct stat st;
-       
-       if(!source)
-       {
-               fprintf(stderr, "No source was specified.......");
-               return(-1);
-       }
-       src->source = source;
-       
-       i = 0;
-       int r = src_v4l2.flags;
-       if(S_ISCHR(st.st_mode) && r & SRC_TYPE_DEVICE) r = -1;
-       else if(!S_ISCHR(st.st_mode) && r & SRC_TYPE_FILE) r = -1;
-       else r = 0;
-       src->type = 0;
-       r = src_v4l2.open(src);
-       if(r == -2) return(-1);
-
-       /*
-       int frame;
-       for(frame = 0; frame < config->skipframes; frame++)
-           if(src_grab(src) == -1) break;*/
-
-       return 0;
-}
 
-const char *src_query(src_t *src, char *source, uint *width, uint *height, char **pixelformatdescription)
+int v4l2_free_mmap(src_t *src)
 {
-    src->source = source;
-    return src_v4l2.query(src, width, height, pixelformatdescription);
-}
+        src_v4l2_t *s = (src_v4l2_t *) src->state;
+        int i;
 
-int src_close(src_t *src)
-{
-       int r;
-       
-       if(src->captured_frames)
-       {
-               double seconds =
-                  (src->tv_last.tv_sec  + src->tv_last.tv_usec  / 1000000.0) -
-                  (src->tv_first.tv_sec + src->tv_first.tv_usec / 1000000.0);
-               
-               /* Display FPS if enough frames where captured. */
-               if(src->captured_frames == 1)
-               {
-                       /*MSG("Captured frame in %0.2f seconds.", seconds);*/
-               }
-               else if(src->captured_frames < 3)
-               {
-                       /*MSG("Captured %i frames in %0.2f seconds.",
-                           src->captured_frames, seconds);*/
-               }
-               else
-               {
-                       /*MSG("Captured %i frames in %0.2f seconds. (%i fps)",
-                           src->captured_frames, seconds,
-                           (int) (src->captured_frames / seconds));*/
-               }
-       }
-       
-       r = src_v4l2.close(src);
-       
-       if(src->source) free(src->source);
-       
-       return(r);
-}
+        for(i = 0; i < s->req.count; i++)
+                munmap(s->buffer[i].start, s->buffer[i].length);
 
-int src_grab(src_t *src)
-{
-       int r = src_v4l2.grab(src);
-       
-       if(!r)
-       {
-               if(!src->captured_frames) gettimeofday(&src->tv_first, NULL);
-               gettimeofday(&src->tv_last, NULL);
-               
-               src->captured_frames++;
-       }
-       
-       return(r);
+        return(0);
 }
 
-/* Pointers are great things. Terrible things yes, but great. */
-/* These work but are very ugly and will be re-written soon. */
-
-int src_set_option(src_option_t ***options, char *name, char *value)
+static int close_v4l2(src_t *src)
 {
-       src_option_t **opts, *opt;
-       int count;
-       
-       if(!options) return(-1);
-       if(!*options)
-       {
-               *options = malloc(sizeof(src_option_t *));
-               if(!*options)
-               {
-                       /*ERROR("Out of memory.");*/
-                       return(-1);
-               }
-               
-               *options[0] = NULL;
-       }
-       
-       count = 0;
-       opts = *options;
-       while(*opts)
-       {
-               if((*opts)->name) if(!strcasecmp(name, (*opts)->name)) break;
-               opts++;
-               count++;
-       }
-       
-       if(!*opts)
-       {
-               void *new;
-               
-               opt = (src_option_t *) malloc(sizeof(src_option_t));
-               if(!opt)
-               {
-                       /*ERROR("Out of memory.");*/
-                       return(-1);
-               }
-               
-               new = realloc(*options, sizeof(src_option_t *) * (count + 2));
-               if(!new)
-               {
-                       free(opt);
-                       /*ERROR("Out of memory.");*/
-                       return(-1);
-               }
-               
-               *options = (src_option_t **) new;
-               (*options)[count++] = opt;
-               (*options)[count++] = NULL;
-               
-               opt->name = strdup(name);
-               opt->value = NULL;
-       }
-       else opt = *opts;
-       
-       if(opt->value)
-       {
-               free(opt->value);
-               opt->value = NULL;
-       }
-       if(value) opt->value = strdup(value);
-       
-       return(0);
+        src_v4l2_t *s = (src_v4l2_t *) src->state;
+
+        if(s->buffer)
+        {
+                if(!s->map) free(s->buffer[0].start);
+                else v4l2_free_mmap(src);
+                free(s->buffer);
+        }
+        if(s->fd >= 0) close(s->fd);
+        free(s);
+
+        return(0);
 }
 
-int src_get_option_by_number(src_option_t **opt, int number,
-                             char **name, char **value)
+//static
+const char *query_v4ldevice(src_t *src, char **pixelformatdescription)
 {
-       int i;
-       
-       if(!opt || !name || !value) return(-1);
-       
-       i = 0;
-       while(*opt)
-       {
-               if(i == number)
-               {
-                       *name  = (*opt)->name;
-                       *value = (*opt)->value;
-                       return(0);
-               }
-               
-               i++;
-       }
-       
-       return(-1);
+        if(!src->source)
+        {
+                /*ERROR("No device name specified.");*/
+                fprintf(stderr, "No device name specified.");
+                return NULL;
+        }
+        src_v4l2_t *s;
+
+        /* Allocate memory for the state structure. */
+        s = calloc(sizeof(src_v4l2_t), 1);
+        if(!s)
+        {
+                fprintf(stderr, "Out of memory.");
+                return NULL;
+        }
+
+        src->state = (void *) s;
+        char value[200];
+        //snprintf( value, sizeof(value), '\0' );
+        //strcpy(*pixelformatdescription, (char*) value);
+        /* Open the device. */
+        s->fd = open(src->source, O_RDWR | O_NONBLOCK);
+        if(s->fd < 0)
+        {
+                fprintf(stderr, "Cannot open device.");
+                free(s);
+                return NULL;
+        }
+
+        if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0) {
+            close_v4l2(src);
+            fprintf(stderr, "Cannot get capabilities.");
+            return NULL;
+        }
+        char *res = strdup((char*) s->cap.card);
+        /*strcpy(res, (char*) s->cap.card);*/
+        if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
+            // Device cannot capture
+        }
+        else {
+            struct v4l2_format format;
+            memset(&format,0,sizeof(format));
+            format.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+            if (ioctl(s->fd,VIDIOC_G_FMT,&format) < 0) {
+                fprintf(stderr, "Cannot get format.");
+                // Cannot query
+            }
+            struct v4l2_fmtdesc fmt;
+            memset(&fmt,0,sizeof(fmt));
+            fmt.index = 0;
+            fmt.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+            struct v4l2_frmsizeenum sizes;
+            memset(&sizes,0,sizeof(sizes));
+
+            struct v4l2_frmivalenum rates;
+            memset(&rates,0,sizeof(rates));
+
+            while (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
+            {
+                /*strcpy(*pixelformatdescription, (char *) fmt.description);*/
+                //*pixelformatdescription = strdup((char*)fmt.description);
+                snprintf( value, sizeof(value), ">%c%c%c%c", fmt.pixelformat >> 0,  fmt.pixelformat >> 8, fmt.pixelformat >> 16, fmt.pixelformat >> 24 );
+                strcat(*pixelformatdescription, (char *) value);
+                fprintf(stderr, "detected format: %s: %c%c%c%c\n", fmt.description, fmt.pixelformat >> 0,  fmt.pixelformat >> 8,
+                      fmt.pixelformat >> 16, fmt.pixelformat >> 24);
+
+                sizes.pixel_format = fmt.pixelformat;
+                sizes.index = 0;
+                // Query supported frame size
+                while (ioctl(s->fd, VIDIOC_ENUM_FRAMESIZES, &sizes) != -1) {
+                    struct v4l2_frmsize_discrete image_size = sizes.un.discrete;
+                    // Query supported frame rates
+                    rates.index = 0;
+                    rates.pixel_format = fmt.pixelformat;
+                    rates.width = image_size.width;
+                    rates.height = image_size.height;
+                    snprintf( value, sizeof(value), ":%dx%d=", image_size.width, image_size.height );
+                    strcat(*pixelformatdescription, (char *) value);
+                    fprintf(stderr, "Size: %dx%d: ", image_size.width, image_size.height);
+                    while (ioctl(s->fd, VIDIOC_ENUM_FRAMEINTERVALS, &rates) != -1) {
+                        snprintf( value, sizeof(value), "%d/%d,", rates.un.discrete.denominator, rates.un.discrete.numerator );
+                        strcat(*pixelformatdescription, (char *) value);
+                        fprintf(stderr, "%d/%d, ", rates.un.discrete.numerator, rates.un.discrete.denominator);
+                        rates.index ++;
+                    }
+                    fprintf(stderr, "\n");
+                    sizes.index++;
+                }
+
+
+                /*[0x%08X] '%c%c%c%c' (%s)", v4l2_pal,
+                      fmt.pixelformat,
+                      fmt.pixelformat >> 0,  fmt.pixelformat >> 8,
+                      fmt.pixelformat >> 16, fmt.pixelformat >> 24*/
+                fmt.index++;
+            }
+            /*else {
+                *pixelformatdescription = '\0';
+            }*/
+        }
+        close_v4l2(src);
+        return res;
 }
 
-int src_get_option_by_name(src_option_t **opt, char *name, char **value)
-{
-       if(!opt || !name || !value) return(-1);
-       
-       while(*opt)
-       {
-               if((*opt)->name)
-               {
-                       if(!strcasecmp(name, (*opt)->name))
-                       {
-                               *value = (*opt)->value;
-                               return(0);
-                       }
-               }
-               
-               opt++;
-       }
-       
-       return(-1);
-}
 
-int src_free_options(src_option_t ***options)
-{
-       src_option_t **opts;
-       
-       if(!options || !*options) return(-1);
-       
-       opts = *options;
-        while(*opts)
-       {
-               if((*opts)->name)  free((*opts)->name);
-               if((*opts)->value) free((*opts)->value);
-               
-               free(*opts);
-               
-               opts++;
-       }
-       
-       free(*options);
-       *options = NULL;
-       
-       return(0);
-}
 
index 3ce1d3b2584a736c0a9814c608124a783557d136..be2f0d9912fe3f3bff281550592441d5ce88ee7a 100644 (file)
@@ -11,6 +11,9 @@
 extern "C" {
  #endif
 
+#ifndef INC_SRC_H
+#define INC_SRC_H
+
 #include <stdint.h>
 #include <sys/time.h>
 #include <stdio.h>
@@ -20,8 +23,9 @@ extern "C" {
 #include <unistd.h>
 #include <fcntl.h>
 
-#ifndef INC_SRC_H
-#define INC_SRC_H
+#include "videodev2.h"
+
+
 
 typedef unsigned char avgbmp_t;
 
@@ -115,19 +119,6 @@ typedef struct {
        
 } src_t;
 
-typedef struct {
-       
-       char *name;
-       
-       uint8_t flags;
-       
-       int (*open)(src_t *);
-       int (*close)(src_t *);
-       int (*grab)(src_t *);
-       const char *(*query)(src_t *, uint*, uint*, char **);
-       
-} src_mod_t;
-
 typedef struct {
        
        /* List of options. */
@@ -209,15 +200,31 @@ typedef struct {
 
 } fswebcam_config_t;
 
-extern int src_open(src_t *src, char *source);
-extern int src_close(src_t *src);
-extern int src_grab(src_t *src);
-extern const char *src_query(src_t *src, char *source, uint *width, uint *height, char **pixelformatdescription);
 
-extern int src_set_option(src_option_t ***options, char *name, char *value);
-extern int src_get_option_by_number(src_option_t **opt, int number, char **name, char **value);
-extern int src_get_option_by_name(src_option_t **opt, char *name, char **value);
-extern int src_free_options(src_option_t ***options);
+
+typedef struct {
+        void *start;
+        size_t length;
+} v4l2_buffer_t;
+
+typedef struct {
+
+        int fd;
+        char map;
+
+        struct v4l2_capability cap;
+        struct v4l2_format fmt;
+        struct v4l2_requestbuffers req;
+        struct v4l2_buffer buf;
+
+        v4l2_buffer_t *buffer;
+
+        int pframe;
+
+} src_v4l2_t;
+
+
+const char *query_v4ldevice(src_t *src, char **pixelformatdescription);
 
 #endif
 
index 7d1e03f434573e4bcb3ff9ac30d785895a039aac..716804d9ec7c4a739d958f9df1c29378248da689 100644 (file)
 
 #ifdef HAVE_V4L2
 
-typedef struct {
-       void *start;
-       size_t length;
-} v4l2_buffer_t;
-
-typedef struct {
-       
-       int fd;
-       char map;
-       
-       struct v4l2_capability cap;
-       struct v4l2_format fmt;
-       struct v4l2_requestbuffers req;
-       struct v4l2_buffer buf;
-       
-       v4l2_buffer_t *buffer;
-       
-       int pframe;
-       
-} src_v4l2_t;
-
-static int src_v4l2_close(src_t *src);
-
-typedef struct {
-       uint16_t src;
-       uint32_t v4l2;
-} v4l2_palette_t;
-
-v4l2_palette_t v4l2_palette[] = {
-       { SRC_PAL_JPEG,    V4L2_PIX_FMT_JPEG   },
-       { SRC_PAL_MJPEG,   V4L2_PIX_FMT_MJPEG  },
-       { SRC_PAL_S561,    V4L2_PIX_FMT_SPCA561 },
-       { SRC_PAL_RGB24,   V4L2_PIX_FMT_RGB24  },
-       { SRC_PAL_BGR24,   V4L2_PIX_FMT_BGR24  },
-       { SRC_PAL_RGB32,   V4L2_PIX_FMT_RGB32  },
-       { SRC_PAL_BGR32,   V4L2_PIX_FMT_BGR32  },
-       { SRC_PAL_YUYV,    V4L2_PIX_FMT_YUYV   },
-       { SRC_PAL_UYVY,    V4L2_PIX_FMT_UYVY   },
-       { SRC_PAL_YUV420P, V4L2_PIX_FMT_YUV420 },
-       { SRC_PAL_BAYER,   V4L2_PIX_FMT_SBGGR8 },
-       { SRC_PAL_SGBRG8,  V4L2_PIX_FMT_SGBRG8 },
-       { SRC_PAL_SGRBG8,  V4L2_PIX_FMT_SGRBG8 },
-       { SRC_PAL_RGB565,  V4L2_PIX_FMT_RGB565 },
-       { SRC_PAL_RGB555,  V4L2_PIX_FMT_RGB555 },
-       { SRC_PAL_Y16,     V4L2_PIX_FMT_Y16    },
-       { SRC_PAL_GREY,    V4L2_PIX_FMT_GREY   },
-       { 0, 0 }
-};
-
 int src_v4l2_get_capability(src_t *src)
 {
        src_v4l2_t *s = (src_v4l2_t *) src->state;
@@ -857,15 +808,57 @@ static const char *src_v4l2_query(src_t *src, uint *width, uint *height, char **
            memset(&fmt,0,sizeof(fmt));
            fmt.index = 0;
            fmt.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-           if (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
+
+            struct v4l2_frmsizeenum sizes;
+            memset(&sizes,0,sizeof(sizes));
+
+            struct v4l2_frmivalenum rates;
+            memset(&rates,0,sizeof(rates));
+            char value[200];
+            *pixelformatdescription = strdup((char *) "result:");
+
+           while (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
            {
                /*strcpy(*pixelformatdescription, (char *) fmt.description);*/
-               *pixelformatdescription = strdup((char*)fmt.description);
-               fprintf(stderr, "format: %s", fmt.description);
+               //*pixelformatdescription = strdup((char*)fmt.description);
+                snprintf( value, sizeof(value), "%c%c%c%c:", fmt.pixelformat >> 0,  fmt.pixelformat >> 8, fmt.pixelformat >> 16, fmt.pixelformat >> 24 );
+                strcat(*pixelformatdescription, strdup((char *) value));
+               fprintf(stderr, "detected format: %s: %c%c%c%c\n", fmt.description, fmt.pixelformat >> 0,  fmt.pixelformat >> 8,
+                      fmt.pixelformat >> 16, fmt.pixelformat >> 24);
+
+                sizes.pixel_format = fmt.pixelformat;
+                sizes.index = 0;
+                // Query supported frame size
+                while (ioctl(s->fd, VIDIOC_ENUM_FRAMESIZES, &sizes) != -1) {
+                    struct v4l2_frmsize_discrete image_size = sizes.un.discrete;
+                    // Query supported frame rates
+                    rates.index = 0;
+                    rates.pixel_format = fmt.pixelformat;
+                    rates.width = image_size.width;
+                    rates.height = image_size.height;
+                    snprintf( value, sizeof(value), "%dx%d,", image_size.width, image_size.height );
+                    strcat(*pixelformatdescription, strdup((char *) value));
+                    fprintf(stderr, "Size: %dx%d: ", image_size.width, image_size.height);
+                    while (ioctl(s->fd, VIDIOC_ENUM_FRAMEINTERVALS, &rates) != -1) {
+                        snprintf( value, sizeof(value), "%d/%d,", rates.un.discrete.numerator, rates.un.discrete.denominator );
+                        strcat(*pixelformatdescription, strdup((char *) value));
+                        fprintf(stderr, "%d/%d, ", rates.un.discrete.numerator, rates.un.discrete.denominator);
+                        rates.index ++;
+                    }
+                    fprintf(stderr, "\n");
+                    sizes.index++;
+                }
+                
+
+                /*[0x%08X] '%c%c%c%c' (%s)", v4l2_pal,
+                      fmt.pixelformat,
+                      fmt.pixelformat >> 0,  fmt.pixelformat >> 8,
+                      fmt.pixelformat >> 16, fmt.pixelformat >> 24*/
+                fmt.index++;
            }
-           else {
+           /*else {
                *pixelformatdescription = '\0';
-           }
+           }*/
        }
        src_v4l2_close(src);
        return res;
index 76d9a4a68d66d1638774cfdd215c847fbde89102..530fe8143eae704540a38eea25237b8009852442 100644 (file)
 
 #include "v4lcapture.h"
 #include "kdenlivesettings.h"
-#include "dec.h"
 
-static src_t v4lsrc;
 
-QImage add_image_png(src_t *src)
+V4lCaptureHandler::V4lCaptureHandler()
 {
-    QImage im;
-    im.loadFromData((uchar *)src->img, src->length, "PNG");
-    return im;
-}
-
-QImage add_image_jpeg(src_t *src)
-{
-    uint32_t hlength;
-    uint8_t *himg = NULL;
-    QImage im;
-
-    /* MJPEG data may lack the DHT segment required for decoding... */
-    verify_jpeg_dht((uint8_t *) src->img, src->length, &himg, &hlength);
-
-    im.loadFromData(himg, hlength, "JPG");
-    free(himg);
-    return im;
-}
-
-class MyDisplay : public QLabel
-{
-public:
-    MyDisplay(QWidget *parent = 0);
-    void setImage(QImage img);
-    virtual void paintEvent(QPaintEvent *);
-    virtual void resizeEvent(QResizeEvent *);
-
-private:
-    QImage m_img;
-    bool m_clear;
-};
-
-MyDisplay::MyDisplay(QWidget *parent):
-    QLabel(parent)
-    , m_clear(false)
-{
-    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-    setAttribute(Qt::WA_PaintOnScreen);
-    setAttribute(Qt::WA_OpaquePaintEvent);
-}
-
-void MyDisplay::resizeEvent(QResizeEvent *)
-{
-    m_clear = true;
-}
-
-void MyDisplay::paintEvent(QPaintEvent *)
-{
-    QPainter p(this);
-    if (m_clear) {
-        // widget resized, cleanup
-        p.fillRect(0, 0, width(), height(), palette().background());
-        m_clear = false;
-    }
-    if (m_img.isNull()) return;
-    QImage img = m_img.scaled(width(), height(), Qt::KeepAspectRatio);
-    p.drawImage((width() - img.width()) / 2, (height() - img.height()) / 2, img);
-    p.end();
-}
-
-void MyDisplay::setImage(QImage img)
-{
-    m_img = img;
-    update();
 }
 
-
-
-V4lCaptureHandler::V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent):
-    CaptureHandler(lay, parent)
-    , m_update(false)
-    , m_device(KdenliveSettings::video4vdevice())
-    , m_width(-1)
-    , m_height(-1)
-{
-    if (lay == NULL) return;
-    m_display = new MyDisplay;
-    lay->addWidget(m_display);
-}
+//static
 
 QStringList V4lCaptureHandler::getDeviceName(QString input)
 {
-    fswebcam_config_t *config;
-    /* Prepare the configuration structure. */
-    config = (fswebcam_config_t *) calloc(sizeof(fswebcam_config_t), 1);
-    if (!config) {
-        /*WARN("Out of memory.");*/
-        fprintf(stderr, "Out of MEM....");
-        return QStringList() << input;
-    }
-
-    /* Set the defaults. */
-    config->loop = 0;
-    config->offset = 0;
-    config->background = 0;
-    config->pidfile = NULL;
-    config->logfile = NULL;
-    config->gmt = 0;
-    config->start = 0;
-    config->device = strdup(input.toUtf8().constData());
-    config->input = NULL;
-    config->tuner = 0;
-    config->frequency = 0;
-    config->delay = 0;
-    config->use_read = 0;
-    config->list = 0;
-    if (m_width > 0) config->width = m_width;
-    else config->width = 384;
-    if (m_height > 0) config->height = m_height;
-    else config->height = 288;
-    config->fps = 0;
-    config->frames = 1;
-    config->skipframes = 0;
-    config->palette = SRC_PAL_ANY;
-    config->option = NULL;
-    config->dumpframe = NULL;
-    config->jobs = 0;
-    config->job = NULL;
-
-    /* Set defaults and parse the command line. */
-    /*if(fswc_getopts(config, argc, argv)) return(-1);*/
+    src_t v4lsrc;
 
-
-    /* Record the start time. */
-    config->start = time(NULL);
     /* Set source options... */
     memset(&v4lsrc, 0, sizeof(v4lsrc));
-    v4lsrc.input      = config->input;
-    v4lsrc.tuner      = config->tuner;
-    v4lsrc.frequency  = config->frequency;
-    v4lsrc.delay      = config->delay;
+    v4lsrc.input      = NULL;
+    v4lsrc.tuner      = 0;
+    v4lsrc.frequency  = 0;
+    v4lsrc.delay      = 0;
     v4lsrc.timeout    = 10; /* seconds */
-    v4lsrc.use_read   = config->use_read;
-    v4lsrc.list       = config->list;
-    v4lsrc.palette    = config->palette;
-    v4lsrc.width      = config->width;
-    v4lsrc.height     = config->height;
-    v4lsrc.fps        = config->fps;
-    v4lsrc.option     = config->option;
-    char *source = config->device;
-    uint width = 0;
-    uint height = 0;
+    v4lsrc.use_read   = 0;
+    v4lsrc.list       = 0;
+    v4lsrc.palette    = SRC_PAL_ANY;
+    v4lsrc.width      = 384;
+    v4lsrc.height     = 288;
+    v4lsrc.fps        = 0;
+    v4lsrc.option     = NULL;
+    v4lsrc.source     = strdup(input.toUtf8().constData());
     char *pixelformatdescription;
-    QString deviceName(src_query(&v4lsrc, source, &width, &height, &pixelformatdescription));
-    free(config);
+    pixelformatdescription = (char *) calloc(2048, sizeof(char));
+    QString deviceName(query_v4ldevice(&v4lsrc, &pixelformatdescription));
+    QString info(pixelformatdescription);
+    free (pixelformatdescription);
     QStringList result;
-    result << (deviceName.isEmpty() ? input : deviceName) << (width == 0 ? QString() : QString("%1x%2").arg(width).arg(height)) << QString(pixelformatdescription);
+    result << (deviceName.isEmpty() ? input : deviceName) << info;
     return result;
 }
 
-void V4lCaptureHandler::setDevice(const QString input, QString size)
-{
-    m_device = input;
-    if (!size.isEmpty()) {
-        m_width = size.section('x', 0, 0).toInt();
-        m_height = size.section('x', -1).toInt();
-
-    }
-}
-
-void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/, bool)
-{
-    m_display->setHidden(false);
-    fswebcam_config_t *config;
-    /* Prepare the configuration structure. */
-    config = (fswebcam_config_t *) calloc(sizeof(fswebcam_config_t), 1);
-    if (!config) {
-        /*WARN("Out of memory.");*/
-        fprintf(stderr, "Out of MEM....");
-        return;
-    }
-
-    /* Set the defaults. */
-    config->loop = 0;
-    config->offset = 0;
-    config->background = 0;
-    config->pidfile = NULL;
-    config->logfile = NULL;
-    config->gmt = 0;
-    config->start = 0;
-    config->device = strdup(m_device.toUtf8().constData());
-    config->input = NULL;
-    config->tuner = 0;
-    config->frequency = 0;
-    config->delay = 0;
-    config->use_read = 0;
-    config->list = 0;
-    if (m_width > 0) config->width = m_width;
-    else config->width = KdenliveSettings::video4size().section("x", 0, 0).toInt();/*384;*/
-    if (m_height > 0) config->height = m_height;
-    else config->height = KdenliveSettings::video4size().section("x", -1).toInt();/*288;*/
-    config->fps = 0;
-    config->frames = 1;
-    config->skipframes = 0;
-    config->palette = SRC_PAL_ANY;
-    config->option = NULL;
-    config->dumpframe = NULL;
-    config->jobs = 0;
-    config->job = NULL;
-
-    /* Set defaults and parse the command line. */
-    /*if(fswc_getopts(config, argc, argv)) return(-1);*/
-
-
-    /* Record the start time. */
-    config->start = time(NULL);
-    /* Set source options... */
-    memset(&v4lsrc, 0, sizeof(v4lsrc));
-    v4lsrc.input      = config->input;
-    v4lsrc.tuner      = config->tuner;
-    v4lsrc.frequency  = config->frequency;
-    v4lsrc.delay      = config->delay;
-    v4lsrc.timeout    = 10; /* seconds */
-    v4lsrc.use_read   = config->use_read;
-    v4lsrc.list       = config->list;
-    v4lsrc.palette    = config->palette;
-    v4lsrc.width      = config->width;
-    v4lsrc.height     = config->height;
-    v4lsrc.fps        = config->fps;
-    v4lsrc.option     = config->option;
-    char *source = config->device;
-
-    if (src_open(&v4lsrc, source) != 0) return;
-    m_update = true;
-    free(config);
-    QTimer::singleShot(200, this, SLOT(slotUpdate()));
-}
-
-V4lCaptureHandler::~V4lCaptureHandler()
-{
-    stopCapture();
-}
-
-void V4lCaptureHandler::slotUpdate()
-{
-    if (!m_update) return;
-    src_grab(&v4lsrc);
-    QImage qimg(v4lsrc.width, v4lsrc.height, QImage::Format_RGB888);
-    switch (v4lsrc.palette) {
-    case SRC_PAL_PNG:
-        qimg = add_image_png(&v4lsrc);
-        break;
-    case SRC_PAL_JPEG:
-    case SRC_PAL_MJPEG:
-        qimg = add_image_jpeg(&v4lsrc);
-        break;
-    case SRC_PAL_S561:
-        fswc_add_image_s561(qimg.bits(), (uchar *)v4lsrc.img, v4lsrc.length, v4lsrc.width, v4lsrc.height, v4lsrc.palette);
-        break;
-    case SRC_PAL_RGB32:
-        fswc_add_image_rgb32(&v4lsrc, qimg.bits());
-        break;
-    case SRC_PAL_BGR32:
-        fswc_add_image_bgr32(&v4lsrc, qimg.bits());
-        break;
-    case SRC_PAL_RGB24:
-        fswc_add_image_rgb24(&v4lsrc, qimg.bits());
-        break;
-    case SRC_PAL_BGR24:
-        fswc_add_image_bgr24(&v4lsrc, qimg.bits());
-        break;
-    case SRC_PAL_BAYER:
-    case SRC_PAL_SGBRG8:
-    case SRC_PAL_SGRBG8:
-        fswc_add_image_bayer(qimg.bits(), (uchar *)v4lsrc.img, v4lsrc.length, v4lsrc.width, v4lsrc.height, v4lsrc.palette);
-        break;
-    case SRC_PAL_YUYV:
-    case SRC_PAL_UYVY:
-        fswc_add_image_yuyv(&v4lsrc, (avgbmp_t *)qimg.bits());
-        break;
-    case SRC_PAL_YUV420P:
-        fswc_add_image_yuv420p(&v4lsrc, qimg.bits());
-        break;
-    case SRC_PAL_NV12MB:
-        fswc_add_image_nv12mb(&v4lsrc, qimg.bits());
-        break;
-    case SRC_PAL_RGB565:
-        fswc_add_image_rgb565(&v4lsrc, qimg.bits());
-        break;
-    case SRC_PAL_RGB555:
-        fswc_add_image_rgb555(&v4lsrc, qimg.bits());
-        break;
-    case SRC_PAL_Y16:
-        fswc_add_image_y16(&v4lsrc, qimg.bits());
-        break;
-    case SRC_PAL_GREY:
-        fswc_add_image_grey(&v4lsrc, qimg.bits());
-        break;
-    }
-    if (m_analyseFrame) {
-       emit gotFrame(qimg);
-    }
-    if (!m_captureFramePath.isEmpty()) {
-        qimg.save(m_captureFramePath);
-        emit frameSaved(m_captureFramePath);
-        m_captureFramePath.clear();
-    }
-    if (!m_overlayImage.isNull()) {
-        // overlay image
-        QPainter p(&qimg);
-        p.setOpacity(0.5);
-        p.drawImage(0, 0, m_overlayImage);
-        p.end();
-    }
-    m_display->setImage(qimg);
-    if (m_update) QTimer::singleShot(50, this, SLOT(slotUpdate()));
-}
-
-void V4lCaptureHandler::startCapture(const QString &/*path*/)
-{
-}
-
-void V4lCaptureHandler::stopCapture()
-{
-}
-
-void V4lCaptureHandler::captureFrame(const QString &fname)
-{
-    m_captureFramePath = fname;
-}
-
-void V4lCaptureHandler::showOverlay(QImage img, bool /*transparent*/)
-{
-    m_overlayImage = img;
-}
-
-void V4lCaptureHandler::hideOverlay()
-{
-    m_overlayImage = QImage();
-}
-
-void V4lCaptureHandler::hidePreview(bool hide)
-{
-    m_display->setHidden(hide);
-}
-
-void V4lCaptureHandler::stopPreview()
-{
-    m_display->setHidden(true);
-    if (!m_update) return;
-    m_update = false;
-    src_close(&v4lsrc);
-}
 
 
index 4a72ed1338919a7e5494d9fc19a8733088ce795a..03bd9c3b35c9a62d736fc5d24c0b9e33d194572c 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef __V4LCAPTUREHANDLER_H__
 #define __V4LCAPTUREHANDLER_H__
 
-#include "../stopmotion/capturehandler.h"
 #include "src.h"
 
 #include <QWidget>
 #include <QLayout>
 #include <QLabel>
 
-class MyDisplay;
-
-class V4lCaptureHandler : public CaptureHandler
+class V4lCaptureHandler
 {
-    Q_OBJECT
-public:
-    V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent = 0);
-    ~V4lCaptureHandler();
-    void startPreview(int deviceId, int captureMode, bool audio = true);
-    void stopPreview();
-    void startCapture(const QString &path);
-    void stopCapture();
-    void captureFrame(const QString &fname);
-    void showOverlay(QImage img, bool transparent = true);
-    void hideOverlay();
-    void hidePreview(bool hide);
-    QStringList getDeviceName(QString input);
-    /** @brief Sets the path to the capture devide and optionnaly the width / height of the capture. */
-    void setDevice(const QString input, QString size = QString());
 
-private:
-    bool m_update;
-    MyDisplay *m_display;
-    QString m_captureFramePath;
-    QImage m_overlayImage;
-    QString m_device;
-    int m_width;
-    int m_height;
-
-private slots:
-    void slotUpdate();
+public:
+    V4lCaptureHandler();
+    static QStringList getDeviceName(QString input);
 
 };
 
index 1e0c066f342ba144a38452cd6edb57464c11a266..1248522cf2d9fef1d723a260d10b27836d268012 100644 (file)
@@ -395,7 +395,7 @@ struct v4l2_frmsizeenum {
        union {                                 /* Frame size */
                struct v4l2_frmsize_discrete    discrete;
                struct v4l2_frmsize_stepwise    stepwise;
-       };
+       } un;
 
        __u32   reserved[2];                    /* Reserved space for future use */
 };
@@ -425,7 +425,7 @@ struct v4l2_frmivalenum {
        union {                                 /* Frame interval */
                struct v4l2_fract               discrete;
                struct v4l2_frmival_stepwise    stepwise;
-       };
+       } un;
 
        __u32   reserved[2];                    /* Reserved space for future use */
 };
index 9f7a5fa3970c80a51877f208b5333010b0e38a86..2697db9f3cc3dc06df87561ca2359c0c3b42d8ef 100644 (file)
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>405</width>
-    <height>470</height>
+    <height>563</height>
    </rect>
   </property>
   <layout class="QGridLayout" name="gridLayout_8">
@@ -63,7 +63,7 @@
       </size>
      </property>
      <property name="currentIndex">
-      <number>0</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="tab">
       <attribute name="title">
       <attribute name="title">
        <string>Video4Linux</string>
       </attribute>
-      <layout class="QGridLayout" name="gridLayout_9">
-       <item row="1" column="0" colspan="2">
-        <widget class="QGroupBox" name="groupBox">
-         <property name="title">
-          <string>Video</string>
-         </property>
-         <layout class="QGridLayout" name="gridLayout">
-          <item row="0" column="0">
-           <widget class="QLabel" name="label_14">
-            <property name="text">
-             <string>Device</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="1">
-           <widget class="KLineEdit" name="kcfg_video4vdevice">
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="2">
-           <widget class="QLabel" name="label_3">
-            <property name="sizePolicy">
-             <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
-              <horstretch>0</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="text">
-             <string>Format</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="3">
-           <widget class="KLineEdit" name="kcfg_video4vformat">
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="0">
-           <widget class="QLabel" name="label_4">
-            <property name="sizePolicy">
-             <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
-              <horstretch>0</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="text">
-             <string>Image size</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="1">
-           <widget class="KLineEdit" name="kcfg_video4size">
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="2">
-           <widget class="QLabel" name="label_6">
-            <property name="text">
-             <string>Frame rate</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="3">
-           <widget class="QSpinBox" name="kcfg_video4rate">
-            <property name="value">
-             <number>15</number>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="0">
-           <widget class="QLabel" name="label_23">
-            <property name="text">
-             <string>Codec</string>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="1">
-           <widget class="KLineEdit" name="kcfg_video4vcodec"/>
-          </item>
-         </layout>
+      <layout class="QGridLayout" name="gridLayout">
+       <item row="0" column="0">
+        <widget class="QLabel" name="label_30">
+         <property name="text">
+          <string>Detected devices</string>
+         </property>
         </widget>
        </item>
-       <item row="2" column="0" colspan="2">
-        <widget class="QGroupBox" name="groupBox_2">
-         <property name="title">
-          <string>Audio</string>
+       <item row="0" column="1" colspan="4">
+        <widget class="KComboBox" name="kcfg_detectedv4ldevices"/>
+       </item>
+       <item row="1" column="0">
+        <widget class="QLabel" name="label_14">
+         <property name="text">
+          <string>Video device</string>
          </property>
-         <layout class="QGridLayout" name="gridLayout_6">
-          <item row="0" column="0">
-           <widget class="QLabel" name="label_16">
-            <property name="text">
-             <string>Audio device</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="1">
-           <widget class="KLineEdit" name="kcfg_video4adevice">
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="2">
-           <widget class="QLabel" name="label_9">
-            <property name="sizePolicy">
-             <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
-              <horstretch>0</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="text">
-             <string>Format</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="3">
-           <widget class="KLineEdit" name="kcfg_video4aformat">
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="0">
-           <widget class="QLabel" name="label_24">
-            <property name="text">
-             <string>Audio codec</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="1">
-           <widget class="KLineEdit" name="kcfg_video4acodec"/>
-          </item>
-         </layout>
         </widget>
        </item>
-       <item row="3" column="0" colspan="2">
-        <widget class="QGroupBox" name="groupBox_3">
-         <property name="title">
-          <string>Container</string>
+       <item row="1" column="1" colspan="4">
+        <widget class="KLineEdit" name="kcfg_video4vdevice">
+         <property name="text">
+          <string/>
          </property>
-         <layout class="QGridLayout" name="gridLayout_7">
-          <item row="0" column="0">
-           <widget class="QLabel" name="label_25">
-            <property name="text">
-             <string>Format</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="1">
-           <widget class="KLineEdit" name="kcfg_video4container"/>
-          </item>
-          <item row="0" column="2">
-           <widget class="QLabel" name="label_26">
-            <property name="text">
-             <string>Extension</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="3">
-           <widget class="KLineEdit" name="kcfg_video4extension"/>
-          </item>
-         </layout>
         </widget>
        </item>
-       <item row="4" column="0">
-        <widget class="QLabel" name="label_11">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
+       <item row="3" column="0">
+        <widget class="QLabel" name="label_6">
+         <property name="text">
+          <string>Size:</string>
          </property>
+        </widget>
+       </item>
+       <item row="3" column="1" colspan="4">
+        <widget class="QLabel" name="p_size">
          <property name="text">
-          <string>Capture params</string>
+          <string>720x576</string>
          </property>
         </widget>
        </item>
-       <item row="5" column="0" colspan="2">
-        <widget class="KLineEdit" name="kcfg_video4capture">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
+       <item row="4" column="1" colspan="4">
+        <widget class="QLabel" name="p_fps">
+         <property name="text">
+          <string>25/1</string>
+         </property>
+        </widget>
+       </item>
+       <item row="5" column="0">
+        <widget class="QLabel" name="label_23">
+         <property name="text">
+          <string>Pixel aspect ratio:</string>
+         </property>
+        </widget>
+       </item>
+       <item row="5" column="1" colspan="4">
+        <widget class="QLabel" name="p_aspect">
+         <property name="text">
+          <string>59/54</string>
          </property>
         </widget>
        </item>
        <item row="6" column="0">
+        <widget class="QLabel" name="label_31">
+         <property name="text">
+          <string>Display aspect ratio:</string>
+         </property>
+        </widget>
+       </item>
+       <item row="6" column="1" colspan="4">
+        <widget class="QLabel" name="p_display">
+         <property name="text">
+          <string>4/3</string>
+         </property>
+        </widget>
+       </item>
+       <item row="7" column="0">
+        <widget class="QLabel" name="label_32">
+         <property name="text">
+          <string>Colorspace</string>
+         </property>
+        </widget>
+       </item>
+       <item row="7" column="1" colspan="4">
+        <widget class="QLabel" name="p_colorspace">
+         <property name="text">
+          <string/>
+         </property>
+        </widget>
+       </item>
+       <item row="8" column="0">
+        <widget class="QLabel" name="p_progressive">
+         <property name="text">
+          <string>Interlaced</string>
+         </property>
+        </widget>
+       </item>
+       <item row="8" column="1" colspan="3">
+        <spacer name="horizontalSpacer_5">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>127</width>
+           <height>21</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="8" column="4">
+        <widget class="QPushButton" name="pushButton">
+         <property name="text">
+          <string>Edit</string>
+         </property>
+        </widget>
+       </item>
+       <item row="9" column="0" colspan="4">
+        <widget class="Line" name="line">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item row="12" column="0" colspan="4">
+        <widget class="Line" name="line_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item row="13" column="0">
         <widget class="QLabel" name="label_12">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
           </sizepolicy>
          </property>
          <property name="text">
-          <string>Encoding params</string>
+          <string>Encoding parameters</string>
          </property>
         </widget>
        </item>
-       <item row="7" column="0" colspan="2">
-        <widget class="KLineEdit" name="kcfg_video4encoding"/>
+       <item row="14" column="0" colspan="5">
+        <widget class="QPlainTextEdit" name="kcfg_v4l_parameters">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+        </widget>
        </item>
-       <item row="8" column="1">
+       <item row="16" column="0">
         <spacer name="verticalSpacer">
          <property name="orientation">
           <enum>Qt::Vertical</enum>
          </property>
         </spacer>
        </item>
-       <item row="0" column="1">
-        <widget class="KComboBox" name="kcfg_detectedv4ldevices">
-         <item>
-          <property name="text">
-           <string>Select device in list</string>
-          </property>
-         </item>
+       <item row="15" column="0">
+        <widget class="QLabel" name="label_3">
+         <property name="text">
+          <string>File extension</string>
+         </property>
         </widget>
        </item>
-       <item row="0" column="0">
-        <widget class="QLabel" name="label_30">
+       <item row="15" column="1" colspan="4">
+        <widget class="QLineEdit" name="kcfg_v4l_extension">
+         <property name="maxLength">
+          <number>5</number>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="0">
+        <widget class="QLabel" name="label_9">
          <property name="text">
-          <string>Detected devices</string>
+          <string>Capture format</string>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="1" colspan="4">
+        <widget class="KComboBox" name="kcfg_v4l_format"/>
+       </item>
+       <item row="4" column="0">
+        <widget class="QLabel" name="label_4">
+         <property name="text">
+          <string>Frame rate:</string>
+         </property>
+        </widget>
+       </item>
+       <item row="10" column="0">
+        <widget class="QCheckBox" name="kcfg_v4l_captureaudio">
+         <property name="text">
+          <string>Capture audio (ALSA)</string>
+         </property>
+        </widget>
+       </item>
+       <item row="10" column="1" colspan="4">
+        <widget class="KComboBox" name="kcfg_v4l_alsadevice">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
          </property>
         </widget>
        </item>
   <tabstop>kcfg_firewireformat</tabstop>
   <tabstop>kcfg_firewireautosplit</tabstop>
   <tabstop>kcfg_firewiretimestamp</tabstop>
-  <tabstop>kcfg_video4vdevice</tabstop>
-  <tabstop>kcfg_video4vformat</tabstop>
-  <tabstop>kcfg_video4adevice</tabstop>
-  <tabstop>kcfg_video4aformat</tabstop>
-  <tabstop>kcfg_video4encoding</tabstop>
   <tabstop>kcfg_rmd_capture_audio</tabstop>
   <tabstop>radioButton_2</tabstop>
   <tabstop>kcfg_rmd_alsa_device</tabstop>
index 0d7d35cc214849457c76330e64e7311c0de1c223..a31b3ed7de6eb1827f2781251500d0c2d5596ec1 100644 (file)
      </widget>
     </widget>
    </item>
-   <item row="1" column="9">
-    <widget class="KComboBox" name="sequence_name">
-     <property name="toolTip">
-      <string>Sequence name</string>
+   <item row="1" column="2">
+    <widget class="QToolButton" name="config_button">
+     <property name="whatsThis">
+      <string/>
      </property>
-     <property name="editable">
-      <bool>true</bool>
+     <property name="text">
+      <string>...</string>
+     </property>
+     <property name="popupMode">
+      <enum>QToolButton::InstantPopup</enum>
      </property>
     </widget>
    </item>
-   <item row="1" column="11">
-    <widget class="KComboBox" name="capture_device">
+   <item row="1" column="3">
+    <widget class="QToolButton" name="live_button">
      <property name="toolTip">
-      <string>Capture device</string>
+      <string>Live view</string>
      </property>
      <property name="whatsThis">
       <string/>
      </property>
-    </widget>
-   </item>
-   <item row="1" column="12">
-    <widget class="KComboBox" name="log_box">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
+     <property name="text">
+      <string>...</string>
      </property>
-     <property name="maxCount">
-      <number>10</number>
+     <property name="checkable">
+      <bool>true</bool>
      </property>
-     <property name="frame">
-      <bool>false</bool>
+     <property name="autoRaise">
+      <bool>true</bool>
      </property>
     </widget>
    </item>
-   <item row="1" column="13">
-    <widget class="QPushButton" name="button_addsequence">
+   <item row="1" column="4">
+    <widget class="QToolButton" name="capture_button">
+     <property name="toolTip">
+      <string>Capture frame</string>
+     </property>
      <property name="text">
-      <string>Add to project</string>
+      <string>...</string>
      </property>
     </widget>
    </item>
-   <item row="1" column="7">
-    <widget class="QToolButton" name="preview_button">
+   <item row="1" column="5">
+    <widget class="QToolButton" name="capture_interval">
      <property name="toolTip">
-      <string>Preview sequence</string>
-     </property>
-     <property name="whatsThis">
-      <string/>
+      <string>Interval capture</string>
      </property>
      <property name="text">
       <string>...</string>
      </property>
     </widget>
    </item>
-   <item row="1" column="2">
-    <widget class="QToolButton" name="config_button">
-     <property name="whatsThis">
-      <string/>
-     </property>
+   <item row="1" column="6">
+    <widget class="QToolButton" name="overlay_button">
      <property name="text">
       <string>...</string>
      </property>
-     <property name="popupMode">
-      <enum>QToolButton::InstantPopup</enum>
-     </property>
     </widget>
    </item>
-   <item row="1" column="3">
-    <widget class="QToolButton" name="live_button">
+   <item row="1" column="7">
+    <widget class="QToolButton" name="preview_button">
      <property name="toolTip">
-      <string>Live view</string>
+      <string>Preview sequence</string>
      </property>
      <property name="whatsThis">
       <string/>
      <property name="checkable">
       <bool>true</bool>
      </property>
-     <property name="autoRaise">
-      <bool>true</bool>
-     </property>
     </widget>
    </item>
    <item row="1" column="8">
      </property>
     </widget>
    </item>
-   <item row="1" column="6">
-    <widget class="QToolButton" name="overlay_button">
-     <property name="text">
-      <string>...</string>
+   <item row="1" column="9">
+    <widget class="KComboBox" name="sequence_name">
+     <property name="toolTip">
+      <string>Sequence name</string>
+     </property>
+     <property name="editable">
+      <bool>true</bool>
      </property>
     </widget>
    </item>
-   <item row="1" column="5">
-    <widget class="QToolButton" name="capture_interval">
+   <item row="1" column="11">
+    <widget class="KComboBox" name="capture_device">
      <property name="toolTip">
-      <string>Interval capture</string>
-     </property>
-     <property name="text">
-      <string>...</string>
+      <string>Capture device</string>
      </property>
-     <property name="checkable">
-      <bool>true</bool>
+     <property name="whatsThis">
+      <string/>
      </property>
     </widget>
    </item>
-   <item row="1" column="4">
-    <widget class="QToolButton" name="capture_button">
-     <property name="toolTip">
-      <string>Capture frame</string>
+   <item row="1" column="12">
+    <widget class="KComboBox" name="log_box">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="maxCount">
+      <number>10</number>
      </property>
+     <property name="frame">
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="13">
+    <widget class="QPushButton" name="button_addsequence">
      <property name="text">
-      <string>...</string>
+      <string>Add to project</string>
      </property>
     </widget>
    </item>
index 0c151a638402ec251bec309566063c81a4592979..96b1b7508679c2b1ff414310655101aa6fc7b2be 100644 (file)
@@ -6,55 +6,49 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>273</width>
-    <height>153</height>
+    <width>279</width>
+    <height>110</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
   <layout class="QGridLayout" name="gridLayout">
-   <item row="0" column="0" colspan="3">
+   <item row="0" column="0" colspan="4">
     <widget class="QLabel" name="label">
      <property name="text">
       <string>Autodetected capture devices</string>
      </property>
     </widget>
    </item>
-   <item row="0" column="3">
+   <item row="0" column="4">
     <widget class="QPushButton" name="button_reload">
      <property name="text">
       <string>Check</string>
      </property>
     </widget>
    </item>
-   <item row="1" column="0" colspan="4">
-    <widget class="QTreeWidget" name="device_list">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="alternatingRowColors">
-      <bool>true</bool>
+   <item row="1" column="0" colspan="5">
+    <widget class="QLabel" name="v4l_status">
+     <property name="text">
+      <string/>
      </property>
-     <property name="allColumnsShowFocus">
-      <bool>true</bool>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="5">
+    <widget class="KComboBox" name="v4l_devices"/>
+   </item>
+   <item row="3" column="0" colspan="2">
+    <widget class="QLabel" name="label_9">
+     <property name="text">
+      <string>Select capture format</string>
      </property>
-     <column>
-      <property name="text">
-       <string>Device Name</string>
-      </property>
-     </column>
-     <column>
-      <property name="text">
-       <string>Capacities</string>
-      </property>
-     </column>
     </widget>
    </item>
-   <item row="3" column="1">
+   <item row="3" column="2" colspan="3">
+    <widget class="KComboBox" name="v4l_formats"/>
+   </item>
+   <item row="4" column="1">
     <spacer name="verticalSpacer">
      <property name="orientation">
       <enum>Qt::Vertical</enum>
      </property>
     </spacer>
    </item>
-   <item row="2" column="0" colspan="4">
-    <widget class="QLabel" name="v4l_status">
-     <property name="text">
-      <string/>
-     </property>
-    </widget>
-   </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KComboBox</class>
+   <extends>QComboBox</extends>
+   <header>kcombobox.h</header>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections/>
 </ui>
index ed2ce32cdb797a299ae6fac53435117f06f4a00f..985aa4d25af4328390de3b783b05adb24c1fcae9 100644 (file)
@@ -128,7 +128,8 @@ Wizard::Wizard(bool upgrade, QWidget *parent) :
     page6->setTitle(i18n("Webcam"));
     m_capture.setupUi(page6);
     connect(m_capture.button_reload, SIGNAL(clicked()), this, SLOT(slotDetectWebcam()));
-    connect(m_capture.device_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotUpdateCaptureParameters()));
+    connect(m_capture.v4l_devices, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateCaptureParameters()));
+    connect(m_capture.v4l_formats, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSaveCaptureFormat()));
     m_capture.button_reload->setIcon(KIcon("view-refresh"));
 
     addPage(page6);
@@ -148,47 +149,90 @@ Wizard::Wizard(bool upgrade, QWidget *parent) :
 void Wizard::slotDetectWebcam()
 {
 #if !defined(Q_WS_MAC) && !defined(Q_OS_FREEBSD)
-    m_capture.device_list->clear();
+    m_capture.v4l_devices->blockSignals(true);
+    m_capture.v4l_devices->clear();
 
     // Video 4 Linux device detection
-    V4lCaptureHandler v4l(NULL);
     for (int i = 0; i < 10; i++) {
         QString path = "/dev/video" + QString::number(i);
         if (QFile::exists(path)) {
-            QStringList deviceInfo = v4l.getDeviceName(path.toUtf8().constData());
+            QStringList deviceInfo = V4lCaptureHandler::getDeviceName(path.toUtf8().constData());
             if (!deviceInfo.isEmpty()) {
-                QTreeWidgetItem *item = new QTreeWidgetItem(m_capture.device_list, QStringList() << deviceInfo.at(0) << "(" + deviceInfo.at(1) + ") " + deviceInfo.at(2));
-                item->setData(0, Qt::UserRole, path);
-                item->setData(0, Qt::UserRole + 1, deviceInfo.at(1));
+                m_capture.v4l_devices->addItem(deviceInfo.at(0), path);
+                m_capture.v4l_devices->setItemData(m_capture.v4l_devices->count() - 1, deviceInfo.at(1), Qt::UserRole + 1);
             }
         }
     }
-    if (m_capture.device_list->topLevelItemCount() > 0) {
+    if (m_capture.v4l_devices->count() > 0) {
         m_capture.v4l_status->setText(i18n("Select your default video4linux device"));
         // select default device
         bool found = false;
-        for (int i = 0; i < m_capture.device_list->topLevelItemCount(); i++) {
-            QTreeWidgetItem * item = m_capture.device_list->topLevelItem(i);
-            if (item && item->data(0, Qt::UserRole).toString() == KdenliveSettings::video4vdevice()) {
-                m_capture.device_list->setCurrentItem(item);
+        for (int i = 0; i < m_capture.v4l_devices->count(); i++) {
+            QString device = m_capture.v4l_devices->itemData(i).toString();
+            if (device == KdenliveSettings::video4vdevice()) {
+                m_capture.v4l_devices->setCurrentIndex(i);
                 found = true;
                 break;
             }
         }
-        if (!found) m_capture.device_list->setCurrentItem(m_capture.device_list->topLevelItem(0));
+        slotUpdateCaptureParameters();
+        if (!found) m_capture.v4l_devices->setCurrentIndex(0);
     } else m_capture.v4l_status->setText(i18n("No device found, plug your webcam and refresh."));
+    m_capture.v4l_devices->blockSignals(false);
 #endif
 }
 
 void Wizard::slotUpdateCaptureParameters()
 {
-    QTreeWidgetItem * item = m_capture.device_list->currentItem();
-    if (!item) return;
-    QString device = item->data(0, Qt::UserRole).toString();
+    QString device = m_capture.v4l_devices->itemData(m_capture.v4l_devices->currentIndex()).toString();
     if (!device.isEmpty()) KdenliveSettings::setVideo4vdevice(device);
 
-    QString size = item->data(0, Qt::UserRole + 1).toString();
-    if (!size.isEmpty()) KdenliveSettings::setVideo4size(size);
+    QString formats = m_capture.v4l_devices->itemData(m_capture.v4l_devices->currentIndex(), Qt::UserRole + 1).toString();
+
+    m_capture.v4l_formats->blockSignals(true);
+    m_capture.v4l_formats->clear();
+
+    QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+    if (QFile::exists(vl4ProfilePath)) {
+        MltVideoProfile profileInfo = ProfilesDialog::getVideoProfile(vl4ProfilePath);
+        m_capture.v4l_formats->addItem(i18n("Current settings (%1x%2, %3/%4fps)", profileInfo.width, profileInfo.height, profileInfo.frame_rate_num, profileInfo.frame_rate_den), QStringList() << QString("unknown") <<QString::number(profileInfo.width)<<QString::number(profileInfo.height)<<QString::number(profileInfo.frame_rate_num)<<QString::number(profileInfo.frame_rate_den));
+    }
+    QStringList pixelformats = formats.split(">", QString::SkipEmptyParts);
+    QString itemSize;
+    QString pixelFormat;
+    QStringList itemRates;
+    for (int i = 0; i < pixelformats.count(); i++) {
+        QString format = pixelformats.at(i).section(':', 0, 0);
+        QStringList sizes = pixelformats.at(i).split(":", QString::SkipEmptyParts);
+        pixelFormat = sizes.takeFirst();
+        for (int j = 0; j < sizes.count(); j++) {
+            itemSize = sizes.at(j).section("=", 0, 0);
+            itemRates = sizes.at(j).section("=", 1, 1).split(",", QString::SkipEmptyParts);
+            for (int k = 0; k < itemRates.count(); k++) {
+                m_capture.v4l_formats->addItem("[" + format + "] " + itemSize + " (" + itemRates.at(k) + ")", QStringList() << format << itemSize.section('x', 0, 0) << itemSize.section('x', 1, 1) << itemRates.at(k).section('/', 0, 0) << itemRates.at(k).section('/', 1, 1));
+            }
+        }
+    }
+    if (!QFile::exists(vl4ProfilePath)) {
+        if (m_capture.v4l_formats->count() > 9) slotSaveCaptureFormat();
+        else {
+            // No existing profile and no autodetected profiles
+            MltVideoProfile profileInfo;
+            profileInfo.width = 320;
+            profileInfo.height = 200;
+            profileInfo.frame_rate_num = 15;
+            profileInfo.frame_rate_den = 1;
+            profileInfo.display_aspect_num = 4;
+            profileInfo.display_aspect_den = 3;
+            profileInfo.sample_aspect_num = 1;
+            profileInfo.sample_aspect_den = 1;
+            profileInfo.progressive = 1;
+            profileInfo.colorspace = 601;
+            ProfilesDialog::saveProfile(profileInfo, vl4ProfilePath);
+            m_capture.v4l_formats->addItem(i18n("Default settings (%1x%2, %3/%4fps)", profileInfo.width, profileInfo.height, profileInfo.frame_rate_num, profileInfo.frame_rate_den), QStringList() << QString("unknown") <<QString::number(profileInfo.width)<<QString::number(profileInfo.height)<<QString::number(profileInfo.frame_rate_num)<<QString::number(profileInfo.frame_rate_den));
+        }
+    }
+    m_capture.v4l_formats->blockSignals(false);
 }
 
 void Wizard::checkMltComponents()
@@ -646,4 +690,24 @@ void Wizard::slotShowWebInfos()
     KRun::runUrl(KUrl("http://kdenlive.org/discover/" + QString(kdenlive_version).section(' ', 0, 0)), "text/html", this);
 }
 
+void Wizard::slotSaveCaptureFormat()
+{
+    QStringList format = m_capture.v4l_formats->itemData(m_capture.v4l_formats->currentIndex()).toStringList();
+    if (format.isEmpty()) return;
+    MltVideoProfile profile;
+    profile.description = "Video4Linux capture";
+    profile.colorspace = 601;
+    profile.width = format.at(1).toInt();
+    profile.height = format.at(2).toInt();
+    profile.sample_aspect_num = 1;
+    profile.sample_aspect_den = 1;
+    profile.display_aspect_num = format.at(1).toInt();
+    profile.display_aspect_den = format.at(2).toInt();
+    profile.frame_rate_num = format.at(3).toInt();
+    profile.frame_rate_den = format.at(4).toInt();
+    profile.progressive = 1;
+    QString vl4ProfilePath = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
+    ProfilesDialog::saveProfile(profile, vl4ProfilePath);
+}
+
 #include "wizard.moc"
index da2a551329df064093124830e3b7c33d49b02761..4a0d1344cdaf8ea2e400caea0835a2868e0d8cb5 100644 (file)
@@ -106,6 +106,7 @@ private slots:
     void slotShowWebInfos();
     void slotDetectWebcam();
     void slotUpdateCaptureParameters();
+    void slotSaveCaptureFormat();
 };
 
 #endif