]> git.sesse.net Git - kdenlive/blobdiff - src/clipmanager.cpp
Fix forcing some clip properties not always working correctly
[kdenlive] / src / clipmanager.cpp
index c65526969a52eda0b4cee4e613fe0e7c7e7975d5..f8d556f0a43f784c6a8bfabe7fe0290cdcb47671 100644 (file)
@@ -26,6 +26,7 @@
 #include "abstractclipitem.h"
 #include "abstractgroupitem.h"
 #include "titledocument.h"
+#include "subprojectitem.h"
 #include "kthumb.h"
 
 #include <mlt++/Mlt.h>
@@ -122,7 +123,7 @@ void ClipManager::clearCache()
 #endif
 }
 
-void ClipManager::requestThumbs(const QString id, QList <int> frames)
+void ClipManager::slotRequestThumbs(const QString id, QList <int> frames)
 {
     m_thumbsMutex.lock();
     foreach (int frame, frames) {
@@ -167,19 +168,42 @@ void ClipManager::slotGetThumbs()
     QMap<QString, int>::const_iterator i;
     int max;
     int done = 0;
+    int thumbType = 0; // 0 = timeline thumb, 1 = project clip zone thumb, 2 = clip properties thumb
+    
     while (!m_requestedThumbs.isEmpty() && !m_abortThumb) {
         m_thumbsMutex.lock();
         i = m_requestedThumbs.constBegin();
         m_processingThumbId = i.key();
         QList<int> values = m_requestedThumbs.values(m_processingThumbId);
         m_requestedThumbs.remove(m_processingThumbId);
+       if (m_processingThumbId.startsWith("?")) {
+           // if id starts with ?, it means the request comes from a clip property widget
+           thumbType = 2;
+           m_processingThumbId.remove(0, 1);
+       }
+       if (m_processingThumbId.startsWith("#")) {
+           // if id starts with #, it means the request comes from project tree
+           thumbType = 1;
+           m_processingThumbId.remove(0, 1);
+       }
         m_thumbsMutex.unlock();
         qSort(values);
         DocClipBase *clip = getClipById(m_processingThumbId);
         if (!clip) continue;
         max = m_requestedThumbs.size() + values.count();
+       int pos;
         while (!values.isEmpty() && clip->thumbProducer() && !m_abortThumb) {
-            clip->thumbProducer()->getThumb(values.takeFirst());
+           pos = values.takeFirst();
+           switch (thumbType) {
+             case 1:
+                 clip->thumbProducer()->getGenericThumb(pos, SubProjectItem::itemDefaultHeight(), thumbType);
+                 break;
+             case 2:
+                 clip->thumbProducer()->getGenericThumb(pos, 180, thumbType);
+                 break;
+             default:
+                 clip->thumbProducer()->getThumb(pos);
+           }
             done++;
             if (max > 3) emit displayMessage(i18n("Loading thumbnails"), 100 * done / max);
         }
@@ -228,7 +252,7 @@ void ClipManager::askForAudioThumb(const QString &id)
 void ClipManager::slotGetAudioThumbs()
 {
     Mlt::Profile prof((char*) KdenliveSettings::current_profile().toUtf8().constData());
-    mlt_audio_format audioFormat = mlt_audio_pcm;
+    mlt_audio_format audioFormat = mlt_audio_s16;
     while (!m_abortAudioThumb && !m_audioThumbsQueue.isEmpty()) {
         m_thumbsMutex.lock();
         m_processingAudioThumbId = m_audioThumbsQueue.takeFirst();
@@ -240,11 +264,17 @@ void ClipManager::slotGetAudioThumbs()
         if (hash.isEmpty()) continue;
         QString audioPath = projectFolder() + "/thumbs/" + hash + ".thumb";
         double lengthInFrames = clip->duration().frames(m_doc->fps());
-        //FIXME: should this be hardcoded??
-        int channels = 2;
-        int frequency = 48000;
-        int arrayWidth = 20;
+       int frequency = 0;
+       int channels = 0;
+       QString data = clip->getProperty("frequency");
+       if (!data.isEmpty()) frequency = data.toInt();
+       if (frequency <= 0) frequency = 48000;
+       data = clip->getProperty("channels");
+       if (!data.isEmpty()) channels = data.toInt();
+       if (channels <= 0) channels = 2;
+       int arrayWidth = 20;
         double frame = 0.0;
+       int maxVolume = 0;
         audioByteArray storeIn;
         QFile f(audioPath);
         if (QFileInfo(audioPath).size() > 0 && f.open(QIODevice::ReadOnly)) {
@@ -266,13 +296,17 @@ void ClipManager::slotGetAudioThumbs()
                     QByteArray audioArray(arrayWidth, '\x00');
                     for (int i = 0; i < arrayWidth; i++) {
                         audioArray[i] = channelarray.at(h2 + h3 + i);
+                       if (audioArray.at(i) > maxVolume) maxVolume = audioArray.at(i);
                     }
                     h3 += arrayWidth;
                     storeIn[z][c] = audioArray;
                 }
                 h2 += h1;
             }
-            if (!m_abortAudioThumb) clip->updateAudioThumbnail(storeIn);
+            if (!m_abortAudioThumb) {
+               clip->setProperty("audio_max", QString::number(maxVolume - 64));
+               clip->updateAudioThumbnail(storeIn);
+           }
             continue;
         } 
         
@@ -295,9 +329,9 @@ void ClipManager::slotGetAudioThumbs()
         producer.set("video_index", "-1");
 
         if (KdenliveSettings::normaliseaudiothumbs()) {
-            Mlt::Filter m_convert(prof, "volume");
+            /*Mlt::Filter m_convert(prof, "volume");
             m_convert.set("gain", "normalise");
-            producer.attach(m_convert);
+            producer.attach(m_convert);*/
         }
 
         int last_val = 0;
@@ -320,7 +354,17 @@ void ClipManager::slotGetAudioThumbs()
                     QByteArray audioArray;
                     audioArray.resize(arrayWidth);
                     for (int i = 0; i < audioArray.size(); i++) {
-                        audioArray[i] = ((*(pcm + c + i * samples / audioArray.size())) >> 9) + 127 / 2 ;
+                       double pcmval = *(pcm + c + i * samples / audioArray.size());
+                       if (pcmval >= 0) {
+                           pcmval = sqrt(pcmval) / 2.83 + 64;
+                           audioArray[i] = pcmval;
+                           if (pcmval > maxVolume) maxVolume = pcmval;
+                       }
+                       else {
+                           pcmval = -sqrt(-pcmval) / 2.83 + 64;
+                           audioArray[i] = pcmval;
+                           if (-pcmval > maxVolume) maxVolume = -pcmval;
+                       }
                     }
                     f.write(audioArray);
                     storeIn[z][c] = audioArray;
@@ -336,6 +380,7 @@ void ClipManager::slotGetAudioThumbs()
             f.remove();
         } else {
             clip->updateAudioThumbnail(storeIn);
+           clip->setProperty("audio_max", QString::number(maxVolume - 64));
         }
     }
     m_processingAudioThumbId.clear();
@@ -388,12 +433,12 @@ void ClipManager::deleteClip(const QString &clipId)
 {
     for (int i = 0; i < m_clipList.count(); i++) {
         if (m_clipList.at(i)->getId() == clipId) {
-            if (m_clipList.at(i)->clipType() != COLOR && m_clipList.at(i)->clipType() != SLIDESHOW  && !m_clipList.at(i)->fileURL().isEmpty()) {
+           DocClipBase *clip = m_clipList.takeAt(i);
+            if (clip->clipType() != COLOR && clip->clipType() != SLIDESHOW  && !clip->fileURL().isEmpty()) {
                 //if (m_clipList.at(i)->clipType() == IMAGE || m_clipList.at(i)->clipType() == AUDIO || (m_clipList.at(i)->clipType() == TEXT && !m_clipList.at(i)->fileURL().isEmpty())) {
                 // listen for file change
-                m_fileWatcher.removeFile(m_clipList.at(i)->fileURL().path());
+                m_fileWatcher.removeFile(clip->fileURL().path());
             }
-            DocClipBase *clip = m_clipList.takeAt(i);
             delete clip;
             clip = NULL;
             break;
@@ -531,7 +576,7 @@ void ClipManager::slotAddClipList(const KUrl::List urls, QMap <QString, QString>
             if (type->name().startsWith("image/")) {
                 prod.setAttribute("type", (int) IMAGE);
                 prod.setAttribute("in", 0);
-                prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::image_duration()));
+                prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::image_duration()) - 1);
                 if (KdenliveSettings::autoimagetransparency()) prod.setAttribute("transparency", 1);
                 // Read EXIF metadata for JPEG
                 if (type->is("image/jpeg")) {
@@ -561,15 +606,23 @@ void ClipManager::slotAddClipList(const KUrl::List urls, QMap <QString, QString>
                             }
                         }
                     }
-                    QString titleData = txtdoc.toString();
-                    prod.setAttribute("xmldata", titleData);
                     prod.setAttribute("transparency", 1);
                     prod.setAttribute("in", 0);
-                    int out = txtdoc.documentElement().attribute("out").toInt();
-                    if (out > 0)
-                        prod.setAttribute("out", out);
-                    else
-                        prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::title_duration()));
+                   if (!txtdoc.documentElement().hasAttribute("out")) {
+                       prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::title_duration()) - 1);
+                       txtdoc.documentElement().setAttribute("out", m_doc->getFramePos(KdenliveSettings::title_duration()) - 1);
+                   }
+                   else {
+                       int out = txtdoc.documentElement().attribute("out").toInt();
+                       if (out >= 0)
+                           prod.setAttribute("out", out);
+                       else {
+                           prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::title_duration()) - 1);
+                           txtdoc.documentElement().setAttribute("out", m_doc->getFramePos(KdenliveSettings::title_duration()) - 1);
+                       }
+                   }
+                   QString titleData = txtdoc.toString();
+                    prod.setAttribute("xmldata", titleData);
                 } else
                     txtfile.close();
             }
@@ -616,7 +669,7 @@ void ClipManager::slotAddColorClipFile(const QString &name, const QString &color
     uint id = m_clipIdCounter++;
     prod.setAttribute("id", QString::number(id));
     prod.setAttribute("in", "0");
-    prod.setAttribute("out", m_doc->getFramePos(duration));
+    prod.setAttribute("out", m_doc->getFramePos(duration) - 1);
     prod.setAttribute("name", name);
     if (!group.isEmpty()) {
         prod.setAttribute("groupname", group);
@@ -648,7 +701,7 @@ void ClipManager::slotAddSlideshowClipFile(QMap <QString, QString> properties, c
 
 
 
-void ClipManager::slotAddTextClipFile(const QString &titleName, int out, const QString &xml, const QString &group, const QString &groupId)
+void ClipManager::slotAddTextClipFile(const QString &titleName, int duration, const QString &xml, const QString &group, const QString &groupId)
 {
     QDomDocument doc;
     QDomElement prod = doc.createElement("producer");
@@ -665,7 +718,7 @@ void ClipManager::slotAddTextClipFile(const QString &titleName, int out, const Q
     prod.setAttribute("type", (int) TEXT);
     prod.setAttribute("transparency", "1");
     prod.setAttribute("in", "0");
-    prod.setAttribute("out", out);
+    prod.setAttribute("out", duration - 1);
     AddClipCommand *command = new AddClipCommand(m_doc, doc.documentElement(), QString::number(id), true);
     m_doc->commandStack()->push(command);
 }
@@ -687,16 +740,22 @@ void ClipManager::slotAddTextTemplateClip(QString titleName, const KUrl &path, c
     prod.setAttribute("transparency", "1");
     prod.setAttribute("in", "0");
 
-    int out = 0;
+    int duration = 0;
     QDomDocument titledoc;
     QFile txtfile(path.path());
     if (txtfile.open(QIODevice::ReadOnly) && titledoc.setContent(&txtfile)) {
         txtfile.close();
-        out = titledoc.documentElement().attribute("out").toInt();
+       if (titledoc.documentElement().hasAttribute("duration")) {
+           duration = titledoc.documentElement().attribute("duration").toInt();
+       }
+        else {
+           // keep some time for backwards compatibility - 26/12/12
+           duration = titledoc.documentElement().attribute("out").toInt();
+       }
     } else txtfile.close();
 
-    if (out == 0) out = m_doc->getFramePos(KdenliveSettings::image_duration());
-    prod.setAttribute("out", out);
+    if (duration == 0) duration = m_doc->getFramePos(KdenliveSettings::title_duration());
+    prod.setAttribute("out", duration - 1);
 
     AddClipCommand *command = new AddClipCommand(m_doc, doc.documentElement(), QString::number(id), true);
     m_doc->commandStack()->push(command);
@@ -918,5 +977,14 @@ bool ClipManager::isOnRemovableDevice(const KUrl &url)
     return volumeMatch;
 }
 
-
+void ClipManager::projectTreeThumbReady(const QString &id, int frame, QImage img, int type)
+{
+    switch (type) {
+      case 2:
+         emit gotClipPropertyThumbnail(id, img);
+         break;
+      default:
+       emit thumbReady(id, frame, img);
+    }
+}