]> git.sesse.net Git - kdenlive/blobdiff - src/mainwindow.cpp
Color scopes now using the common abstract scope as well. --> Common functions, more...
[kdenlive] / src / mainwindow.cpp
index 6da2cacaffb174b85b3a4dc9ccdde1e8409f7977..457fc9f626bcadd3d799a6360d7a2ffe20d9b92a 100644 (file)
 #include "kdenlive-config.h"
 #include "cliptranscode.h"
 #include "ui_templateclip_ui.h"
-#include "vectorscope.h"
-#include "waveform.h"
-#include "rgbparade.h"
-#include "histogram.h"
+#include "colorscopes/vectorscope.h"
+#include "colorscopes/waveform.h"
+#include "colorscopes/rgbparade.h"
+#include "colorscopes/histogram.h"
+#include "audiospectrum.h"
 
 #include <KApplication>
 #include <KAction>
 static const char version[] = VERSION;
 
 static const int ID_TIMELINE_POS = 0;
-
 namespace Mlt
 {
 class Producer;
 };
 
+Q_DECLARE_METATYPE(QVector<int16_t>)
+
 EffectsList MainWindow::videoEffects;
 EffectsList MainWindow::audioEffects;
 EffectsList MainWindow::customEffects;
@@ -133,7 +135,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_findActivated(false),
     m_stopmotion(NULL)
 {
-
+    qRegisterMetaType<QVector<int16_t> > ();
     // Create DBus interface
     new MainWindowAdaptor(this);
     QDBusConnection dbus = QDBusConnection::sessionBus();
@@ -276,14 +278,38 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_audiosignalDock->setObjectName("audiosignal");
     m_audiosignalDock->setWidget(m_audiosignal);
     addDockWidget(Qt::TopDockWidgetArea, m_audiosignalDock);
-    if (m_projectMonitor) {
+    connect(m_audiosignal, SIGNAL(updateAudioMonitoring()), m_monitorManager, SLOT(slotUpdateAudioMonitoring()));
+    /*if (m_projectMonitor) {
         connect(m_projectMonitor->render, SIGNAL(showAudioSignal(const QByteArray&)), m_audiosignal, SLOT(showAudio(const QByteArray&)));
     }
     if (m_clipMonitor) {
         connect(m_clipMonitor->render, SIGNAL(showAudioSignal(const QByteArray&)), m_audiosignal, SLOT(showAudio(const QByteArray&)));
+    }*/
+
+    m_audioSpectrum = new AudioSpectrum();
+    m_audioSpectrumDock = new QDockWidget(i18n("AudioSpectrum"), this);
+    m_audioSpectrumDock->setObjectName(m_audioSpectrum->widgetName());
+    m_audioSpectrumDock->setWidget(m_audioSpectrum);
+    addDockWidget(Qt::TopDockWidgetArea, m_audioSpectrumDock);
+
+    // Connect the audio signal to the audio scope slots
+    bool b = true;
+    if (m_projectMonitor) {
+        qDebug() << "project monitor connected";
+        b &= connect(m_projectMonitor->render, SIGNAL(audioSamplesSignal(QVector<int16_t>, int, int, int)),
+                     m_audioSpectrum, SLOT(slotReceiveAudio(QVector<int16_t>, int, int, int)));
+        b &= connect(m_projectMonitor->render, SIGNAL(audioSamplesSignal(const QVector<int16_t>&, const int&, const int&, const int&)),
+                     m_audiosignal, SLOT(slotReceiveAudio(const QVector<int16_t>&, const int&, const int&, const int&)));
     }
-    //connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest()));
-    //connect(m_histogram, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest()));
+    if (m_clipMonitor) {
+        qDebug() << "clip monitor connected";
+        b &= connect(m_clipMonitor->render, SIGNAL(audioSamplesSignal(QVector<int16_t>, int, int, int)),
+                     m_audioSpectrum, SLOT(slotReceiveAudio(QVector<int16_t>, int, int, int)));
+        b &= connect(m_clipMonitor->render, SIGNAL(audioSamplesSignal(const QVector<int16_t>&, int, int, int)),
+                     m_audiosignal, SLOT(slotReceiveAudio(const QVector<int16_t>&, int, int, int)));
+    }
+    // Ensure connection was set up correctly
+    Q_ASSERT(b);
 
     m_undoViewDock = new QDockWidget(i18n("Undo History"), this);
     m_undoViewDock->setObjectName("undo_history");
@@ -341,6 +367,20 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
         layoutActions->addAction("save_layout" + QString::number(i), save);
     }
 
+    KAction *action;
+    // Stop motion actions. Beware of the order, we MUST use the same order in stopmotion/stopmotion.cpp
+    m_stopmotion_actions = new KActionCategory(i18n("Stop Motion"), actionCollection());
+    action = new KAction(KIcon("media-record"), i18n("Capture frame"), this);
+    action->setShortcut(Qt::Key_Space);
+    //action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    m_stopmotion_actions->addAction("stopmotion_capture", action);
+    action = new KAction(i18n("Switch live / captured frame"), this);
+    //action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    m_stopmotion_actions->addAction("stopmotion_switch", action);
+    action = new KAction(KIcon("edit-paste"), i18n("Show last frame over video"), this);
+    action->setCheckable(true);
+    action->setChecked(false);
+    m_stopmotion_actions->addAction("stopmotion_overlay", action);
     setupGUI();
 
 
@@ -379,7 +419,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
                                       static_cast<QMenu*>(factory()->container("transcoders", this)),
                                       clipInTimeline);
 
-    KAction *action;
     // build themes menus
     QMenu *themesMenu = static_cast<QMenu*>(factory()->container("themes_menu", this));
     QActionGroup *themegroup = new QActionGroup(this);
@@ -503,9 +542,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor);
     slotConnectMonitors();
 
-    // Disable drop B frames, see Kdenlive issue #1330, see also kdenlivesettingsdialog.cpp
-    KdenliveSettings::setDropbframes(false);
-
     // Open or create a file.  Command line argument passed in Url has
     // precedence, then "openlastproject", then just a plain empty file.
     // If opening Url fails, openlastproject will _not_ be used.
@@ -540,6 +576,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
 
 MainWindow::~MainWindow()
 {
+    if (m_stopmotion) {
+        delete m_stopmotion;
+    }
     m_effectStack->slotClipItemSelected(NULL, 0);
     m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false);
 
@@ -559,7 +598,7 @@ MainWindow::~MainWindow()
 void MainWindow::queryQuit()
 {
     if (queryClose()) {
-        kapp->quit();
+        close();
     }
 }
 
@@ -739,7 +778,6 @@ void MainWindow::activateShuttleDevice()
     connect(m_jogProcess, SIGNAL(forward1()), m_monitorManager, SLOT(slotForwardOneFrame()));
     connect(m_jogProcess, SIGNAL(rewind(double)), m_monitorManager, SLOT(slotRewind(double)));
     connect(m_jogProcess, SIGNAL(forward(double)), m_monitorManager, SLOT(slotForward(double)));
-    connect(m_jogProcess, SIGNAL(stop()), m_monitorManager, SLOT(slotPlay()));
     connect(m_jogProcess, SIGNAL(button(int)), this, SLOT(slotShuttleButton(int)));
 }
 
@@ -858,7 +896,7 @@ void MainWindow::setupActions()
 
     KActionCollection* collection = actionCollection();
     m_timecodeFormat = new KComboBox(this);
-    m_timecodeFormat->addItem(i18n("hh:mm:ss::ff"));
+    m_timecodeFormat->addItem(i18n("hh:mm:ss:ff"));
     m_timecodeFormat->addItem(i18n("Frames"));
     if (KdenliveSettings::frametimecode()) m_timecodeFormat->setCurrentIndex(1);
     connect(m_timecodeFormat, SIGNAL(activated(int)), this, SLOT(slotUpdateTimecodeFormat(int)));
@@ -1535,7 +1573,7 @@ void MainWindow::setupActions()
     connect(reloadClip , SIGNAL(triggered()), m_projectList, SLOT(slotReloadClip()));
     reloadClip->setEnabled(false);
 
-    QAction *stopMotion = new KAction(KIcon("image-x-generic"), i18n("Stopmotion Animation"), this);
+    QAction *stopMotion = new KAction(KIcon("image-x-generic"), i18n("Stop Motion Capture"), this);
     collection->addAction("stopmotion", stopMotion);
     connect(stopMotion , SIGNAL(triggered()), this, SLOT(slotOpenStopmotion()));
 
@@ -1845,15 +1883,8 @@ bool MainWindow::saveFileAs(const QString &outputFileName)
 {
     QString currentSceneList;
     m_monitorManager->stopActiveMonitor();
-    if (KdenliveSettings::dropbframes()) {
-        KdenliveSettings::setDropbframes(false);
-        m_activeDocument->clipManager()->updatePreviewSettings();
-        currentSceneList = m_projectMonitor->sceneList();
-        KdenliveSettings::setDropbframes(true);
-        m_activeDocument->clipManager()->updatePreviewSettings();
-    } else currentSceneList = m_projectMonitor->sceneList();
-
-    if (m_activeDocument->saveSceneList(outputFileName, currentSceneList) == false)
+
+    if (m_activeDocument->saveSceneList(outputFileName, m_projectMonitor->sceneList()) == false)
         return false;
 
     // Save timeline thumbnails
@@ -1967,6 +1998,12 @@ void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale)
     if (!m_timelineArea->isEnabled()) return;
     m_fileRevert->setEnabled(true);
 
+    // Recreate stopmotion widget on document change
+    if (m_stopmotion) {
+        delete m_stopmotion;
+        m_stopmotion = NULL;
+    }
+
     KProgressDialog progressDialog(this, i18n("Loading project"), i18n("Loading project"));
     progressDialog.setAllowCancel(false);
     progressDialog.progressBar()->setMaximum(4);
@@ -2163,6 +2200,12 @@ void MainWindow::slotUpdateProjectProfile(const QString &profile)
 {
     double dar = m_activeDocument->dar();
 
+    // Recreate the stopmotion widget if profile changes
+    if (m_stopmotion) {
+        delete m_stopmotion;
+        m_stopmotion = NULL;
+    }
+
     // Deselect current effect / transition
     m_effectStack->slotClipItemSelected(NULL, 0);
     m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false);
@@ -2449,7 +2492,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
 #ifndef   Q_WS_MAC
     m_recMonitor->slotUpdateCaptureFolder(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash));
 #endif
-    if (KdenliveSettings::dropbframes()) slotUpdatePreviewSettings();
     //Update the mouse position display so it will display in DF/NDF format by default based on the project setting.
     slotUpdateMousePosition(0);
     // set tool to select tool
@@ -2483,6 +2525,7 @@ void MainWindow::slotPreferences(int page, int option)
      * cached, in which case you want to display the cached dialog
      * instead of creating another one
      */
+    if (m_stopmotion) m_stopmotion->slotLive(false);
     if (KConfigDialog::showDialog("settings")) {
         KdenliveSettingsDialog* d = static_cast <KdenliveSettingsDialog*>(KConfigDialog::exists("settings"));
         if (page != -1) d->showPage(page, option);
@@ -2495,11 +2538,9 @@ void MainWindow::slotPreferences(int page, int option)
     connect(dialog, SIGNAL(settingsChanged(const QString&)), this, SLOT(updateConfiguration()));
     //connect(dialog, SIGNAL(doResetProfile()), this, SLOT(slotDetectAudioDriver()));
     connect(dialog, SIGNAL(doResetProfile()), m_monitorManager, SLOT(slotResetProfiles()));
-    connect(dialog, SIGNAL(updatePreviewSettings()), this, SLOT(slotUpdatePreviewSettings()));
 #ifndef Q_WS_MAC
     connect(dialog, SIGNAL(updateCaptureFolder()), this, SLOT(slotUpdateCaptureFolder()));
 #endif
-    //connect(dialog, SIGNAL(updatePreviewSettings()), this, SLOT(slotUpdatePreviewSettings()));
     dialog->show();
     if (page != -1) dialog->showPage(page, option);
 }
@@ -2513,14 +2554,6 @@ void MainWindow::slotUpdateCaptureFolder()
 #endif
 }
 
-void MainWindow::slotUpdatePreviewSettings()
-{
-    if (m_activeDocument) {
-        m_clipMonitor->slotSetXml(NULL);
-        m_activeDocument->updatePreviewSettings();
-    }
-}
-
 void MainWindow::updateConfiguration()
 {
     //TODO: we should apply settings to all projects, not only the current one
@@ -3066,6 +3099,13 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip)
                 // duration changed, we need to update duration
                 newprops.insert("out", QString::number(dia_ui->outPoint()));
             }
+            if (!path.isEmpty()) {
+                // we are editing an external file, asked if we want to detach from that file or save the result to that title file.
+                if (KMessageBox::questionYesNo(this, i18n("You are editing an external title clip (%1). Do you want to save your changes to the title file or save the changes for this project only?", path), i18n("Save Title"), KGuiItem(i18n("Save to title file")), KGuiItem(i18n("Save in project only"))) == KMessageBox::Yes) {
+                    // save to external file
+                    dia_ui->saveTitle(path);
+                } else newprops.insert("resource", QString());
+            }
             EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newprops, true);
             m_activeDocument->commandStack()->push(command);
             //m_activeTimeline->projectView()->slotUpdateClip(clip->getId());
@@ -3929,7 +3969,7 @@ void MainWindow::slotMonitorRequestRenderFrame(bool request)
         return;
     } else {
         for (int i = 0; i < m_scopesList.count(); i++) {
-            if (m_scopesList.at(i)->isVisible() && tabifiedDockWidgets(m_scopesList.at(i)).isEmpty() && static_cast<AbstractScopeWidget *>(m_scopesList.at(i)->widget())->autoRefreshEnabled()) {
+            if (m_scopesList.at(i)->isVisible() && tabifiedDockWidgets(m_scopesList.at(i)).isEmpty() && static_cast<AbstractGfxScopeWidget *>(m_scopesList.at(i)->widget())->autoRefreshEnabled()) {
                 request = true;
                 break;
             }
@@ -3951,8 +3991,8 @@ void MainWindow::slotDoUpdateScopeFrameRequest()
     // Check scopes
     bool request = false;
     for (int i = 0; i < m_scopesList.count(); i++) {
-        if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && static_cast<AbstractScopeWidget *>(m_scopesList.at(i)->widget())->autoRefreshEnabled()) {
-            kDebug() << "SCOPE VISIBLE: " << static_cast<AbstractScopeWidget *>(m_scopesList.at(i)->widget())->widgetName();
+        if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && static_cast<AbstractGfxScopeWidget *>(m_scopesList.at(i)->widget())->autoRefreshEnabled()) {
+            kDebug() << "SCOPE VISIBLE: " << static_cast<AbstractGfxScopeWidget *>(m_scopesList.at(i)->widget())->widgetName();
             request = true;
             break;
         }
@@ -3972,8 +4012,8 @@ void MainWindow::slotUpdateColorScopes()
     bool request = false;
     for (int i = 0; i < m_scopesList.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;
-        static_cast<AbstractScopeWidget *>(m_scopesList.at(i)->widget())->slotActiveMonitorChanged(m_clipMonitor->isActive());
+        if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast<AbstractGfxScopeWidget *>(m_scopesList.at(i)->widget())->autoRefreshEnabled())) request = true;
+        static_cast<AbstractGfxScopeWidget *>(m_scopesList.at(i)->widget())->slotActiveMonitorChanged(m_clipMonitor->isActive());
     }
     if (request) {
         if (m_clipMonitor->isActive()) m_clipMonitor->render->sendFrameUpdate();
@@ -3984,13 +4024,18 @@ void MainWindow::slotUpdateColorScopes()
 void MainWindow::slotOpenStopmotion()
 {
     if (m_stopmotion == NULL) {
-        m_stopmotion = new StopmotionWidget(m_activeDocument->projectFolder(), this);
+        m_stopmotion = new StopmotionWidget(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_scopesList.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_scopesList.at(i)->widget()), SLOT(slotRenderZoneUpdated(QImage)));
+            //static_cast<AbstractScopeWidget *>(m_scopesList.at(i)->widget())->slotMonitorCapture();
+        }
     }
     m_stopmotion->show();
 }
 
-
 void MainWindow::slotDeleteClip(const QString &id)
 {
     QList <ClipProperties *> list = findChildren<ClipProperties *>();