]> git.sesse.net Git - kdenlive/commitdiff
Experimental add / remove track, do not use in production yet
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 2 Dec 2008 16:48:01 +0000 (16:48 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 2 Dec 2008 16:48:01 +0000 (16:48 +0000)
svn path=/branches/KDE4/; revision=2745

src/addtrackcommand.cpp
src/customtrackview.cpp
src/customtrackview.h
src/renderer.cpp
src/renderer.h

index 184d06613f946605604274357452b4e1ec264ffa..b47cb119827ae09ef0634659b36049f1a9c1e200 100644 (file)
@@ -32,15 +32,15 @@ AddTrackCommand::AddTrackCommand(CustomTrackView *view, int ix, TrackInfo info,
 void AddTrackCommand::undo() {
 // kDebug()<<"----  undoing action";
     m_doIt = true;
-    if (m_addTrack) m_view->deleteTimelineTrack(m_ix);
-    else m_view->addTimelineTrack(m_ix, m_info);
+    if (m_addTrack) m_view->removeTrack(m_ix);
+    else m_view->addTrack(m_info, m_ix);
 }
 // virtual
 void AddTrackCommand::redo() {
     kDebug() << "----  redoing action";
     if (m_doIt) {
-        if (m_addTrack) m_view->addTimelineTrack(m_ix, m_info);
-        else m_view->deleteTimelineTrack(m_ix);
+        if (m_addTrack) m_view->addTrack(m_info, m_ix);
+        else m_view->removeTrack(m_ix);
     }
     m_doIt = true;
 }
index f41af69e05ff6f2240b26f695fa9e6828ba6a641..393b97198e1420408a0e126e9ec71f8d676c1834 100644 (file)
@@ -1312,17 +1312,113 @@ int CustomTrackView::duration() const {
 
 void CustomTrackView::addTrack(TrackInfo type, int ix) {
     if (ix == -1) m_scene->m_tracksList << type;
-    else m_scene->m_tracksList.insert(ix, type);
+    else {
+        m_scene->m_tracksList.insert(m_scene->m_tracksList.count() - ix, type);
+        // insert track in MLT playlist
+        m_document->renderer()->mltInsertTrack(m_scene->m_tracksList.count() - ix);
+
+        double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2;
+        QRectF r(0, startY, sceneRect().width(), sceneRect().height() - startY);
+        QList<QGraphicsItem *> selection = m_scene->items(r);
+        resetSelectionGroup();
+
+        m_selectionGroup = new AbstractGroupItem(m_document->fps());
+        scene()->addItem(m_selectionGroup);
+        for (int i = 0; i < selection.count(); i++) {
+            if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET)
+                m_selectionGroup->addToGroup(selection.at(i));
+        }
+        QPointF top = m_selectionGroup->boundingRect().topLeft();
+        const int width = m_selectionGroup->boundingRect().width();
+        const int height = m_selectionGroup->boundingRect().height();
+        m_selectionGroup->setPos(top);
+        m_selectionGroup->translate(-top.x(), -top.y() + 1);
+
+        // Move graphic items
+        m_selectionGroup->setPos(m_selectionGroup->pos().x(), m_selectionGroup->pos().y() + m_tracksHeight);
+
+        // adjust track number
+        QList<QGraphicsItem *> children = m_selectionGroup->childItems();
+        for (int i = 0; i < children.count(); i++) {
+            AbstractClipItem *item = static_cast <AbstractClipItem *>(children.at(i));
+            item->updateItem();
+            ItemInfo clipinfo = item->info();
+            if (item->type() == AVWIDGET) {
+                ClipItem *clip = static_cast <ClipItem *>(item);
+                // We add a move clip command so that we get the correct producer for new track number
+                /*if (clip->clipType() == AV || clip->clipType() == AUDIO)
+                    moveClip(clipinfo, clipinfo, true);*/
+            } else if (item->type() == TRANSITIONWIDGET) {
+                Transition *tr = static_cast <Transition *>(item);
+                int track = tr->transitionEndTrack();
+                if (track >= ix) {
+                    tr->updateTransitionEndTrack(getPreviousVideoTrack(clipinfo.track));
+                }
+            }
+        }
+        resetSelectionGroup();
+
+    }
     m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), m_tracksHeight * m_scene->m_tracksList.count());
     setSceneRect(0, 0, sceneRect().width(), m_tracksHeight * m_scene->m_tracksList.count());
     verticalScrollBar()->setMaximum(m_tracksHeight * m_scene->m_tracksList.count());
     //setFixedHeight(50 * m_tracksCount);
 }
 
-void CustomTrackView::removeTrack() {
-    // TODO: implement track deletion
-    //m_tracksCount--;
+void CustomTrackView::removeTrack(int ix) {
+    // Delete track in MLT playlist
+    m_document->renderer()->mltDeleteTrack(m_scene->m_tracksList.count() - ix);
+    m_scene->m_tracksList.removeAt(m_scene->m_tracksList.count() - ix);
+
+    double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2;
+    QRectF r(0, startY, sceneRect().width(), sceneRect().height() - startY);
+    QList<QGraphicsItem *> selection = m_scene->items(r);
+
+    resetSelectionGroup();
+
+    m_selectionGroup = new AbstractGroupItem(m_document->fps());
+    scene()->addItem(m_selectionGroup);
+    for (int i = 0; i < selection.count(); i++) {
+        if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET)
+            m_selectionGroup->addToGroup(selection.at(i));
+    }
+
+    QPointF top = m_selectionGroup->boundingRect().topLeft();
+    const int width = m_selectionGroup->boundingRect().width();
+    const int height = m_selectionGroup->boundingRect().height();
+    m_selectionGroup->setPos(top);
+    m_selectionGroup->translate(-top.x(), -top.y() + 1);
+
+    // Move graphic items
+    m_selectionGroup->setPos(m_selectionGroup->pos().x(), m_selectionGroup->pos().y() - m_tracksHeight);
+
+    // adjust track number
+    QList<QGraphicsItem *> children = m_selectionGroup->childItems();
+    kDebug() << "// FOUND CLIPS TO MOVE: " << children.count();
+    for (int i = 0; i < children.count(); i++) {
+        if (children.at(i)->type() == AVWIDGET) {
+            ClipItem *clip = static_cast <ClipItem *>(children.at(i));
+            clip->updateItem();
+            ItemInfo clipinfo = clip->info();
+            kDebug() << "// CLIP TRK IS: " << clipinfo.track;
+            // We add a move clip command so that we get the correct producer for new track number
+            /*if (clip->clipType() == AV || clip->clipType() == AUDIO)
+            moveClip(clipinfo, clipinfo, true);*/
+        } else if (children.at(i)->type() == TRANSITIONWIDGET) {
+            Transition *tr = static_cast <Transition *>(children.at(i));
+            tr->updateItem();
+            int track = tr->transitionEndTrack();
+            if (track >= ix) {
+                ItemInfo clipinfo = tr->info();
+                tr->updateTransitionEndTrack(getPreviousVideoTrack(clipinfo.track));
+            }
+        }
+    }
+    resetSelectionGroup();
+
     m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), m_tracksHeight * m_scene->m_tracksList.count());
+    setSceneRect(0, 0, sceneRect().width(), m_tracksHeight * m_scene->m_tracksList.count());
+    verticalScrollBar()->setMaximum(m_tracksHeight * m_scene->m_tracksList.count());
 }
 
 
@@ -2597,7 +2693,6 @@ void CustomTrackView::slotUpdateAllThumbs() {
 
 void CustomTrackView::slotInsertTrack(int ix) {
     kDebug() << "// INSERTING TRK: " << ix;
-
     QDialog d(parentWidget());
     Ui::AddTrack_UI view;
     view.setupUi(&d);
@@ -2619,55 +2714,70 @@ void CustomTrackView::slotInsertTrack(int ix) {
             info.isMute = false;
             info.isBlind = false;
         }
-        AddTrackCommand* command = new AddTrackCommand(this, ix, info, true, true);
-        m_commandStack->push(command);
+        addTimelineTrack(ix, info);
+        /*AddTrackCommand* command = new AddTrackCommand(this, ix, info, true, true);
+        m_commandStack->push(command);*/
     }
 }
 
 void CustomTrackView::slotDeleteTrack(int ix) {
+    bool ok;
+    ix = QInputDialog::getInteger(this, i18n("Remove Track"), i18n("Track"), ix, 0, m_scene->m_tracksList.count() - 1, 1, &ok);
+    if (ok) {
+        TrackInfo info = m_scene->m_tracksList.at(m_scene->m_tracksList.count() - ix);
+        deleteTimelineTrack(ix, info);
+        /*AddTrackCommand* command = new AddTrackCommand(this, ix, info, false, true);
+        m_commandStack->push(command);*/
+    }
 }
 
-void CustomTrackView::addTimelineTrack(int ix, TrackInfo info) {
+void CustomTrackView::addTimelineTrack(int ix, TrackInfo trackinfo) {
     double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2;
     QRectF r(0, startY, sceneRect().width(), sceneRect().height() - startY);
     QList<QGraphicsItem *> selection = m_scene->items(r);
     kDebug() << "// TRK RECT: " << r << ", ITEMS: " << selection.count();
-    addTrack(info, m_scene->m_tracksList.count() - ix);
     QUndoCommand *addTrack = new QUndoCommand();
     addTrack->setText("Add track");
+    new AddTrackCommand(this, ix, trackinfo, true, true, addTrack);
 
-    resetSelectionGroup();
-
-    m_selectionGroup = new AbstractGroupItem(m_document->fps());
-    scene()->addItem(m_selectionGroup);
-    for (int i = 0; i < selection.count(); i++) {
-        if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET)
-            m_selectionGroup->addToGroup(selection.at(i));
-    }
-    // insert track in MLT playlist
-    m_document->renderer()->mltInsertTrack(m_scene->m_tracksList.count() - ix);
-
-    // Move graphic items
-    m_selectionGroup->setPos(m_selectionGroup->pos().x(), m_selectionGroup->pos().y() + m_tracksHeight);
-
-    // adjust track number
-    QList<QGraphicsItem *> children = m_selectionGroup->childItems();
-    for (int i = 0; i < children.count(); i++) {
-        AbstractClipItem *item = static_cast <AbstractClipItem *>(children.at(i));
-        item->updateItem();
-        if (item->type() == AV || item->type() == AUDIO) {
-            // We add a move clip command so that we get the correct producer for new track number
-            ItemInfo clipinfo = item->info();
-            MoveClipCommand(this, clipinfo, clipinfo, true, true, addTrack);
-        }
-    }
-    resetSelectionGroup();
     m_commandStack->push(addTrack);
+    kDebug() << "// ADD TRCKL DONE...";
     update();
-    emit trackHeightChanged();
+    QTimer::singleShot(300, this, SIGNAL(trackHeightChanged()));
 }
 
-void CustomTrackView::deleteTimelineTrack(int ix) {
+void CustomTrackView::deleteTimelineTrack(int ix, TrackInfo trackinfo) {
+    double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2;
+    QRectF r(0, startY, sceneRect().width(), m_tracksHeight / 2 - 1);
+    QList<QGraphicsItem *> selection = m_scene->items(r);
+    QUndoCommand *deleteTrack = new QUndoCommand();
+    deleteTrack->setText("Delete track");
+
+    // Delete all clips in selected track
+    for (int i = 0; i < selection.count(); i++) {
+        if (selection.at(i)->type() == AVWIDGET) {
+            ClipItem *item =  static_cast <ClipItem *>(selection.at(i));
+            new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), item->info(), item->effectList(), false, false, deleteTrack);
+            m_scene->removeItem(item);
+            delete item;
+            item = NULL;
+        } else if (selection.at(i)->type() == TRANSITIONWIDGET) {
+            Transition *item =  static_cast <Transition *>(selection.at(i));
+            new AddTransitionCommand(this, item->info(), item->transitionEndTrack(), item->toXML(), true, false, deleteTrack);
+            m_scene->removeItem(item);
+            delete item;
+            item = NULL;
+        }
+    }
+
+    new AddTrackCommand(this, ix, trackinfo, false, true, deleteTrack);
+
+    m_commandStack->push(deleteTrack);
+    //removeTrack(ix, trackinfo);
+    kDebug() << "// REM TRK DONE...";
+    update();
+    QTimer::singleShot(300, this, SIGNAL(trackHeightChanged()));
+
 }
 
 #include "customtrackview.moc"
index 742c7e871f4cffb9192fc0c4ee56356b1d54878f..a07d4b8b8297ae583e6b7c8cf8587681a723a910 100644 (file)
@@ -49,7 +49,7 @@ public:
     virtual void mouseMoveEvent(QMouseEvent * event);
     virtual void mouseDoubleClickEvent(QMouseEvent *event);
     void addTrack(TrackInfo type, int ix = -1);
-    void removeTrack();
+    void removeTrack(int ix);
     int cursorPos();
     void checkAutoScroll();
     void moveClip(const ItemInfo start, const ItemInfo end, bool forceProducer);
@@ -100,8 +100,8 @@ public:
     void slotRemoveSpace();
     void insertSpace(const GenTime &pos, int track, const GenTime duration, bool add);
     ClipItem *getActiveClipUnderCursor(bool allowOutsideCursor = false) const;
-    void addTimelineTrack(int ix, TrackInfo info);
-    void deleteTimelineTrack(int ix);
+    void addTimelineTrack(int ix, TrackInfo trackinfo);
+    void deleteTimelineTrack(int ix, TrackInfo trackinfo);
 
 public slots:
     void setCursorPos(int pos, bool seek = true);
index c85c8ab7f8f80e37d4b15dfc2ea2c547bee6f9cd..bcd0d59539616c8360af84c5c200780f2b52b89c 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 */
@@ -2116,13 +2120,17 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
     bool checkLength = false;
     if (endTrack == startTrack) {
         //mlt_service_lock(service.get_service());
+        Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
         if (forceProducer) {
-            Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
+            if (clipProducer.is_blank()) {
+                kDebug() << "// ERROR RESTTING CLIP PROD: " << moveEnd << ", TRK: " << startTrack;
+                mlt_service_unlock(m_mltConsumer->get_service());
+                m_isBlocked = false;
+                return false;
+            }
             trackPlaylist.insert(clipProducer, moveEnd, clipProducer.get_in(), clipProducer.get_out());
         } else {
-            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;
@@ -2149,6 +2157,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;
@@ -2647,7 +2663,87 @@ void Render::mltInsertTrack(int ix) {
     mlt_service_unlock(m_mltConsumer->get_service());
     m_isBlocked = false;
     blockSignals(false);
-    //Mlt::Producer trackProducer(tractor.track(startTrack));
+}
+
+
+void Render::mltDeleteTrack(int ix) {
+    QDomDocument doc;
+    doc.setContent(sceneList(), false);
+    QDomNode track = doc.elementsByTagName("track").at(ix);
+    QDomNode tractor = doc.elementsByTagName("tractor").at(0);
+    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"
index 5737f2030b7c603047f04803ee08bcc08002ce0a..cb5dcd2d4fd0a28b10ad2c3fd7cf04e8f84a82f7 100644 (file)
@@ -172,6 +172,7 @@ Q_OBJECT public:
     void mltDeleteTransparency(int pos, int track, int id);
     void mltResizeTransparency(int oldStart, int newStart, int newEnd, int track, int id);
     void mltInsertTrack(int ix);
+    void mltDeleteTrack(int ix);
 
     /** Change speed of a clip in playlist. To do this, we create a new "framebuffer" producer.
     This new producer must have its "resource" param set to: video.mpg?0.6 where video.mpg is the path