]> git.sesse.net Git - kdenlive/blobdiff - src/mainwindow.cpp
Make renderjobs code a bit easier to read, fix detection of broken render scripts
[kdenlive] / src / mainwindow.cpp
index 829d1169c39c49324b519a953900de918e43df77..a090bf03df96f6d5ebef8425631d113df5323b94 100644 (file)
 #include "renderwidget.h"
 #include "renderer.h"
 #include "audiosignal.h"
-#ifndef NO_JOGSHUTTLE
+#ifdef USE_JOGSHUTTLE
 #include "jogshuttle.h"
 #include "jogaction.h"
 #include "jogshuttleconfig.h"
-#endif /* NO_JOGSHUTTLE */
+#endif
 #include "clipproperties.h"
 #include "wizard.h"
-#include "editclipcommand.h"
+#include "commands/editclipcommand.h"
 #include "titlewidget.h"
 #include "markerdialog.h"
 #include "clipitem.h"
 #include "interfaces.h"
-#include "kdenlive-config.h"
+#include "config-kdenlive.h"
 #include "cliptranscode.h"
+#include "clipstabilize.h"
 #include "ui_templateclip_ui.h"
 #include "colorscopes/vectorscope.h"
 #include "colorscopes/waveform.h"
 #include "colorscopes/rgbparade.h"
 #include "colorscopes/histogram.h"
-#include "audiospectrum.h"
-#include "spectrogram.h"
+#include "audioscopes/audiospectrum.h"
+#include "audioscopes/spectrogram.h"
 #include "archivewidget.h"
 #include "databackup/backupwidget.h"
 
 #include <knewstuff2/engine.h>
 #include <knewstuff2/ui/knewstuffaction.h>
 #define KNS3 KNS
-#endif /* KDE_IS_VERSION(4,3,80) */
+#endif
 #include <KToolBar>
 #include <KColorScheme>
 #include <KProgressDialog>
 #include <QBitmap>
 
 #include <stdlib.h>
+#include <locale.h>
 
 // Uncomment for deeper debugging
 //#define DEBUG_MAINW
@@ -143,10 +145,10 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_activeTimeline(NULL),
     m_recMonitor(NULL),
     m_renderWidget(NULL),
-#ifndef NO_JOGSHUTTLE
+#ifdef USE_JOGSHUTTLE
     m_jogProcess(NULL),
     m_jogShuttle(NULL),
-#endif /* NO_JOGSHUTTLE */
+#endif
     m_findActivated(false),
     m_stopmotion(NULL)
 {   
@@ -156,6 +158,15 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
 
     // Init locale
     QLocale systemLocale = QLocale();
+    setlocale(LC_NUMERIC, NULL);
+    char *separator = localeconv()->decimal_point;
+    if (separator != systemLocale.decimalPoint()) {
+        kDebug()<<"------\n!!! system locale is not similar to Qt's locale... be prepared for bugs!!!\n------";
+        // HACK: There is a locale conflict, so set locale to at least have correct decimal point
+        if (strncmp(separator, ".", 1) == 0) systemLocale = QLocale::c();
+        else if (strncmp(separator, ",", 1) == 0) systemLocale = QLocale("fr_FR.UTF-8");
+    }
+    
     systemLocale.setNumberOptions(QLocale::OmitGroupSeparator);
     QLocale::setDefault(systemLocale);
 
@@ -209,9 +220,19 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_clipMonitorDock->setObjectName("clip_monitor");
     m_clipMonitor = new Monitor("clip", m_monitorManager, QString(), m_timelineArea);
     m_clipMonitorDock->setWidget(m_clipMonitor);
-    connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint)));
-    connect(m_projectList, SIGNAL(raiseClipMonitor()), m_clipMonitor, SLOT(activateMonitor()));
     
+    // Connect the project list
+    connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint, bool)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool)));
+    connect(m_projectList, SIGNAL(raiseClipMonitor()), m_clipMonitor, SLOT(activateMonitor()));
+    connect(m_projectList, SIGNAL(loadingIsOver()), this, SLOT(slotElapsedTime()));
+    connect(m_projectList, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int)));
+    connect(m_projectList, SIGNAL(updateRenderStatus()), this, SLOT(slotCheckRenderStatus()));
+    connect(m_projectList, SIGNAL(clipNeedsReload(const QString&)),this, SLOT(slotUpdateClip(const QString &)));
+    connect(m_projectList, SIGNAL(updateProfile(const QString &)), this, SLOT(slotUpdateProjectProfile(const QString &)));
+    connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor(const QString &)));
+    connect(m_projectList, SIGNAL(findInTimeline(const QString&)), this, SLOT(slotClipInTimeline(const QString&)));
+    connect(m_clipMonitor, SIGNAL(zoneUpdated(QPoint)), m_projectList, SLOT(slotUpdateClipCut(QPoint)));
+
     m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this);
     m_projectMonitorDock->setObjectName("project_monitor");
     m_projectMonitor = new Monitor("project", m_monitorManager, QString());
@@ -225,7 +246,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     connect(m_recMonitor, SIGNAL(addProjectClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl)));
     connect(m_recMonitor, SIGNAL(addProjectClipList(KUrl::List)), this, SLOT(slotAddProjectClipList(KUrl::List)));
     connect(m_recMonitor, SIGNAL(showConfigDialog(int, int)), this, SLOT(slotPreferences(int, int)));
-#endif
+#endif /* ! Q_WS_MAC */
     m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor, m_recMonitor);
 
     m_notesDock = new QDockWidget(i18n("Project Notes"), this);
@@ -465,15 +486,19 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
 
     loadPlugins();
     loadTranscoders();
+    loadStabilize();
 
     m_projectMonitor->setupMenu(static_cast<QMenu*>(factory()->container("monitor_go", this)), m_playZone, m_loopZone, NULL, m_loopClip);
     m_clipMonitor->setupMenu(static_cast<QMenu*>(factory()->container("monitor_go", this)), m_playZone, m_loopZone, static_cast<QMenu*>(factory()->container("marker_menu", this)));
 
     QMenu *clipInTimeline = static_cast<QMenu*>(factory()->container("clip_in_timeline", this));
     clipInTimeline->setIcon(KIcon("go-jump"));
-    m_projectList->setupGeneratorMenu(static_cast<QMenu*>(factory()->container("generators", this)),
-                                      static_cast<QMenu*>(factory()->container("transcoders", this)),
-                                      clipInTimeline);
+       QHash<QString,QMenu*> menus;
+       menus.insert("addMenu",static_cast<QMenu*>(factory()->container("generators", this)));
+       menus.insert("transcodeMenu",static_cast<QMenu*>(factory()->container("transcoders", this)));
+       menus.insert("stabilizeMenu",static_cast<QMenu*>(factory()->container("stabilize", this)));
+       menus.insert("inTimelineMenu",clipInTimeline);
+    m_projectList->setupGeneratorMenu(menus);
 
     // build themes menus
     QMenu *themesMenu = static_cast<QMenu*>(factory()->container("themes_menu", this));
@@ -575,7 +600,6 @@ 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(checkColorScopes()), this, SLOT(slotUpdateColorScopes()));
     connect(m_monitorManager, SIGNAL(clearScopes()), this, SLOT(slotClearColorScopes()));
     connect(m_effectList, SIGNAL(addEffect(const QDomElement)), this, SLOT(slotAddEffect(const QDomElement)));
@@ -606,9 +630,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
         m_projectList->slotAddClip(urls);
     }
 
-#ifndef NO_JOGSHUTTLE
+#ifdef USE_JOGSHUTTLE
     activateShuttleDevice();
-#endif /* NO_JOGSHUTTLE */
+#endif
     m_projectListDock->raise();
 
     actionCollection()->addAssociatedWidget(m_clipMonitor->container());
@@ -616,7 +640,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     
     // Populate encoding profiles
     KConfig conf("encodingprofiles.rc", KConfig::FullConfig, "appdata");
-    if (KdenliveSettings::proxyparams().isEmpty()) {
+    if (KdenliveSettings::proxyparams().isEmpty() || KdenliveSettings::proxyextension().isEmpty()) {
         KConfigGroup group(&conf, "proxy");
         QMap< QString, QString > values = group.entryMap();
         QMapIterator<QString, QString> i(values);
@@ -627,7 +651,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
             KdenliveSettings::setProxyextension(data.section(';', 1, 1));
         }
     }
-    if (KdenliveSettings::v4l_parameters().isEmpty()) {
+    if (KdenliveSettings::v4l_parameters().isEmpty() || KdenliveSettings::v4l_extension().isEmpty()) {
         KConfigGroup group(&conf, "video4linux");
         QMap< QString, QString > values = group.entryMap();
         QMapIterator<QString, QString> i(values);
@@ -638,7 +662,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
             KdenliveSettings::setV4l_extension(data.section(';', 1, 1));
         }
     }
-    if (KdenliveSettings::decklink_parameters().isEmpty()) {
+    if (KdenliveSettings::decklink_parameters().isEmpty() || KdenliveSettings::decklink_extension().isEmpty()) {
         KConfigGroup group(&conf, "decklink");
         QMap< QString, QString > values = group.entryMap();
         QMapIterator<QString, QString> i(values);
@@ -820,7 +844,7 @@ void MainWindow::slotReloadEffects()
     m_effectList->reloadEffectList(m_effectsMenu, m_effectActions);
 }
 
-#ifndef NO_JOGSHUTTLE
+#ifdef USE_JOGSHUTTLE
 void MainWindow::activateShuttleDevice()
 {
     delete m_jogShuttle;
@@ -838,7 +862,7 @@ void MainWindow::activateShuttleDevice()
     connect(m_jogShuttle, SIGNAL(forward(double)), m_monitorManager, SLOT(slotForward(double)));
     connect(m_jogShuttle, SIGNAL(action(const QString&)), this, SLOT(slotDoAction(const QString&)));
 }
-#endif /* NO_JOGSHUTTLE */
+#endif /* USE_JOGSHUTTLE */
 
 void MainWindow::slotDoAction(const QString& action_name)
 {
@@ -2251,7 +2275,7 @@ void MainWindow::slotEditProjectSettings()
     if (w->exec() == QDialog::Accepted) {
         QString profile = w->selectedProfile();
         m_activeDocument->setProjectFolder(w->selectedFolder());
-#ifndef   Q_WS_MAC
+#ifndef Q_WS_MAC
         m_recMonitor->slotUpdateCaptureFolder(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash));
 #endif
         if (m_renderWidget) m_renderWidget->setDocumentPath(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash));
@@ -2342,7 +2366,9 @@ void MainWindow::slotRenderProject()
 {
     if (!m_renderWidget) {
         QString projectfolder = m_activeDocument ? m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) : KdenliveSettings::defaultprojectfolder();
-        m_renderWidget = new RenderWidget(projectfolder, m_projectList->useProxy(), this);
+        MltVideoProfile profile;
+        if (m_activeDocument) profile = m_activeDocument->mltProfile();
+        m_renderWidget = new RenderWidget(projectfolder, m_projectList->useProxy(), profile, this);
         connect(m_renderWidget, SIGNAL(shutdown()), this, SLOT(slotShutdown()));
         connect(m_renderWidget, SIGNAL(selectedRenderProfile(QMap <QString, QString>)), this, SLOT(slotSetDocumentRenderProfile(QMap <QString, QString>)));
         connect(m_renderWidget, SIGNAL(prepareRenderingData(bool, bool, const QString&)), this, SLOT(slotPrepareRendering(bool, bool, const QString&)));
@@ -2440,7 +2466,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
             disconnect(m_notesWidget, SIGNAL(textChanged()), m_activeDocument, SLOT(setModified()));
             disconnect(m_clipMonitor, SIGNAL(zoneUpdated(QPoint)), m_activeDocument, SLOT(setModified()));
             disconnect(m_projectList, SIGNAL(projectModified()), m_activeDocument, SLOT(setModified()));
-            disconnect(m_projectList, SIGNAL(updateProfile(const QString &)), this, SLOT(slotUpdateProjectProfile(const QString &)));
 
             disconnect(m_projectMonitor->render, SIGNAL(refreshDocumentProducers(bool, bool)), m_activeDocument, SLOT(checkProjectClips(bool, bool)));
 
@@ -2458,7 +2483,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
             disconnect(m_activeTimeline->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*)));
             disconnect(m_activeTimeline->projectView(), SIGNAL(playMonitor()), m_projectMonitor, SLOT(slotPlay()));
             disconnect(m_activeTimeline->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType)));
-            disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, const int)));
+            disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, bool, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool, const int)));
             disconnect(m_activeTimeline, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
             disconnect(m_activeTimeline, SIGNAL(insertTrack(int)), this, SLOT(slotInsertTrack(int)));
             disconnect(m_activeTimeline, SIGNAL(deleteTrack(int)), this, SLOT(slotDeleteTrack(int)));
@@ -2476,14 +2501,10 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
             disconnect(m_activeTimeline->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(activateMonitor()));
             disconnect(m_activeTimeline, SIGNAL(zoneMoved(int, int)), this, SLOT(slotZoneMoved(int, int)));
             disconnect(m_projectList, SIGNAL(loadingIsOver()), m_activeTimeline->projectView(), SLOT(slotUpdateAllThumbs()));
-            disconnect(m_projectList, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int)));
-            disconnect(m_projectList, SIGNAL(updateRenderStatus()), this, SLOT(slotCheckRenderStatus()));
-            disconnect(m_projectList, SIGNAL(clipNeedsReload(const QString&)), this, SLOT(slotUpdateClip(const QString &)));
             disconnect(m_projectList, SIGNAL(refreshClip(const QString &)), m_activeTimeline->projectView(), SLOT(slotRefreshThumbs(const QString &)));
             m_effectStack->clear();
         }
         //m_activeDocument->setRenderer(NULL);
-        disconnect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor()));
         m_clipMonitor->stop();
     }
     KdenliveSettings::setCurrent_profile(doc->profilePath());
@@ -2493,17 +2514,11 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     m_projectList->setDocument(doc);
     m_transitionConfig->updateProjectFormat(doc->mltProfile(), doc->timecode(), doc->tracksList());
     m_effectStack->updateProjectFormat(doc->mltProfile(), doc->timecode());
-    connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor()));
     connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), trackView->projectView(), SLOT(slotRefreshThumbs(const QString &, bool)));
-    connect(m_projectList, SIGNAL(clipNeedsReload(const QString&)),this, SLOT(slotUpdateClip(const QString &)));
 
     connect(m_projectList, SIGNAL(projectModified()), doc, SLOT(setModified()));
-    connect(m_projectList, SIGNAL(updateProfile(const QString &)), this, SLOT(slotUpdateProjectProfile(const QString &)));
     connect(m_projectList, SIGNAL(clipNameChanged(const QString, const QString)), trackView->projectView(), SLOT(clipNameChanged(const QString, const QString)));
 
-    connect(m_projectList, SIGNAL(findInTimeline(const QString&)), this, SLOT(slotClipInTimeline(const QString&)));
-
-
     //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)));
@@ -2513,7 +2528,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     connect(trackView->projectView(), SIGNAL(forceClipProcessing(const QString &)), m_projectList, SLOT(slotForceProcessing(const QString &)));
     connect(m_projectMonitor, SIGNAL(renderPosition(int)), trackView, SLOT(moveCursorPos(int)));
     connect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), trackView, SLOT(slotSetZone(QPoint)));
-    connect(m_clipMonitor, SIGNAL(zoneUpdated(QPoint)), m_projectList, SLOT(slotUpdateClipCut(QPoint)));
     connect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), doc, SLOT(setModified()));
     connect(m_clipMonitor, SIGNAL(zoneUpdated(QPoint)), doc, SLOT(setModified()));
     connect(m_projectMonitor, SIGNAL(durationChanged(int)), trackView, SLOT(setDuration(int)));
@@ -2545,7 +2559,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     connect(trackView, SIGNAL(setZoom(int)), this, SLOT(slotSetZoom(int)));
     connect(trackView->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType)));
 
-    connect(trackView->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, const int)));
+    connect(trackView->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, bool, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool, const int)));
     connect(trackView->projectView(), SIGNAL(playMonitor()), m_projectMonitor, SLOT(slotPlay()));
 
     connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*)));
@@ -2566,9 +2580,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     connect(trackView->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(activateMonitor()));
     connect(trackView, SIGNAL(zoneMoved(int, int)), this, SLOT(slotZoneMoved(int, int)));
     connect(m_projectList, SIGNAL(loadingIsOver()), trackView->projectView(), SLOT(slotUpdateAllThumbs()));
-    connect(m_projectList, SIGNAL(loadingIsOver()), this, SLOT(slotElapsedTime()));
-    connect(m_projectList, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int)));
-    connect(m_projectList, SIGNAL(updateRenderStatus()), this, SLOT(slotCheckRenderStatus()));
 
 
     trackView->projectView()->setContextMenu(m_timelineContextMenu, m_timelineContextClipMenu, m_timelineContextTransitionMenu, m_clipTypeGroup, (QMenu*)(factory()->container("marker_menu", this)));
@@ -2595,7 +2606,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     m_activeDocument = doc;
     m_activeTimeline->updateProjectFps();
     m_activeDocument->checkProjectClips();
-#ifndef   Q_WS_MAC
+#ifndef Q_WS_MAC
     m_recMonitor->slotUpdateCaptureFolder(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash));
 #endif
     //Update the mouse position display so it will display in DF/NDF format by default based on the project setting.
@@ -2662,7 +2673,7 @@ void MainWindow::slotPreferences(int page, int option)
 void MainWindow::slotUpdateCaptureFolder()
 {
 
-#ifndef   Q_WS_MAC
+#ifndef Q_WS_MAC
     if (m_activeDocument) m_recMonitor->slotUpdateCaptureFolder(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash));
     else m_recMonitor->slotUpdateCaptureFolder(KdenliveSettings::defaultprojectfolder());
 #endif
@@ -2685,9 +2696,10 @@ void MainWindow::updateConfiguration()
 
     // Update list of transcoding profiles
     loadTranscoders();
-#ifndef NO_JOGSHUTTLE
+       loadStabilize();
+#ifdef USE_JOGSHUTTLE
     activateShuttleDevice();
-#endif /* NO_JOGSHUTTLE */
+#endif
 
 }
 
@@ -3193,7 +3205,7 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip)
                 else newprops.insert("templatetext", description);
                 //newprops.insert("xmldata", m_projectList->generateTemplateXml(newtemplate, description).toString());
                 if (!newprops.isEmpty()) {
-                    EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newprops, true);
+                    EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newprops), newprops, true);
                     m_activeDocument->commandStack()->push(command);
                 }
             }
@@ -3208,7 +3220,7 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip)
         if (dia_ui->exec() == QDialog::Accepted) {
             QMap <QString, QString> newprops;
             newprops.insert("xmldata", dia_ui->xml().toString());
-            if (dia_ui->outPoint() != clip->duration().frames(m_activeDocument->fps()) - 1) {
+            if (dia_ui->outPoint() != clip->duration().frames(m_activeDocument->fps())) {
                 // duration changed, we need to update duration
                 newprops.insert("out", QString::number(dia_ui->outPoint()));
                 int currentLength = QString(clip->producerProperty("length")).toInt();
@@ -3223,7 +3235,7 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip)
                     dia_ui->saveTitle(path);
                 } else newprops.insert("resource", QString());
             }
-            EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newprops, true);
+            EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newprops), newprops, true);
             m_activeDocument->commandStack()->push(command);
             //m_activeTimeline->projectView()->slotUpdateClip(clip->getId());
             m_activeDocument->setModified(true);
@@ -3271,9 +3283,9 @@ void MainWindow::slotShowClipProperties(QList <DocClipBase *> cliplist, QMap<QSt
         for (int i = 0; i < cliplist.count(); i++) {
             DocClipBase *clip = cliplist.at(i);
             if (clip->clipType() == IMAGE)
-                new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newImageProps, true, command);
+                new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newImageProps), newImageProps, true, command);
             else 
-                new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newProps, true, command);
+                new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newProps), newProps, true, command);
         }
         m_activeDocument->commandStack()->push(command);
         for (int i = 0; i < cliplist.count(); i++)
@@ -3691,7 +3703,7 @@ int MainWindow::getNewStuff(const QString &configFile)
         if (entry->status() == KNS::Entry::Installed)
             kDebug() << "// Installed files: " << entry->installedFiles();
     }
-#endif /* KDE_IS_VERSION(4,3,80) */
+#endif
     return entries.size();
 }
 
@@ -3779,6 +3791,27 @@ void MainWindow::slotMaximizeCurrent(bool)
     kDebug() << "CURRENT WIDGET: " << par->objectName();
 }
 
+void MainWindow::loadStabilize()
+{
+       QMenu* stabMenu= static_cast<QMenu*>(factory()->container("stabilize", this));
+       if (stabMenu){
+               stabMenu->clear();
+               Mlt::Profile profile;
+               if (Mlt::Factory::filter(profile,(char*)"videostab")){
+                       QAction *action=stabMenu->addAction("Videostab (vstab)");
+                       action->setData("videostab");
+                       connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize()));
+               }
+               if (Mlt::Factory::filter(profile,(char*)"videostab2")){
+                       QAction *action=stabMenu->addAction("Videostab (transcode)");
+                       action->setData("videostab2");
+                       connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize()));
+               }
+       }
+
+
+}
+
 void MainWindow::loadTranscoders()
 {
     QMenu *transMenu = static_cast<QMenu*>(factory()->container("transcoders", this));
@@ -3800,6 +3833,29 @@ void MainWindow::loadTranscoders()
     }
 }
 
+void MainWindow::slotStabilize(KUrl::List urls)
+{
+       QString condition,filtername;
+
+       if (urls.isEmpty()) {
+        QAction *action = qobject_cast<QAction *>(sender());
+               if (action){
+                       filtername=action->data().toString();
+                       urls = m_projectList->getConditionalUrls(condition);
+               }
+    }
+    if (urls.isEmpty()) {
+        m_messageLabel->setMessage(i18n("No clip to transcode"), ErrorMessage);
+        return;
+    }
+       Mlt::Profile profile;
+       Mlt::Filter filter(profile,filtername.toUtf8().data());
+       ClipStabilize *d=new ClipStabilize(urls,filtername,&filter);
+       connect(d, SIGNAL(addClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl)));
+       d->show();
+
+}
+
 void MainWindow::slotTranscode(KUrl::List urls)
 {
     QString params;