]> git.sesse.net Git - kdenlive/blobdiff - src/renderer.cpp
Updated translation file
[kdenlive] / src / renderer.cpp
index d107fbbc05076712df14147582d665b112e3fd44..57e2ef85120ef844da7d3423fdb95acc61f37e2f 100644 (file)
@@ -116,12 +116,15 @@ void Render::closeMlt()
             Mlt::Tractor tractor(service);
             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") {
-                mlt_field_disconnect_service(field->get_field(), nextservice);
+                nextservicetodisconnect = nextservice;
+                nextservice = mlt_service_producer(nextservice);
+                mlt_field_disconnect_service(field->get_field(), nextservicetodisconnect);
                 nextservice = mlt_service_producer(nextservice);
                 if (nextservice == NULL) break;
                 properties = MLT_SERVICE_PROPERTIES(nextservice);
@@ -244,7 +247,7 @@ int Render::resetProfile()
     m_mltConsumer = NULL;
     QString scene = sceneList();
     int pos = 0;
-
+    double current_fps = m_mltProfile->fps();
     delete m_blackClip;
     m_blackClip = NULL;
 
@@ -268,10 +271,15 @@ int Render::resetProfile()
     m_mltProducer = NULL;
 
     buildConsumer();
-
+    double new_fps = m_mltProfile->fps();
+    if (current_fps != new_fps) {
+        // fps changed, we must update the scenelist positions
+        scene = updateSceneListFps(current_fps, new_fps, scene);
+    }
     //kDebug() << "//RESET WITHSCENE: " << scene;
     setSceneList(scene, pos);
-
+    // producers have changed (different profile), so reset them...
+    emit refreshDocumentProducers();
     /*char *tmp = decodedString(scene);
     Mlt::Producer *producer = new Mlt::Producer(*m_mltProfile , "xml-string", tmp);
     delete[] tmp;
@@ -342,14 +350,15 @@ int Render::renderHeight() const
     return m_mltProfile->height();
 }
 
-QPixmap Render::extractFrame(int frame_position, int width, int height)
+QImage Render::extractFrame(int frame_position, int width, int height)
 {
     if (width == -1) {
         width = renderWidth();
         height = renderHeight();
     } else if (width % 2 == 1) width++;
-    QPixmap pix(width, height);
+
     if (!m_mltProducer) {
+        QImage pix(width, height, QImage::Format_RGB32);
         pix.fill(Qt::black);
         return pix;
     }
@@ -635,6 +644,12 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, boo
     producer->set("id", tmp);
     delete[] tmp;
 
+    if (xml.hasAttribute("templatetext")) {
+        char *tmp = decodedString(xml.attribute("templatetext"));
+        producer->set("templatetext", tmp);
+        delete[] tmp;
+    }
+
     if (!replaceProducer && xml.hasAttribute("file_hash")) {
         // Clip  already has all properties
         emit replyGetFileProperties(clipId, producer, QMap < QString, QString >(), QMap < QString, QString >(), replaceProducer);
@@ -921,13 +936,15 @@ int Render::setSceneList(QString playlist, int position)
             Mlt::Tractor tractor(service);
             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") {
-                mlt_field_disconnect_service(field->get_field(), nextservice);
+                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");
@@ -999,7 +1016,7 @@ int Render::setSceneList(QString playlist, int position)
 
     m_isBlocked = false;
     blockSignals(false);
-    emit refreshDocumentProducers();
+
     return error;
     //kDebug()<<"// SETSCN LST, POS: "<<position;
     //if (position != 0) emit rendererPosition(position);
@@ -1356,7 +1373,11 @@ void Render::setDropFrames(bool show)
         int dropFrames = 1;
         if (show == false) dropFrames = 0;
         m_mltConsumer->stop();
+#ifdef Q_WS_MAC
+        m_mltConsumer->set("real_time", dropFrames);
+#else
         m_mltConsumer->set("play.real_time", dropFrames);
+#endif
         if (m_mltConsumer->start() == -1) {
             emit blockMonitors();
             delete m_mltProducer;
@@ -1665,8 +1686,40 @@ void Render::mltCutClip(int track, GenTime position)
 void Render::mltUpdateClip(ItemInfo info, QDomElement element, Mlt::Producer *prod)
 {
     // TODO: optimize
+    Mlt::Service service(m_mltProducer->parent().get_service());
+    if (service.type() != tractor_type) {
+        kWarning() << "// TRACTOR PROBLEM";
+        return;
+    }
+    Mlt::Tractor tractor(service);
+    Mlt::Producer trackProducer(tractor.track(info.track));
+    Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+    int startPos = info.startPos.frames(m_fps);
+    int clipIndex = trackPlaylist.get_clip_index_at(startPos);
+    Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
+
+    // keep effects
+    QList <Mlt::Filter *> filtersList;
+    Mlt::Service sourceService(clip->get_service());
+    int ct = 0;
+    Mlt::Filter *filter = sourceService.filter(ct);
+    while (filter) {
+        if (filter->get("kdenlive_ix") != 0) {
+            filtersList.append(filter);
+        }
+        ct++;
+        filter = sourceService.filter(ct);
+    }    
     mltRemoveClip(info.track, info.startPos);
     mltInsertClip(info, element, prod);
+    if (!filtersList.isEmpty()) {
+        clipIndex = trackPlaylist.get_clip_index_at(startPos);
+        Mlt::Producer *destclip = trackPlaylist.get_clip(clipIndex);
+        Mlt::Service destService(destclip->get_service());
+        delete destclip;
+        for (int i = 0; i < filtersList.count(); i++)
+            destService.attach(*(filtersList.at(i)));
+    }
 }
 
 
@@ -1910,6 +1963,7 @@ void Render::mltInsertSpace(QMap <int, int> trackClipStartList, QMap <int, int>
 
 void Render::mltPasteEffects(Mlt::Producer *source, Mlt::Producer *dest)
 {
+    if (source == dest) return;
     Mlt::Service sourceService(source->get_service());
     Mlt::Service destService(dest->get_service());
 
@@ -1942,21 +1996,22 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, int
     int clipIndex = trackPlaylist.get_clip_index_at(startPos);
     int clipLength = trackPlaylist.clip_length(clipIndex);
 
-    Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
-    if (clip == NULL) {
+    Mlt::Producer *original = trackPlaylist.get_clip(clipIndex);
+    if (original == NULL) {
         return -1;
     }
-    if (!clip->is_valid() || clip->is_blank()) {
+    if (!original->is_valid() || original->is_blank()) {
         // invalid clip
-        delete clip;
+        delete original;
         return -1;
     }
-    Mlt::Producer clipparent = clip->parent();
+    Mlt::Producer clipparent = original->parent();
     if (!clipparent.is_valid() || clipparent.is_blank()) {
         // invalid clip
-        delete clip;
+        delete original;
         return -1;
     }
+    delete original;
 
     QString serv = clipparent.get("mlt_service");
     QString id = clipparent.get("id");
@@ -1968,8 +2023,8 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, int
         if (strobe > 1) url.append("&strobe=" + QString::number(strobe));
         Mlt::Producer *slowprod = m_slowmotionProducers.value(url);
         if (!slowprod || slowprod->get_producer() == NULL) {
-            char *tmp = decodedString(url);
-            slowprod = new Mlt::Producer(*m_mltProfile, "framebuffer", tmp);
+            char *tmp = decodedString("framebuffer:" + url);
+            slowprod = new Mlt::Producer(*m_mltProfile, 0, tmp);
             if (strobe > 1) slowprod->set("strobe", strobe);
             delete[] tmp;
             QString producerid = "slowmotion:" + id + ':' + QString::number(speed);
@@ -2034,8 +2089,8 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, int
         if (strobe > 1) url.append("&strobe=" + QString::number(strobe));
         Mlt::Producer *slowprod = m_slowmotionProducers.value(url);
         if (!slowprod || slowprod->get_producer() == NULL) {
-            char *tmp = decodedString(url);
-            slowprod = new Mlt::Producer(*m_mltProfile, "framebuffer", tmp);
+            char *tmp = decodedString("framebuffer:" + url);
+            slowprod = new Mlt::Producer(*m_mltProfile, 0, tmp);
             delete[] tmp;
             slowprod->set("strobe", strobe);
             QString producerid = "slowmotion:" + id.section(':', 1, 1) + ':' + QString::number(speed);
@@ -2073,7 +2128,6 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, int
         mlt_service_unlock(service.get_service());
     }
 
-    delete clip;
     if (clipIndex + 1 == trackPlaylist.count()) mltCheckLength(&tractor);
     m_isBlocked = false;
     return newLength;
@@ -2248,7 +2302,6 @@ bool Render::mltAddEffect(int track, GenTime position, EffectsParameterList para
     for (int i = 0; i < filtersList.count(); i++) {
         clipService.attach(*(filtersList.at(i)));
     }
-
     m_isBlocked = false;
     if (doRefresh) refresh();
     return true;
@@ -2612,9 +2665,9 @@ void Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod)
     Mlt::Tractor tractor(service);
     Mlt::Producer trackProducer(tractor.track(track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
-    int clipIndex = trackPlaylist.get_clip_index_at(pos + 1);
+    int clipIndex = trackPlaylist.get_clip_index_at(pos);
     Mlt::Producer *clipProducer = trackPlaylist.replace_with_blank(clipIndex);
-    if (clipProducer->is_blank()) {
+    if (clipProducer == NULL || clipProducer->is_blank()) {
         kDebug() << "// ERROR UPDATING CLIP PROD";
         delete clipProducer;
         mlt_service_unlock(m_mltConsumer->get_service());
@@ -2709,8 +2762,9 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
 
             // move all effects to the correct producer
             mltPasteEffects(clipProducer, clip);
-
+            
             int newIndex = destTrackPlaylist.insert_at(moveEnd, clip, 1);
+            
             if (clip == clipProducer) {
                 delete clip;
                 clip = NULL;
@@ -3341,5 +3395,100 @@ void Render::updatePreviewSettings()
     setSceneList(scene, pos);
 }
 
+
+QString Render::updateSceneListFps(double current_fps, double new_fps, QString scene)
+{
+    // Update all frame positions to the new fps value
+    //WARNING: there are probably some effects or other that hold a frame value
+    // as parameter and will also need to be updated here!
+    QDomDocument doc;
+    doc.setContent(scene);
+
+    double factor = new_fps / current_fps;
+    QDomNodeList producers = doc.elementsByTagName("producer");
+    for (int i = 0; i < producers.count(); i++) {
+        QDomElement prod = producers.at(i).toElement();
+        prod.removeAttribute("in");
+        prod.removeAttribute("out");
+
+        QDomNodeList props = prod.childNodes();
+        for (int j = 0; j < props.count(); j++) {
+            QDomElement param =  props.at(j).toElement();
+            QString paramName = param.attribute("name");
+            if (paramName.startsWith("meta.") || paramName == "length") {
+                prod.removeChild(props.at(j));
+                j--;
+            }
+        }
+    }
+
+    QDomNodeList entries = doc.elementsByTagName("entry");
+    for (int i = 0; i < entries.count(); i++) {
+        QDomElement entry = entries.at(i).toElement();
+        int in = entry.attribute("in").toInt();
+        int out = entry.attribute("out").toInt();
+        in = factor * in + 0.5;
+        out = factor * out + 0.5;
+        entry.setAttribute("in", in);
+        entry.setAttribute("out", out);
+    }
+
+    QDomNodeList blanks = doc.elementsByTagName("blank");
+    for (int i = 0; i < blanks.count(); i++) {
+        QDomElement blank = blanks.at(i).toElement();
+        int length = blank.attribute("length").toInt();
+        length = factor * length + 0.5;
+        blank.setAttribute("length", QString::number(length));
+    }
+
+    QDomNodeList filters = doc.elementsByTagName("filter");
+    for (int i = 0; i < filters.count(); i++) {
+        QDomElement filter = filters.at(i).toElement();
+        int in = filter.attribute("in").toInt();
+        int out = filter.attribute("out").toInt();
+        in = factor * in + 0.5;
+        out = factor * out + 0.5;
+        filter.setAttribute("in", in);
+        filter.setAttribute("out", out);
+    }
+
+    QDomNodeList transitions = doc.elementsByTagName("transition");
+    for (int i = 0; i < transitions.count(); i++) {
+        QDomElement transition = transitions.at(i).toElement();
+        int in = transition.attribute("in").toInt();
+        int out = transition.attribute("out").toInt();
+        in = factor * in + 0.5;
+        out = factor * out + 0.5;
+        transition.setAttribute("in", in);
+        transition.setAttribute("out", out);
+        QDomNodeList props = transition.childNodes();
+        for (int j = 0; j < props.count(); j++) {
+            QDomElement param =  props.at(j).toElement();
+            QString paramName = param.attribute("name");
+            if (paramName == "geometry") {
+                QString geom = param.firstChild().nodeValue();
+                QStringList keys = geom.split(';');
+                QStringList newKeys;
+                for (int k = 0; k < keys.size(); ++k) {
+                    if (keys.at(k).contains('=')) {
+                        int pos = keys.at(k).section('=', 0, 0).toInt();
+                        pos = factor * pos + 0.5;
+                        newKeys.append(QString::number(pos) + '=' + keys.at(k).section('=', 1));
+                    } else newKeys.append(keys.at(k));
+                }
+                param.firstChild().setNodeValue(newKeys.join(";"));
+            }
+        }
+    }
+    QDomElement tractor = doc.elementsByTagName("tractor").at(0).toElement();
+    int out = tractor.attribute("out").toInt();
+    out = factor * out + 0.5;
+    tractor.setAttribute("out", out);
+    emit durationChanged(out);
+
+    //kDebug() << "///////////////////////////// " << out << " \n" << doc.toString() << "\n-------------------------";
+    return doc.toString();
+}
+
 #include "renderer.moc"