]> git.sesse.net Git - kdenlive/blobdiff - src/renderer.cpp
Add / remove track now seems to work, still a few crashes if project monitor was...
[kdenlive] / src / renderer.cpp
index 467632e6a44e11a0adc109a0cb801a05481e89a6..37011c5ee64e080505fd6ea60086be5a97539baa 100644 (file)
@@ -775,7 +775,10 @@ void Render::setSceneList(QString playlist, int position) {
     if (m_mltConsumer) {
         m_mltConsumer->stop();
         //m_mltConsumer->set("refresh", 0);
-    } else return;
+    } else {
+        m_isBlocked = false;
+        return;
+    }
 
     if (m_mltProducer) {
         m_mltProducer->set_speed(0);
@@ -786,6 +789,7 @@ void Render::setSceneList(QString playlist, int position) {
         emit stopped();
     }
 
+    blockSignals(true);
     char *tmp = decodedString(playlist);
     m_mltProducer = new Mlt::Producer(*m_mltProfile, "westley-xml", tmp);
     delete[] tmp;
@@ -826,11 +830,11 @@ void Render::setSceneList(QString playlist, int position) {
     if (position != 0) {
         //TODO: seek to correct place after opening project.
         //  Needs to be done from another place since it crashes here.
-        //m_mltProducer->seek(position);
-        //emit rendererPosition(position);
+        m_mltProducer->seek(position);
     }
     m_isBlocked = false;
-
+    blockSignals(false);
+    emit rendererPosition(position);
 }
 
 /** Create the producer from the Westley QDomDocument */
@@ -1445,6 +1449,29 @@ bool Render::mltRemoveClip(int track, GenTime position) {
     return true;
 }
 
+int Render::mltGetSpaceLength(const GenTime pos, int track) {
+    if (!m_mltProducer) {
+        kDebug() << "PLAYLIST NOT INITIALISED //////";
+        return -1;
+    }
+    Mlt::Producer parentProd(m_mltProducer->parent());
+    if (parentProd.get_producer() == NULL) {
+        kDebug() << "PLAYLIST BROKEN, CANNOT INSERT CLIP //////";
+        return -1;
+    }
+
+    Mlt::Service service(parentProd.get_service());
+    Mlt::Tractor tractor(service);
+    int insertPos = pos.frames(m_fps);
+
+    Mlt::Producer trackProducer(tractor.track(track));
+    Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+    int clipIndex = trackPlaylist.get_clip_index_at(insertPos);
+    if (!trackPlaylist.is_blank_at(clipIndex)) return -1;
+    return trackPlaylist.clip_length(clipIndex);
+}
+
+
 void Render::mltInsertSpace(const GenTime pos, int track, const GenTime duration) {
     if (!m_mltProducer) {
         kDebug() << "PLAYLIST NOT INITIALISED //////";
@@ -1472,6 +1499,8 @@ void Render::mltInsertSpace(const GenTime pos, int track, const GenTime duration
             int position = trackPlaylist.clip_start(clipIndex);
             trackPlaylist.remove_region(position, -diff - 1);
         }
+        trackPlaylist.consolidate_blanks(0);
+
         // now move transitions
         mlt_service serv = m_mltProducer->parent().get_service();
         mlt_service nextservice = mlt_service_get_producer(serv);
@@ -1505,6 +1534,7 @@ void Render::mltInsertSpace(const GenTime pos, int track, const GenTime duration
                 int position = trackPlaylist.clip_start(clipIndex);
                 trackPlaylist.remove_region(position, -diff - 1);
             }
+            trackPlaylist.consolidate_blanks(0);
             trackNb--;
         }
         // now move transitions
@@ -2074,6 +2104,46 @@ bool Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTim
 }
 
 
+void Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod) {
+    kDebug() << "NEW PROD ID: " << prod->get("id");
+    m_mltConsumer->set("refresh", 0);
+    kDebug() << "// TRYING TO UPDATE CLIP at: " << pos << ", TK: " << track;
+    mlt_service_lock(m_mltConsumer->get_service());
+    Mlt::Service service(m_mltProducer->parent().get_service());
+    if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
+
+    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);
+    Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
+    if (clipProducer.is_blank()) {
+        kDebug() << "// ERROR UPDATING CLIP PROD";
+        mlt_service_unlock(m_mltConsumer->get_service());
+        m_isBlocked = false;
+        return;
+    }
+    Mlt::Producer *clip = prod->cut(clipProducer.get_in(), clipProducer.get_out());
+
+    // move all effects to the correct producer
+    Mlt::Service clipService(clipProducer.get_service());
+    Mlt::Service newClipService(clip->get_service());
+
+    int ct = 0;
+    Mlt::Filter *filter = clipService.filter(ct);
+    while (filter) {
+        if (filter->get("kdenlive_ix") != 0) {
+            clipService.detach(*filter);
+            newClipService.attach(*filter);
+        } else ct++;
+        filter = clipService.filter(ct);
+    }
+
+    trackPlaylist.insert_at(pos, clip, 1);
+    mlt_service_unlock(m_mltConsumer->get_service());
+    m_isBlocked = false;
+}
+
 bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd, Mlt::Producer *prod) {
     m_isBlocked = true;
 
@@ -2091,8 +2161,7 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
     if (endTrack == startTrack) {
         //mlt_service_lock(service.get_service());
         Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
-
-        if (!trackPlaylist.is_blank_at(moveEnd)) {
+        if (!trackPlaylist.is_blank_at(moveEnd) || clipProducer.is_blank()) {
             // error, destination is not empty
             //int ix = trackPlaylist.get_clip_index_at(moveEnd);
             kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd;
@@ -2103,7 +2172,7 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
             trackPlaylist.consolidate_blanks(0);
             int newIndex = trackPlaylist.insert_at(moveEnd, clipProducer, 1);
             /*if (QString(clipProducer.parent().get("transparency")).toInt() == 1) {
-                mltMoveTransparency(moveStart, moveEnd, startTrack, endTrack, QString(clipProducer.parent().get("id")).toInt());
+            mltMoveTransparency(moveStart, moveEnd, startTrack, endTrack, QString(clipProducer.parent().get("id")).toInt());
             }*/
             if (newIndex + 1 == trackPlaylist.count()) checkLength = true;
         }
@@ -2118,6 +2187,14 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
             return false;
         } else {
             Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
+            if (clipProducer.is_blank()) {
+                // error, destination is not empty
+                //int ix = trackPlaylist.get_clip_index_at(moveEnd);
+                kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd;
+                mlt_service_unlock(m_mltConsumer->get_service());
+                m_isBlocked = false;
+                return false;
+            }
             trackPlaylist.consolidate_blanks(0);
             destTrackPlaylist.consolidate_blanks(1);
             Mlt::Producer *clip;
@@ -2551,5 +2628,179 @@ QList <Mlt::Producer *> Render::producersList() {
     return prods;
 }
 
+void Render::mltInsertTrack(int ix) {
+    blockSignals(true);
+    m_isBlocked = true;
+
+    m_mltConsumer->set("refresh", 0);
+    mlt_service_lock(m_mltConsumer->get_service());
+    Mlt::Service service(m_mltProducer->parent().get_service());
+    if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
+
+    Mlt::Tractor tractor(service);
+    Mlt::Playlist *playlist = new Mlt::Playlist();
+    int ct = tractor.count();
+    kDebug() << "// TRACK INSERT: " << ix << ", MAX: " << ct;
+    int pos = ix;
+    if (pos < ct) {
+        Mlt::Producer *prodToMove = new Mlt::Producer(tractor.track(pos));
+        tractor.set_track(*playlist, pos);
+        pos++;
+        for (; pos <= ct; pos++) {
+            Mlt::Producer *prodToMove2 = new Mlt::Producer(tractor.track(pos));
+            tractor.set_track(*prodToMove, pos);
+            prodToMove = prodToMove2;
+        }
+    } else tractor.set_track(*playlist, ix);
+
+    // Move transitions
+    mlt_service serv = m_mltProducer->parent().get_service();
+    mlt_service nextservice = mlt_service_get_producer(serv);
+    mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
+    QString mlt_type = mlt_properties_get(properties, "mlt_type");
+    QString resource = mlt_properties_get(properties, "mlt_service");
+
+    while (mlt_type == "transition") {
+        if (resource != "mix") {
+            mlt_transition tr = (mlt_transition) nextservice;
+            int currentTrack = mlt_transition_get_b_track(tr);
+            int currentaTrack = mlt_transition_get_a_track(tr);
+            mlt_properties properties = MLT_TRANSITION_PROPERTIES(tr);
+
+            if (currentTrack >= ix) {
+                mlt_properties_set_int(properties, "b_track", currentTrack + 1);
+                mlt_properties_set_int(properties, "a_track", currentaTrack + 1);
+            }
+        }
+        nextservice = mlt_service_producer(nextservice);
+        if (nextservice == NULL) break;
+        properties = MLT_SERVICE_PROPERTIES(nextservice);
+        mlt_type = mlt_properties_get(properties, "mlt_type");
+        resource = mlt_properties_get(properties, "mlt_service");
+    }
+
+    // Add audio mix transition to last track
+    Mlt::Field *field = tractor.field();
+    Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, "mix");
+    //transition->set("mlt_service", "mix");
+    transition->set("a_track", 1);
+    transition->set("b_track", ct);
+    transition->set("always_active", 1);
+    transition->set("internal_added", 237);
+    transition->set("combine", 1);
+    field->plant_transition(*transition, 1, ct);
+
+    mlt_service_unlock(m_mltConsumer->get_service());
+    m_isBlocked = false;
+    blockSignals(false);
+}
+
+
+void Render::mltDeleteTrack(int ix) {
+    QDomDocument doc;
+    doc.setContent(sceneList(), false);
+    int tracksCount = doc.elementsByTagName("track").count() - 1;
+    QDomNode track = doc.elementsByTagName("track").at(ix);
+    QDomNode tractor = doc.elementsByTagName("tractor").at(0);
+    QDomNodeList transitions = doc.elementsByTagName("transition");
+    for (int i = 0; i < transitions.count(); i++) {
+        QDomElement e = transitions.at(i).toElement();
+        QDomNodeList props = e.elementsByTagName("property");
+        QMap <QString, QString> mappedProps;
+        for (int j = 0; j < props.count(); j++) {
+            QDomElement f = props.at(j).toElement();
+            mappedProps.insert(f.attribute("name"), f.firstChild().nodeValue());
+        }
+        if (mappedProps.value("mlt_service") == "mix" && mappedProps.value("b_track").toInt() == tracksCount) {
+            tractor.removeChild(transitions.at(i));
+        } else if (mappedProps.value("mlt_service") != "mix" && mappedProps.value("b_track").toInt() >= ix) {
+            // Transition needs to be moved
+            int a_track = mappedProps.value("a_track").toInt();
+            int b_track = mappedProps.value("b_track").toInt();
+            if (a_track > 0) a_track --;
+            if (b_track > 0) b_track --;
+            for (int j = 0; j < props.count(); j++) {
+                QDomElement f = props.at(j).toElement();
+                if (f.attribute("name") == "a_track") f.firstChild().setNodeValue(QString::number(a_track));
+                else if (f.attribute("name") == "b_track") f.firstChild().setNodeValue(QString::number(b_track));
+            }
+
+        }
+    }
+    tractor.removeChild(track);
+    setSceneList(doc.toString(), m_framePosition);
+    return;
+
+    blockSignals(true);
+    m_isBlocked = true;
+
+    m_mltConsumer->set("refresh", 0);
+    mlt_service_lock(m_mltConsumer->get_service());
+    Mlt::Service service(m_mltProducer->parent().get_service());
+    if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
+
+    /*Mlt::Tractor tractor(service);
+
+
+    Mlt::Multitrack *multi = tractor.multitrack();
+
+
+    int ct = tractor.count();
+    kDebug() << "// TRACK REMOVE: " << ix << ", MAX: " << ct;
+    int pos = ix;
+    for (; pos < ct ; pos++) {
+    Mlt::Service *lastTrack = new Mlt::Service(tractor.track(pos)->get_service());
+    //mlt_service_close(lastTrack->get_service());
+    delete lastTrack;
+    Mlt::Producer *prodToMove = new Mlt::Producer(tractor.track(pos + 1));
+    Mlt::Producer *prodToClose = new Mlt::Producer(tractor.track(pos));
+    mlt_service_close(prodToMove->get_service());
+    mlt_service_close(prodToClose->get_service());
+    tractor.set_track(*prodToMove, pos);
+    }*/
+
+    // Move transitions
+    /*mlt_service serv = m_mltProducer->parent().get_service();
+    mlt_service nextservice = mlt_service_get_producer(serv);
+    mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
+    QString mlt_type = mlt_properties_get(properties, "mlt_type");
+    QString resource = mlt_properties_get(properties, "mlt_service");
+
+    while (mlt_type == "transition") {
+        if (resource != "mix") {
+            mlt_transition tr = (mlt_transition) nextservice;
+            int currentTrack = mlt_transition_get_b_track(tr);
+            int currentaTrack = mlt_transition_get_a_track(tr);
+            mlt_properties properties = MLT_TRANSITION_PROPERTIES(tr);
+
+            if (currentTrack >= ix) {
+                mlt_properties_set_int(properties, "b_track", currentTrack + 1);
+                mlt_properties_set_int(properties, "a_track", currentaTrack + 1);
+            }
+        }
+        nextservice = mlt_service_producer(nextservice);
+        if (nextservice == NULL) break;
+        properties = MLT_SERVICE_PROPERTIES(nextservice);
+        mlt_type = mlt_properties_get(properties, "mlt_type");
+        resource = mlt_properties_get(properties, "mlt_service");
+    }
+
+    // Add audio mix transition to last track
+    Mlt::Field *field = tractor.field();
+    Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, "mix");
+    //transition->set("mlt_service", "mix");
+    transition->set("a_track", 1);
+    transition->set("b_track", ct);
+    transition->set("always_active", 1);
+    transition->set("internal_added", 237);
+    transition->set("combine", 1);
+    field->plant_transition(*transition, 1, ct);
+    */
+
+    mlt_service_unlock(m_mltConsumer->get_service());
+    m_isBlocked = false;
+    blockSignals(false);
+}
+
 #include "renderer.moc"