]> git.sesse.net Git - kdenlive/blobdiff - src/mainwindow.cpp
Freesound: save audio file url in clip comment (for attribution)
[kdenlive] / src / mainwindow.cpp
index a3250118bc21c98042ec4d459582a9be0e721ea6..93c3e9758db0186dfc350d03d2726ea98b494f21 100644 (file)
@@ -54,6 +54,7 @@
 #include "interfaces.h"
 #include "config-kdenlive.h"
 #include "cliptranscode.h"
+#include "clipstabilize.h"
 #include "ui_templateclip_ui.h"
 #include "colorscopes/vectorscope.h"
 #include "colorscopes/waveform.h"
@@ -63,6 +64,7 @@
 #include "audioscopes/spectrogram.h"
 #include "archivewidget.h"
 #include "databackup/backupwidget.h"
+#include "utils/freesound.h"
 
 
 #include <KApplication>
 #include <QBitmap>
 
 #include <stdlib.h>
+#include <locale.h>
 
 // Uncomment for deeper debugging
 //#define DEBUG_MAINW
@@ -156,6 +159,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);
 
@@ -211,16 +223,17 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_clipMonitorDock->setWidget(m_clipMonitor);
     
     // Connect the project list
-    connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint)));
+    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()));
+    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)));
+    connect(m_clipMonitor, SIGNAL(extractZone(const QString &, QPoint)), m_projectList, SLOT(slotCutClipJob(const QString &, QPoint)));
 
     m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this);
     m_projectMonitorDock->setObjectName("project_monitor");
@@ -235,6 +248,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 /* ! Q_WS_MAC */
     m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor, m_recMonitor);
 
@@ -256,6 +270,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_effectStack = new EffectStackView(m_projectMonitor);
     m_effectStackDock->setWidget(m_effectStack);
     addDockWidget(Qt::TopDockWidgetArea, m_effectStackDock);
+    connect(m_effectStack, SIGNAL(startFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&)), m_projectList, SLOT(slotStartFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&)));
 
     m_transitionConfigDock = new QDockWidget(i18n("Transition"), this);
     m_transitionConfigDock->setObjectName("transition");
@@ -484,6 +499,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     clipInTimeline->setIcon(KIcon("go-jump"));
        QHash<QString,QMenu*> menus;
        menus.insert("addMenu",static_cast<QMenu*>(factory()->container("generators", this)));
+        menus.insert("extractAudioMenu",static_cast<QMenu*>(factory()->container("extract_audio", 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);
@@ -1623,6 +1639,10 @@ void MainWindow::setupActions()
     QAction *addFolderButton = new KAction(KIcon("folder-new"), i18n("Create Folder"), this);
     collection.addAction("add_folder", addFolderButton);
     connect(addFolderButton , SIGNAL(triggered()), m_projectList, SLOT(slotAddFolder()));
+    
+    QAction *downloadAudio = new KAction(KIcon("download"), i18n("Download Audio"), this);
+    collection.addAction("download_audio", downloadAudio);
+    connect(downloadAudio , SIGNAL(triggered()), this, SLOT(slotDownloadAudio()));
 
     QAction *clipProperties = new KAction(KIcon("document-edit"), i18n("Clip Properties"), this);
     collection.addAction("clip_properties", clipProperties);
@@ -2355,7 +2375,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&)));
@@ -2470,7 +2492,9 @@ 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_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), m_activeTimeline->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap)));
+            
             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)));
@@ -2546,11 +2570,13 @@ 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*)));
     connect(trackView->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*)));
+    
+    connect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), trackView->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap)));
 
     connect(m_effectStack, SIGNAL(updateEffect(ClipItem*, int, QDomElement, QDomElement, int)), trackView->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, int, QDomElement, QDomElement, int)));
     connect(m_effectStack, SIGNAL(updateClipRegion(ClipItem*, int, QString)), trackView->projectView(), SLOT(slotUpdateClipRegion(ClipItem*, int, QString)));
@@ -2683,7 +2709,7 @@ void MainWindow::updateConfiguration()
 
     // Update list of transcoding profiles
     loadTranscoders();
-       loadStabilize();
+    loadStabilize();
 #ifdef USE_JOGSHUTTLE
     activateShuttleDevice();
 #endif
@@ -3029,10 +3055,10 @@ void MainWindow::slotEditItemDuration()
         m_activeTimeline->projectView()->editItemDuration();
 }
 
-void MainWindow::slotAddProjectClip(KUrl url)
+void MainWindow::slotAddProjectClip(KUrl url, const QString &comment)
 {
     if (m_activeDocument)
-        m_activeDocument->slotAddClipFile(url, QString());
+        m_activeDocument->slotAddClipFile(url, QString(), QString(), comment);
 }
 
 void MainWindow::slotAddProjectClipList(KUrl::List urls)
@@ -3192,7 +3218,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);
                 }
             }
@@ -3207,7 +3233,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();
@@ -3222,7 +3248,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);
@@ -3270,9 +3296,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++)
@@ -3781,17 +3807,19 @@ void MainWindow::slotMaximizeCurrent(bool)
 void MainWindow::loadStabilize()
 {
        QMenu* stabMenu= static_cast<QMenu*>(factory()->container("stabilize", this));
-       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()));
+       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()));
+               }
        }
 
 
@@ -3801,6 +3829,9 @@ void MainWindow::loadTranscoders()
 {
     QMenu *transMenu = static_cast<QMenu*>(factory()->container("transcoders", this));
     transMenu->clear();
+    
+    QMenu *extractAudioMenu = static_cast<QMenu*>(factory()->container("extract_audio", this));
+    extractAudioMenu->clear();
 
     KSharedConfigPtr config = KSharedConfig::openConfig("kdenlivetranscodingrc");
     KConfigGroup transConfig(config, "Transcoding");
@@ -3809,25 +3840,42 @@ void MainWindow::loadTranscoders()
     QMapIterator<QString, QString> i(profiles);
     while (i.hasNext()) {
         i.next();
-        QStringList data = i.value().split(";", QString::SkipEmptyParts);
-        QAction *a = transMenu->addAction(i.key());
+        QStringList data = i.value().split(";");
+        QAction *a;
+        // separate audio transcoding in a separate menu
+        if (data.count() > 2 && data.at(2) == "audio") {
+            a = extractAudioMenu->addAction(i.key());
+        }
+        else {
+            a = transMenu->addAction(i.key());
+        }
         a->setData(data);
-        if (data.count() > 1)
-            a->setToolTip(data.at(1));
+        if (data.count() > 1) a->setToolTip(data.at(1));
         connect(a, SIGNAL(triggered()), this, SLOT(slotTranscode()));
     }
 }
 
 void MainWindow::slotStabilize(KUrl::List urls)
 {
-       QString condition;
-       if (urls.isEmpty()) {
+    QString condition,filtername;
+
+    if (urls.isEmpty()) {
         QAction *action = qobject_cast<QAction *>(sender());
-               if (action){
-                       QString filtername=action->data().toString();
-                       urls = m_projectList->getConditionalUrls(condition);
-               }
+       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)
@@ -3840,9 +3888,10 @@ void MainWindow::slotTranscode(KUrl::List urls)
         QStringList data = action->data().toStringList();
         params = data.at(0);
         if (data.count() > 1) desc = data.at(1);
-        if (data.count() > 2) condition = data.at(2);
-        urls << m_projectList->getConditionalUrls(condition);
-        urls.removeAll(KUrl());
+        if (data.count() > 3) condition = data.at(3);
+        QStringList ids = m_projectList->getConditionalIds(condition);
+        m_projectList->slotTranscodeClipJob(ids, params, desc);
+        return;
     }
     if (urls.isEmpty()) {
         m_messageLabel->setMessage(i18n("No clip to transcode"), ErrorMessage);
@@ -3851,7 +3900,6 @@ void MainWindow::slotTranscode(KUrl::List urls)
     ClipTranscode *d = new ClipTranscode(urls, params, desc);
     connect(d, SIGNAL(addClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl)));
     d->show();
-    //QProcess::startDetached("ffmpeg", parameters);
 }
 
 void MainWindow::slotTranscodeClip()
@@ -4350,7 +4398,6 @@ 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;
@@ -4359,6 +4406,9 @@ void MainWindow::slotUpdateColorScopes()
     if (request && m_monitorManager->activeRenderer()) {
         m_monitorManager->activeRenderer()->sendFrameUpdate();
     }
+    if (m_audiosignal->isVisible() && m_recMonitor->abstractRender()) {
+        connect(m_recMonitor->abstractRender(), 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&)));
+    }
 }
 
 void MainWindow::slotClearColorScopes()
@@ -4451,6 +4501,17 @@ void MainWindow::slotElapsedTime()
     kDebug()<<"-----------------------------------------\n"<<"Time elapsed: "<<m_timer.elapsed()<<"\n-------------------------";
 }
 
+
+void MainWindow::slotDownloadAudio()
+{
+    QString currentFolder;
+    if (m_activeDocument) currentFolder = m_activeDocument->projectFolder().path();
+    else currentFolder = KdenliveSettings::defaultprojectfolder();
+    FreeSound *d = new FreeSound(currentFolder);
+    connect(d, SIGNAL(addClip(KUrl, const QString &)), this, SLOT(slotAddProjectClip(KUrl, const QString &)));
+    d->show();
+}
+
 #include "mainwindow.moc"
 
 #ifdef DEBUG_MAINW