]> git.sesse.net Git - kdenlive/blobdiff - src/customtrackview.cpp
Merge branch 'audioAlign'
[kdenlive] / src / customtrackview.cpp
index f45eabe2bded907b333b60b9b157df4d6561801f..76e4bb1cecb3f927b12eab7e8fce2ebc91b5ab5b 100644 (file)
@@ -48,6 +48,7 @@
 #include "commands/insertspacecommand.h"
 #include "spacerdialog.h"
 #include "commands/addtrackcommand.h"
+#include "commands/changeeffectstatecommand.h"
 #include "commands/movegroupcommand.h"
 #include "ui_addtrack_ui.h"
 #include "initeffects.h"
@@ -86,6 +87,8 @@
 #include <QGraphicsDropShadowEffect>
 #endif
 
+//#define DEBUG
+
 bool sortGuidesList(const Guide *g1 , const Guide *g2)
 {
     return (*g1).position() < (*g2).position();
@@ -1293,10 +1296,10 @@ void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event)
             //item->updateKeyframeEffect();
             //QString next = item->keyframes(item->selectedEffectIndex());
             QDomElement newEffect = item->selectedEffect().cloneNode().toElement();
-            EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), oldEffect, newEffect, item->selectedEffectIndex(), false);
+            EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), oldEffect, newEffect, item->selectedEffectIndex(), false, false);
             //EditKeyFrameCommand *command = new EditKeyFrameCommand(this, m_dragItem->track(), m_dragItem->startPos(), item->selectedEffectIndex(), previous, next, false);
             m_commandStack->push(command);
-            updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect(), item->selectedEffectIndex());
+            updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect());
             emit clipItemSelected(item, item->selectedEffectIndex());
         }
     } else if (m_dragItem && !m_dragItem->isItemLocked()) {
@@ -1603,7 +1606,13 @@ bool CustomTrackView::insertDropClips(const QMimeData *data, const QPoint &pos)
 void CustomTrackView::dragEnterEvent(QDragEnterEvent * event)
 {
     if (insertDropClips(event->mimeData(), event->pos())) {
-        event->acceptProposedAction();
+      if (event->source() == this) {
+             event->setDropAction(Qt::MoveAction);
+             event->accept();
+         } else {
+            event->setDropAction(Qt::MoveAction);
+             event->acceptProposedAction();
+        }
     } else QGraphicsView::dragEnterEvent(event);
 }
 
@@ -1678,6 +1687,7 @@ void CustomTrackView::addEffect(int track, GenTime pos, QDomElement effect)
         EffectsParameterList params = clip->addEffect(effect);
         if (!m_document->renderer()->mltAddEffect(track, pos, params))
             emit displayMessage(i18n("Problem adding effect to clip"), ErrorMessage);
+       clip->setSelectedEffect(params.paramValue("kdenlive_ix").toInt());
         if (clip->isSelected()) emit clipItemSelected(clip);
     } else emit displayMessage(i18n("Cannot find clip to add effect"), ErrorMessage);
 }
@@ -1727,45 +1737,54 @@ void CustomTrackView::slotAddGroupEffect(QDomElement effect, AbstractGroupItem *
     if (!namenode.isNull()) effectName = i18n(namenode.text().toUtf8().data());
     else effectName = i18n("effect");
     effectCommand->setText(i18n("Add %1", effectName));
-    int count = 0;
     for (int i = 0; i < itemList.count(); i++) {
         if (itemList.at(i)->type() == AVWIDGET) {
             ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
-            if (effect.attribute("type") == "audio") {
-                // Don't add audio effects on video clips
-                if (item->isVideoOnly() || (item->clipType() != AUDIO && item->clipType() != AV && item->clipType() != PLAYLIST)) continue;
-            } else if (effect.hasAttribute("type") == false) {
-                // Don't add video effect on audio clips
-                if (item->isAudioOnly() || item->clipType() == AUDIO) continue;
-            }
-
-            if (effect.attribute("unique", "0") != "0" && item->hasEffect(effect.attribute("tag"), effect.attribute("id")) != -1) {
-                emit displayMessage(i18n("Effect already present in clip"), ErrorMessage);
-                continue;
-            }
-            if (item->isItemLocked()) {
-                continue;
-            }
-            item->initEffect(effect);
-
-            new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), effect, true, effectCommand);
-            count++;
+            if (effect.tagName() == "effectgroup") {
+               QDomNodeList effectlist = effect.elementsByTagName("effect");
+               for (int j = 0; j < effectlist.count(); j++) {
+                   QDomElement subeffect = effectlist.at(j).toElement();
+                   if (subeffect.hasAttribute("kdenlive_info")) {
+                       // effect is in a group
+                       EffectInfo effectInfo;
+                       effectInfo.fromString(subeffect.attribute("kdenlive_info"));
+                       if (effectInfo.groupIndex < 0) {
+                           // group needs to be appended
+                           effectInfo.groupIndex = item->nextFreeEffectGroupIndex();
+                           subeffect.setAttribute("kdenlive_info", effectInfo.toString());
+                       }
+                   }
+                   processEffect(item, subeffect, effectCommand);
+               }
+           }
+            else {
+               processEffect(item, effect, effectCommand);
+           }
         }
     }
-    if (count > 0) {
+    if (effectCommand->childCount() > 0) {
         m_commandStack->push(effectCommand);
         setDocumentModified();
     } else delete effectCommand;
 }
 
+void CustomTrackView::slotAddEffect(ClipItem *clip, QDomElement effect)
+{
+    if (clip) slotAddEffect(effect, clip->startPos(), clip->track());
+}
+
 void CustomTrackView::slotAddEffect(QDomElement effect, GenTime pos, int track)
 {
     QList<QGraphicsItem *> itemList;
     QUndoCommand *effectCommand = new QUndoCommand();
     QString effectName;
-    QDomElement namenode = effect.firstChildElement("name");
-    if (!namenode.isNull()) effectName = i18n(namenode.text().toUtf8().data());
-    else effectName = i18n("effect");
+    if (effect.tagName() == "effectgroup") {
+       effectName = effect.attribute("name");
+    } else {
+       QDomElement namenode = effect.firstChildElement("name");
+       if (!namenode.isNull()) effectName = i18n(namenode.text().toUtf8().data());
+       else effectName = i18n("effect");
+    }
     effectCommand->setText(i18n("Add %1", effectName));
 
     if (track == -1) itemList = scene()->selectedItems();
@@ -1788,39 +1807,24 @@ void CustomTrackView::slotAddEffect(QDomElement effect, GenTime pos, int track)
     for (int i = 0; i < itemList.count(); i++) {
         if (itemList.at(i)->type() == AVWIDGET) {
             ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
-            if (effect.attribute("type") == "audio") {
-                // Don't add audio effects on video clips
-                if (item->isVideoOnly() || (item->clipType() != AUDIO && item->clipType() != AV && item->clipType() != PLAYLIST)) {
-                    /* do not show error message when item is part of a group as the user probably knows what he does then
-                     * and the message is annoying when working with the split audio feature */
-                    if (!item->parentItem() || item->parentItem() == m_selectionGroup)
-                        emit displayMessage(i18n("Cannot add an audio effect to this clip"), ErrorMessage);
-                    continue;
-                }
-            } else if (effect.attribute("type") == "video" || !effect.hasAttribute("type")) {
-                // Don't add video effect on audio clips
-                if (item->isAudioOnly() || item->clipType() == AUDIO) {
-                    /* do not show error message when item is part of a group as the user probably knows what he does then
-                     * and the message is annoying when working with the split audio feature */
-                    if (!item->parentItem() || item->parentItem() == m_selectionGroup)
-                        emit displayMessage(i18n("Cannot add a video effect to this clip"), ErrorMessage);
-                    continue;
-                }
-            }
-            if (item->hasEffect(effect.attribute("tag"), effect.attribute("id")) != -1 && effect.attribute("unique", "0") != "0") {
-                emit displayMessage(i18n("Effect already present in clip"), ErrorMessage);
-                continue;
-            }
-            if (item->isItemLocked()) {
-                continue;
-            }
-
-            if (effect.attribute("id") == "freeze" && m_cursorPos > item->startPos().frames(m_document->fps()) && m_cursorPos < item->endPos().frames(m_document->fps())) {
-                item->initEffect(effect, m_cursorPos - item->startPos().frames(m_document->fps()));
-            } else {
-                item->initEffect(effect);
-            }
-            new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), effect, true, effectCommand);
+           if (effect.tagName() == "effectgroup") {
+               QDomNodeList effectlist = effect.elementsByTagName("effect");
+               for (int j = 0; j < effectlist.count(); j++) {
+                   QDomElement subeffect = effectlist.at(j).toElement();
+                   if (subeffect.hasAttribute("kdenlive_info")) {
+                       // effect is in a group
+                       EffectInfo effectInfo;
+                       effectInfo.fromString(subeffect.attribute("kdenlive_info"));
+                       if (effectInfo.groupIndex < 0) {
+                           // group needs to be appended
+                           effectInfo.groupIndex = item->nextFreeEffectGroupIndex();
+                           subeffect.setAttribute("kdenlive_info", effectInfo.toString());
+                       }
+                   }
+                   processEffect(item, subeffect, effectCommand);
+               }
+           }
+            else processEffect(item, effect, effectCommand);
         }
     }
     if (effectCommand->childCount() > 0) {
@@ -1831,12 +1835,12 @@ void CustomTrackView::slotAddEffect(QDomElement effect, GenTime pos, int track)
            for (int i = 0; i < itemList.count(); i++) {
                if (itemList.at(i)->type() == AVWIDGET) {
                    ClipItem *clip = static_cast<ClipItem *>(itemList.at(i));
+                   clip->setSelectedEffect(clip->effectsCount());
                    if (!clip->isSelected()) {
-                       clearSelection();
+                       clearSelection(false);
                        clip->setSelected(true);
+                       emit clipItemSelected(clip);
                    }
-                   clip->setSelectedEffect(clip->effectsCount() - 1);
-                   emit clipItemSelected(clip, clip->effectsCount() - 1);
                    break;
                }
            }
@@ -1844,6 +1848,43 @@ void CustomTrackView::slotAddEffect(QDomElement effect, GenTime pos, int track)
     } else delete effectCommand;
 }
 
+void CustomTrackView::processEffect(ClipItem *item, QDomElement effect, QUndoCommand *effectCommand)
+{
+    if (effect.attribute("type") == "audio") {
+       // Don't add audio effects on video clips
+        if (item->isVideoOnly() || (item->clipType() != AUDIO && item->clipType() != AV && item->clipType() != PLAYLIST)) {
+           /* do not show error message when item is part of a group as the user probably knows what he does then
+            * and the message is annoying when working with the split audio feature */
+            if (!item->parentItem() || item->parentItem() == m_selectionGroup)
+               emit displayMessage(i18n("Cannot add an audio effect to this clip"), ErrorMessage);
+            return;
+        }
+    } else if (effect.attribute("type") == "video" || !effect.hasAttribute("type")) {
+       // Don't add video effect on audio clips
+        if (item->isAudioOnly() || item->clipType() == AUDIO) {
+           /* do not show error message when item is part of a group as the user probably knows what he does then
+            * and the message is annoying when working with the split audio feature */
+            if (!item->parentItem() || item->parentItem() == m_selectionGroup)
+               emit displayMessage(i18n("Cannot add a video effect to this clip"), ErrorMessage);
+            return;
+        }
+    }
+    if (effect.attribute("unique", "0") != "0" && item->hasEffect(effect.attribute("tag"), effect.attribute("id")) != -1) {
+       emit displayMessage(i18n("Effect already present in clip"), ErrorMessage);
+        return;
+    }
+    if (item->isItemLocked()) {
+       return;
+    }
+
+    if (effect.attribute("id") == "freeze" && m_cursorPos > item->startPos().frames(m_document->fps()) && m_cursorPos < item->endPos().frames(m_document->fps())) {
+       item->initEffect(effect, m_cursorPos - item->startPos().frames(m_document->fps()));
+    } else {
+       item->initEffect(effect);
+    }
+    new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), effect, true, effectCommand);
+}
+
 void CustomTrackView::slotDeleteEffect(ClipItem *clip, int track, QDomElement effect, bool affectGroup)
 {
     if (clip == NULL) {
@@ -1895,12 +1936,14 @@ void CustomTrackView::slotDeleteEffect(ClipItem *clip, int track, QDomElement ef
     setDocumentModified();
 }
 
-void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedEffect, int ix, bool triggeredByUser)
+void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedEffect, bool updateEffectStack)
 {
     if (insertedEffect.isNull()) {
+       kDebug()<<"// Trying to add null effect";
         emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
         return;
     }
+    int ix = insertedEffect.attribute("kdenlive_ix").toInt();
     QDomElement effect = insertedEffect.cloneNode().toElement();
     //kDebug() << "// update effect ix: " << effect.attribute("kdenlive_ix")<<", GAIN: "<<EffectsList::parameter(effect, "gain");
     if (pos < GenTime()) {
@@ -1911,8 +1954,9 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedE
             clip->initEffect(effect);
             effectParams = getEffectArgs(effect);
         }*/
-        if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - track, pos, effectParams))
+        if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - track, pos, effectParams)) {
             emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
+       }
         m_document->setTrackEffect(m_document->tracksCount() - track - 1, ix, effect);
         emit updateTrackEffectState(track);
         setDocumentModified();
@@ -1932,12 +1976,13 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedE
                 if (strobe == 0) strobe = 1;
                 doChangeClipSpeed(clip->info(), clip->speedIndependantInfo(), speed, clip->speed(), strobe, clip->baseClip()->getId());
             }
-            clip->setEffectAt(ix, effect);
-            if (ix == clip->selectedEffectIndex()) {
-                clip->setSelectedEffect(ix);
-                if (!triggeredByUser)
-                    emit clipItemSelected(clip, ix);
-            }
+            clip->updateEffect(effect);
+           if (updateEffectStack && clip->isSelected())
+               emit clipItemSelected(clip);
+           if (ix == clip->selectedEffectIndex()) {
+               // make sure to update display of clip keyframes
+               clip->setSelectedEffect(ix);
+           }
             return;
         }
 
@@ -1959,74 +2004,146 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedE
                 clip->setFadeOut(pos);
             }
         }
+       bool success = m_document->renderer()->mltEditEffect(m_document->tracksCount() - clip->track(), clip->startPos(), effectParams);
 
-        if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - clip->track(), clip->startPos(), effectParams))
-            emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
-
-        clip->setEffectAt(ix, effect);
-        if (ix == clip->selectedEffectIndex()) {
-            clip->setSelectedEffect(ix);
-            if (!triggeredByUser)
-                emit clipItemSelected(clip, ix);
-        }
+        if (success) {
+           clip->updateEffect(effect);
+           if (updateEffectStack && clip->isSelected()) {
+               emit clipItemSelected(clip);
+           }
+           if (ix == clip->selectedEffectIndex()) {
+               // make sure to update display of clip keyframes
+               clip->setSelectedEffect(ix);
+           }
+       }
+       else emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
     }
     else emit displayMessage(i18n("Cannot find clip to update effect"), ErrorMessage);
     setDocumentModified();
 }
 
-void CustomTrackView::moveEffect(int track, GenTime pos, int oldPos, int newPos)
+void CustomTrackView::updateEffectState(int track, GenTime pos, QList <int> effectIndexes, bool disable, bool updateEffectStack)
+{
+    if (pos < GenTime()) {
+        // editing a track effect
+        if (!m_document->renderer()->mltEnableEffects(m_document->tracksCount() - track, pos, effectIndexes, disable)) {
+            emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
+           return;
+       }
+        m_document->enableTrackEffects(m_document->tracksCount() - track - 1, effectIndexes, disable);
+        emit updateTrackEffectState(track);
+        setDocumentModified();
+        return;
+    }
+    // editing a clip effect
+    ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), m_document->tracksCount() - track);
+    if (clip) {
+       bool success = m_document->renderer()->mltEnableEffects(m_document->tracksCount() - clip->track(), clip->startPos(), effectIndexes, disable);
+       if (success) {
+           clip->enableEffects(effectIndexes, disable);
+           if (updateEffectStack && clip->isSelected()) {
+               emit clipItemSelected(clip);
+           }
+           if (effectIndexes.contains(clip->selectedEffectIndex())) {
+               // make sure to update display of clip keyframes
+               clip->setSelectedEffect(clip->selectedEffectIndex());
+           }
+       }
+       else emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
+    }
+    else emit displayMessage(i18n("Cannot find clip to update effect"), ErrorMessage);
+}
+
+void CustomTrackView::moveEffect(int track, GenTime pos, QList <int> oldPos, QList <int> newPos)
 {
     if (pos < GenTime()) {
         // Moving track effect
-        QDomElement act = m_document->getTrackEffect(m_document->tracksCount() - track - 1, newPos - 1);
-        QDomElement before = m_document->getTrackEffect(m_document->tracksCount() - track - 1, oldPos - 1);
-
-        if (!act.isNull() && !before.isNull()) {
-            m_document->setTrackEffect(m_document->tracksCount() - track - 1, oldPos - 1, act);
-            m_document->setTrackEffect(m_document->tracksCount() - track - 1, newPos - 1, before);
-            m_document->renderer()->mltMoveEffect(m_document->tracksCount() - track, pos, oldPos, newPos);
-            emit showTrackEffects(m_document->tracksCount() - track, m_document->trackInfoAt(m_document->tracksCount() - track - 1));
-        } else emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
+        int documentTrack = m_document->tracksCount() - track - 1;
+        int max = m_document->getTrackEffects(documentTrack).count();
+       int new_position = newPos.at(0);
+       if (new_position > max) {
+           new_position = max;
+       }
+       int old_position = oldPos.at(0);
+       for (int i = 0; i < newPos.count(); i++) {
+           QDomElement act = m_document->getTrackEffect(documentTrack, new_position);
+           if (old_position > new_position) {
+               // Moving up, we need to adjust index
+               old_position = oldPos.at(i);
+               new_position = newPos.at(i);
+           }
+           QDomElement before = m_document->getTrackEffect(documentTrack, old_position);
+           if (!act.isNull() && !before.isNull()) {
+               m_document->setTrackEffect(documentTrack, new_position, before);
+               m_document->renderer()->mltMoveEffect(m_document->tracksCount() - track, pos, old_position, new_position);
+           } else emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
+       }
+       emit showTrackEffects(m_document->tracksCount() - track, m_document->trackInfoAt(documentTrack));
         return;
     }
     ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), m_document->tracksCount() - track);
-    if (clip && !clip->effectAt(newPos - 1).isNull() && !clip->effectAt(oldPos - 1).isNull()) {
-        QDomElement act = clip->effectAt(newPos - 1);
-        QDomElement before = clip->effectAt(oldPos - 1);
-        clip->setEffectAt(oldPos - 1, act);
-        clip->setEffectAt(newPos - 1, before);
-        // special case: speed effect, which is a pseudo-effect, not appearing in MLT's effects
-        if (act.attribute("id") == "speed") {
-            m_document->renderer()->mltUpdateEffectPosition(track, pos, oldPos, newPos);
-        } else if (before.attribute("id") == "speed") {
-            m_document->renderer()->mltUpdateEffectPosition(track, pos, newPos, oldPos);
-        } else m_document->renderer()->mltMoveEffect(track, pos, oldPos, newPos);
-        emit clipItemSelected(clip, newPos - 1);
+    if (clip) {
+       int new_position = newPos.at(0);
+       if (new_position > clip->effectsCount()) {
+           new_position = clip->effectsCount();
+       }
+       int old_position = oldPos.at(0);
+       for (int i = 0; i < newPos.count(); i++) {
+           QDomElement act = clip->effectAt(new_position);
+           if (old_position > new_position) {
+               // Moving up, we need to adjust index
+               old_position = oldPos.at(i);
+               new_position = newPos.at(i);
+           }
+           QDomElement before = clip->effectAt(old_position);
+           if (act.isNull() || before.isNull()) {
+               emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
+               return;
+           }
+           clip->moveEffect(before, new_position);
+           // special case: speed effect, which is a pseudo-effect, not appearing in MLT's effects
+           if (act.attribute("id") == "speed") {
+               m_document->renderer()->mltUpdateEffectPosition(track, pos, old_position, new_position);
+           } else if (before.attribute("id") == "speed") {
+               m_document->renderer()->mltUpdateEffectPosition(track, pos, new_position, old_position);
+           } else m_document->renderer()->mltMoveEffect(track, pos, old_position, new_position);
+       }
+       clip->setSelectedEffect(newPos.at(0));
+       emit clipItemSelected(clip);
         setDocumentModified();
     } else emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
 }
 
-void CustomTrackView::slotChangeEffectState(ClipItem *clip, int track, int effectPos, bool disable)
+void CustomTrackView::slotChangeEffectState(ClipItem *clip, int track, QList <int> effectIndexes, bool disable)
 {
-    EditEffectCommand *command;
-    QDomElement effect;
-    if (clip == NULL) effect = m_document->getTrackEffect(track - 1, effectPos);
-    else effect = clip->effectAt(effectPos);
-    QDomElement oldEffect = effect.cloneNode().toElement();
-    effect.setAttribute("disable", (int) disable);
-
-
+    ChangeEffectStateCommand *command;
     if (clip == NULL) {
         // editing track effect
-        command = new EditEffectCommand(this, m_document->tracksCount() - track, GenTime(-1), oldEffect, effect, effectPos, true);
+        command = new ChangeEffectStateCommand(this, m_document->tracksCount() - track, GenTime(-1), effectIndexes, disable, false, true);
     } else {
-        command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldEffect, effect, effectPos, true);
+       // Check if we have a speed effect, disabling / enabling it needs a special procedure since it is a pseudoo effect
+       QList <int> speedEffectIndexes;
+       for (int i = 0; i < effectIndexes.count(); i++) {
+           QDomElement effect = clip->effectAt(effectIndexes.at(i));
+           if (effect.attribute("id") == "speed") {
+               // speed effect
+               speedEffectIndexes << effectIndexes.at(i);
+               QDomElement newEffect = effect.cloneNode().toElement();
+               newEffect.setAttribute("disable", (int) disable);
+               EditEffectCommand *editcommand = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effect, newEffect, effectIndexes.at(i), false, true);
+               m_commandStack->push(editcommand);
+           }
+       }
+       for (int j = 0; j < speedEffectIndexes.count(); j++) {
+           effectIndexes.removeAll(speedEffectIndexes.at(j));
+       }
+        command = new ChangeEffectStateCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effectIndexes, disable, false, true);
     }
     m_commandStack->push(command);
-    setDocumentModified();;
+    setDocumentModified();
 }
 
-void CustomTrackView::slotChangeEffectPosition(ClipItem *clip, int track, int currentPos, int newPos)
+void CustomTrackView::slotChangeEffectPosition(ClipItem *clip, int track, QList <int> currentPos, int newPos)
 {
     MoveEffectCommand *command;
     if (clip == NULL) {
@@ -2037,11 +2154,11 @@ void CustomTrackView::slotChangeEffectPosition(ClipItem *clip, int track, int cu
     setDocumentModified();
 }
 
-void CustomTrackView::slotUpdateClipEffect(ClipItem *clip, int track, QDomElement oldeffect, QDomElement effect, int ix)
+void CustomTrackView::slotUpdateClipEffect(ClipItem *clip, int track, QDomElement oldeffect, QDomElement effect, int ix, bool refreshEffectStack)
 {
     EditEffectCommand *command;
-    if (clip) command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldeffect, effect, ix, true);
-    else command = new EditEffectCommand(this, m_document->tracksCount() - track, GenTime(-1), oldeffect, effect, ix, true);
+    if (clip) command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldeffect, effect, ix, refreshEffectStack, true);
+    else command = new EditEffectCommand(this, m_document->tracksCount() - track, GenTime(-1), oldeffect, effect, ix, refreshEffectStack, true);
     m_commandStack->push(command);
 }
 
@@ -2050,7 +2167,7 @@ void CustomTrackView::slotUpdateClipRegion(ClipItem *clip, int ix, QString regio
     QDomElement effect = clip->getEffectAt(ix);
     QDomElement oldeffect = effect.cloneNode().toElement();
     effect.setAttribute("region", region);
-    EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldeffect, effect, ix, true);
+    EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldeffect, effect, ix, true, true);
     m_commandStack->push(command);
 }
 
@@ -2477,7 +2594,7 @@ void CustomTrackView::dropEvent(QDropEvent * event)
             groupSelectedItems(true);
         } else if (items.count() == 1) {
             m_dragItem = static_cast <AbstractClipItem *>(items.at(0));
-            emit clipItemSelected((ClipItem*)m_dragItem, -1, false);
+            emit clipItemSelected((ClipItem*)m_dragItem, false);
         }
         event->setDropAction(Qt::MoveAction);
         event->accept();
@@ -2648,13 +2765,14 @@ int CustomTrackView::duration() const
 
 void CustomTrackView::addTrack(TrackInfo type, int ix)
 {
+    QList <TransitionInfo> transitionInfos;
     if (ix == -1 || ix == m_document->tracksCount()) {
         m_document->insertTrack(0, type);
-        m_document->renderer()->mltInsertTrack(1, type.type == VIDEOTRACK);
+        transitionInfos = m_document->renderer()->mltInsertTrack(1, type.type == VIDEOTRACK);
     } else {
         m_document->insertTrack(m_document->tracksCount() - ix, type);
         // insert track in MLT playlist
-        m_document->renderer()->mltInsertTrack(m_document->tracksCount() - ix, type.type == VIDEOTRACK);
+        transitionInfos = m_document->renderer()->mltInsertTrack(m_document->tracksCount() - ix, type.type == VIDEOTRACK);
 
         double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2;
         QRectF r(0, startY, sceneRect().width(), sceneRect().height() - startY);
@@ -2696,14 +2814,24 @@ void CustomTrackView::addTrack(TrackInfo type, int ix)
                         emit displayMessage(i18n("Cannot update clip (time: %1, track: %2)", clipinfo.startPos.frames(m_document->fps()), clipinfo.track), ErrorMessage);
                     }
                 }
-            } else if (item->type() == TRANSITIONWIDGET) {
+            } /*else if (item->type() == TRANSITIONWIDGET) {
                 Transition *tr = static_cast <Transition *>(item);
                 int track = tr->transitionEndTrack();
                 if (track >= ix) {
                     tr->updateTransitionEndTrack(getPreviousVideoTrack(clipinfo.track));
                 }
-            }
-        }
+            }*/
+        }
+        // Sync transition tracks with MLT playlist
+        Transition *tr;        
+       TransitionInfo info;
+       for (int i = 0; i < transitionInfos.count(); i++) {
+           info = transitionInfos.at(i);
+           tr = getTransitionItem(info);
+           if (tr) tr->setForcedTrack(info.forceTrack, info.a_track);
+           else kDebug()<<"// Cannot update TRANSITION AT: "<<info.b_track<<" / "<<info.startPos.frames(m_document->fps()); 
+       }
+       
         resetSelectionGroup(false);
         m_document->renderer()->unlockService(tractor);
     }
@@ -3657,7 +3785,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event)
                 EffectsList::setParameter(oldeffect, "in", QString::number(start));
                 EffectsList::setParameter(oldeffect, "out", QString::number(end));
                 slotUpdateClipEffect(item, -1, effect, oldeffect, ix);
-                emit clipItemSelected(item, ix);
+                emit clipItemSelected(item);
             }
         } else if (item->fadeIn() != 0 && ix2 == -1) {
             QDomElement effect;
@@ -3680,7 +3808,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event)
                 EffectsList::setParameter(oldeffect, "in", QString::number(start));
                 EffectsList::setParameter(oldeffect, "out", QString::number(end));
                 slotUpdateClipEffect(item, -1, effect, oldeffect, ix2);
-                emit clipItemSelected(item, ix2);
+                emit clipItemSelected(item);
             }
         }
     } else if (m_operationMode == FADEOUT) {
@@ -3701,7 +3829,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event)
                 EffectsList::setParameter(oldeffect, "out", QString::number(end));
                 // kDebug()<<"EDIT FADE OUT : "<<start<<"x"<<end;
                 slotUpdateClipEffect(item, -1, effect, oldeffect, ix);
-                emit clipItemSelected(item, ix);
+                emit clipItemSelected(item);
             }
         } else if (item->fadeOut() != 0 && ix2 == -1) {
             QDomElement effect;
@@ -3726,7 +3854,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event)
                 EffectsList::setParameter(oldeffect, "out", QString::number(end));
                 // kDebug()<<"EDIT FADE OUT : "<<start<<"x"<<end;
                 slotUpdateClipEffect(item, -1, effect, oldeffect, ix2);
-                emit clipItemSelected(item, ix2);
+                emit clipItemSelected(item);
             }
         }
     } else if (m_operationMode == KEYFRAME) {
@@ -3753,11 +3881,11 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event)
         //item->updateKeyframeEffect();
         //QString next = item->keyframes(item->selectedEffectIndex());
         //EditKeyFrameCommand *command = new EditKeyFrameCommand(this, item->track(), item->startPos(), item->selectedEffectIndex(), previous, next, false);
-        EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), oldEffect, newEffect, item->selectedEffectIndex(), false);
+        EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), oldEffect, newEffect, item->selectedEffectIndex(), false, false);
 
         m_commandStack->push(command);
-        updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect(), item->selectedEffectIndex());
-        emit clipItemSelected(item, item->selectedEffectIndex());
+        updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect());
+        emit clipItemSelected(item);
     }
     if (m_dragItem && m_dragItem->type() == TRANSITIONWIDGET && m_dragItem->isSelected()) {
         // A transition is selected
@@ -4239,6 +4367,14 @@ ClipItem *CustomTrackView::getClipItemAt(GenTime pos, int track)
     return getClipItemAt((int) pos.frames(m_document->fps()), track);
 }
 
+
+Transition *CustomTrackView::getTransitionItem(TransitionInfo info)
+{
+    int pos = info.startPos.frames(m_document->fps());
+    int track = m_document->tracksCount() - info.b_track;
+    return getTransitionItemAt(pos, track);
+}
+
 Transition *CustomTrackView::getTransitionItemAt(int pos, int track)
 {
     const QPointF p(pos, track * m_tracksHeight + Transition::itemOffset() + 1);
@@ -4303,10 +4439,12 @@ bool CustomTrackView::moveClip(const ItemInfo &start, const ItemInfo &end, bool
     }
     Mlt::Producer *prod = item->getProducer(end.track);
 
+#ifdef DEBUG
     qDebug() << "Moving item " << (long)item << " from .. to:";
     qDebug() << item->info();
     qDebug() << start;
     qDebug() << end;
+#endif
     bool success = m_document->renderer()->mltMoveClip((int)(m_document->tracksCount() - start.track), (int)(m_document->tracksCount() - end.track),
                                                        (int) start.startPos.frames(m_document->fps()), (int)end.startPos.frames(m_document->fps()),
                                                        prod);
@@ -4341,9 +4479,13 @@ bool CustomTrackView::moveClip(const ItemInfo &start, const ItemInfo &end, bool
     if (refresh) m_document->renderer()->doRefresh();
     if (out_actualEnd != NULL) {
         *out_actualEnd = item->info();
+#ifdef DEBUG
         qDebug() << "Actual end position updated:" << *out_actualEnd;
+#endif
     }
+#ifdef DEBUG
     qDebug() << item->info();
+#endif
     return success;
 }
 
@@ -4781,7 +4923,7 @@ void CustomTrackView::updatePositionEffects(ClipItem* item, ItemInfo info, bool
                     emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
                 // if fade effect is displayed, update the effect edit widget with new clip duration
                 if (item->isSelected() && effectPos == item->selectedEffectIndex())
-                    emit clipItemSelected(item, effectPos);
+                    emit clipItemSelected(item);
             }
         }
         effectPos = item->hasEffect("brightness", "fade_from_black");
@@ -4802,7 +4944,7 @@ void CustomTrackView::updatePositionEffects(ClipItem* item, ItemInfo info, bool
                     emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
                 // if fade effect is displayed, update the effect edit widget with new clip duration
                 if (item->isSelected() && effectPos == item->selectedEffectIndex())
-                    emit clipItemSelected(item, effectPos);
+                    emit clipItemSelected(item);
             }
         }
     }
@@ -4828,7 +4970,7 @@ void CustomTrackView::updatePositionEffects(ClipItem* item, ItemInfo info, bool
                     emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
                 // if fade effect is displayed, update the effect edit widget with new clip duration
                 if (item->isSelected() && effectPos == item->selectedEffectIndex())
-                    emit clipItemSelected(item, effectPos);
+                    emit clipItemSelected(item);
             }
         }
         effectPos = item->hasEffect("brightness", "fade_to_black");
@@ -4849,7 +4991,7 @@ void CustomTrackView::updatePositionEffects(ClipItem* item, ItemInfo info, bool
                     emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
                 // if fade effect is displayed, update the effect edit widget with new clip duration
                 if (item->isSelected() && effectPos == item->selectedEffectIndex())
-                    emit clipItemSelected(item, effectPos);
+                    emit clipItemSelected(item);
             }
         }
     }
@@ -4864,7 +5006,7 @@ void CustomTrackView::updatePositionEffects(ClipItem* item, ItemInfo info, bool
             EffectsList::setParameter(eff, "frame", QString::number(freeze_pos));
             if (standalone) {
                 if (item->isSelected() && item->selectedEffect().attribute("id") == "freeze") {
-                    emit clipItemSelected(item, item->selectedEffectIndex());
+                    emit clipItemSelected(item);
                 }
             }
         }
@@ -5548,7 +5690,7 @@ void CustomTrackView::pasteClipEffects()
     for (int i = 0; i < clips.count(); ++i) {
         if (clips.at(i)->type() == AVWIDGET) {
             ClipItem *item = static_cast < ClipItem *>(clips.at(i));
-            for (int j = 0; j < clip->effectsCount(); j++) {
+            for (int j = 1; j <= clip->effectsCount(); j++) {
                 QDomElement eff = clip->effectAt(j);
                 if (eff.attribute("unique", "0") == "0" || item->hasEffect(eff.attribute("tag"), eff.attribute("id")) == -1) {
                     adjustKeyfames(clip->cropStart(), item->cropStart(), item->cropDuration(), eff);
@@ -5774,6 +5916,7 @@ void CustomTrackView::slotInsertTrack(int ix)
         info.duration = 0;
         info.isMute = false;
         info.isLocked = false;
+       info.effectsList = EffectsList(true);
         if (d.video_track->isChecked()) {
             info.type = VIDEOTRACK;
             info.isBlind = false;
@@ -6014,12 +6157,20 @@ void CustomTrackView::alignAudio()
     QList<QGraphicsItem *> selection = scene()->selectedItems();
     foreach (QGraphicsItem *item, selection) {
         if (item->type() == AVWIDGET) {
+
             ClipItem *clip = static_cast<ClipItem*>(item);
+            if (clip == m_audioAlignmentReference) {
+                continue;
+            }
+
             if (clip->clipType() == AV || clip->clipType() == AUDIO) {
                 AudioEnvelope *envelope = new AudioEnvelope(clip->getProducer(clip->track()),
                                                             clip->info().cropStart.frames(m_document->fps()),
                                                             clip->info().cropDuration.frames(m_document->fps()));
-                int index = m_audioCorrelator->addChild(envelope);
+
+                // FFT only for larger vectors. We could use it all time, but for small vectors
+                // the (anyway not noticeable) overhead is smaller with a nested for loop correlation.
+                int index = m_audioCorrelator->addChild(envelope, envelope->envelopeSize() > 200);
                 int shift = m_audioCorrelator->getShift(index);
                 counter++;
 
@@ -6027,12 +6178,14 @@ void CustomTrackView::alignAudio()
                 envelope->drawEnvelope().save("kdenlive-audio-align-envelope.png");
                 envelope->dumpInfo();
 
+#ifdef DEBUG
                 int targetPos = m_audioAlignmentReference->startPos().frames(m_document->fps()) + shift;
                 qDebug() << "Reference starts at " << m_audioAlignmentReference->startPos().frames(m_document->fps());
                 qDebug() << "We will start at " << targetPos;
                 qDebug() << "to shift by " << shift;
                 qDebug() << "(eventually)";
                 qDebug() << "(maybe)";
+#endif
 
 
                 QUndoCommand *moveCommand = new QUndoCommand();
@@ -6041,16 +6194,17 @@ void CustomTrackView::alignAudio()
                 ItemInfo start = clip->info();
 
                 ItemInfo end = start;
-                end.startPos = m_audioAlignmentReference->info().startPos + add;
+                end.startPos = m_audioAlignmentReference->startPos() + add - m_audioAlignmentReference->cropStart();
                 end.endPos = end.startPos + start.cropDuration;
 
                 if ( end.startPos.seconds() < 0 ) {
                     // Clip would start before 0, so crop it first
-                    qDebug() << "Need to crop clip. " << start;
-
-
                     GenTime cropBy = -end.startPos;
+
+#ifdef DEBUG
+                    qDebug() << "Need to crop clip. " << start;
                     qDebug() << "end.startPos: " << end.startPos.toString() << ", cropBy: " << cropBy.toString();
+#endif
 
                     ItemInfo resized = start;
                     resized.startPos += cropBy;
@@ -6061,8 +6215,16 @@ void CustomTrackView::alignAudio()
                     start = clip->info();
                     end.startPos += cropBy;
 
+#ifdef DEBUG
                     qDebug() << "Clip cropped. " << start;
                     qDebug() << "Moving to: " << end;
+#endif
+                }
+
+                if (itemCollision(clip, end)) {
+                    delete moveCommand;
+                    emit displayMessage(i18n("Unable to move clip due to collision."), ErrorMessage);
+                    return;
                 }
 
                 moveCommand->setText(i18n("Auto-align clip"));
@@ -6619,12 +6781,12 @@ void CustomTrackView::insertZoneOverwrite(QStringList data, int in)
         splitAudio();
 }
 
-void CustomTrackView::clearSelection()
+void CustomTrackView::clearSelection(bool emitInfo)
 {
     resetSelectionGroup();
     scene()->clearSelection();
     m_dragItem = NULL;
-    emit clipItemSelected(NULL);
+    if (emitInfo) emit clipItemSelected(NULL);
 }
 
 void CustomTrackView::updatePalette()
@@ -6636,7 +6798,6 @@ void CustomTrackView::updatePalette()
         pen1.setColor(palette().text().color());
         m_cursorLine->setPen(pen1);
     }
-    emit tracksChanged();
 }
 
 void CustomTrackView::removeTipAnimation()
@@ -6743,9 +6904,42 @@ bool CustomTrackView::hasAudio(int track) const
 
 void CustomTrackView::slotAddTrackEffect(const QDomElement &effect, int ix)
 {
-    AddEffectCommand *command = new AddEffectCommand(this, m_document->tracksCount() - ix, GenTime(-1), effect, true);
-    m_commandStack->push(command);
-    setDocumentModified();
+    
+    QUndoCommand *effectCommand = new QUndoCommand();
+    QString effectName;
+    if (effect.tagName() == "effectgroup") {
+        effectName = effect.attribute("name");
+    } else {
+        QDomElement namenode = effect.firstChildElement("name");
+        if (!namenode.isNull()) effectName = i18n(namenode.text().toUtf8().data());
+        else effectName = i18n("effect");
+    }
+    effectCommand->setText(i18n("Add %1", effectName));
+    if (effect.tagName() == "effectgroup") {
+        QDomNodeList effectlist = effect.elementsByTagName("effect");
+        for (int j = 0; j < effectlist.count(); j++) {
+            QDomElement trackeffect = effectlist.at(j).toElement();
+            if (trackeffect.attribute("unique", "0") != "0" && m_document->hasTrackEffect(m_document->tracksCount() - ix - 1, trackeffect.attribute("tag"), trackeffect.attribute("id")) != -1) {
+                emit displayMessage(i18n("Effect already present in track"), ErrorMessage);
+                continue;
+            }
+            new AddEffectCommand(this, m_document->tracksCount() - ix, GenTime(-1), trackeffect, true, effectCommand);
+        }
+    }
+    else {
+        if (effect.attribute("unique", "0") != "0" && m_document->hasTrackEffect(m_document->tracksCount() - ix - 1, effect.attribute("tag"), effect.attribute("id")) != -1) {
+            emit displayMessage(i18n("Effect already present in track"), ErrorMessage);
+            delete effectCommand;
+            return;
+        }
+        new AddEffectCommand(this, m_document->tracksCount() - ix, GenTime(-1), effect, true, effectCommand);
+    }
+
+    if (effectCommand->childCount() > 0) {
+        m_commandStack->push(effectCommand);
+        setDocumentModified();
+    }
+    else delete effectCommand;
 }
 
 
@@ -6754,23 +6948,45 @@ EffectsParameterList CustomTrackView::getEffectArgs(const QDomElement &effect)
     EffectsParameterList parameters;
     QLocale locale;
     parameters.addParam("tag", effect.attribute("tag"));
-    if (effect.hasAttribute("region")) parameters.addParam("region", effect.attribute("region"));
+    //if (effect.hasAttribute("region")) parameters.addParam("region", effect.attribute("region"));
     parameters.addParam("kdenlive_ix", effect.attribute("kdenlive_ix"));
+    parameters.addParam("kdenlive_info", effect.attribute("kdenlive_info"));
     parameters.addParam("id", effect.attribute("id"));
     if (effect.hasAttribute("src")) parameters.addParam("src", effect.attribute("src"));
     if (effect.hasAttribute("disable")) parameters.addParam("disable", effect.attribute("disable"));
     if (effect.hasAttribute("in")) parameters.addParam("in", effect.attribute("in"));
     if (effect.hasAttribute("out")) parameters.addParam("out", effect.attribute("out"));
+    if (effect.attribute("id") == "region") {
+       QDomNodeList subeffects = effect.elementsByTagName("effect");
+       for (int i = 0; i < subeffects.count(); i++) {
+           QDomElement subeffect = subeffects.at(i).toElement();
+           int subeffectix = subeffect.attribute("region_ix").toInt();
+           parameters.addParam(QString("filter%1").arg(subeffectix), subeffect.attribute("id"));
+           parameters.addParam(QString("filter%1.tag").arg(subeffectix), subeffect.attribute("tag"));
+           parameters.addParam(QString("filter%1.kdenlive_info").arg(subeffectix), subeffect.attribute("kdenlive_info"));
+           QDomNodeList subparams = subeffect.elementsByTagName("parameter");
+           adjustEffectParameters(parameters, subparams, QString("filter%1.").arg(subeffectix));
+       }
+    }
 
     QDomNodeList params = effect.elementsByTagName("parameter");
-    for (int i = 0; i < params.count(); i++) {
+    adjustEffectParameters(parameters, params);
+    
+    return parameters;
+}
+
+
+void CustomTrackView::adjustEffectParameters(EffectsParameterList &parameters, QDomNodeList params, const QString &prefix)
+{
+  QLocale locale;
+  for (int i = 0; i < params.count(); i++) {
         QDomElement e = params.item(i).toElement();
+       QString paramname = prefix + e.attribute("name");
         if (e.attribute("type") == "geometry" && !e.hasAttribute("fixed")) {
             // effects with geometry param need in / out synced with the clip, request it...
             parameters.addParam("_sync_in_out", "1");
         }
         if (e.attribute("type") == "simplekeyframe") {
-
             QStringList values = e.attribute("keyframes").split(";", QString::SkipEmptyParts);
             double factor = e.attribute("factor", "1").toDouble();
             double offset = e.attribute("offset", "0").toDouble();
@@ -6780,7 +6996,7 @@ EffectsParameterList CustomTrackView::getEffectArgs(const QDomElement &effect)
                 values[j] = pos + "=" + locale.toString(val);
             }
             // kDebug() << "/ / / /SENDING KEYFR:" << values;
-            parameters.addParam(e.attribute("name"), values.join(";"));
+            parameters.addParam(paramname, values.join(";"));
             /*parameters.addParam(e.attribute("name"), e.attribute("keyframes").replace(":", "="));
             parameters.addParam("max", e.attribute("max"));
             parameters.addParam("min", e.attribute("min"));
@@ -6816,15 +7032,15 @@ EffectsParameterList CustomTrackView::getEffectArgs(const QDomElement &effect)
                     fact = e.attribute("factor", "1").toDouble();
                 }
                 double offset = e.attribute("offset", "0").toDouble();
-                parameters.addParam(e.attribute("name"), locale.toString((e.attribute("value").toDouble() - offset) / fact));
+                parameters.addParam(paramname, locale.toString((e.attribute("value").toDouble() - offset) / fact));
             } else {
-                parameters.addParam(e.attribute("name"), e.attribute("value"));
+                parameters.addParam(paramname, e.attribute("value"));
             }
         }
     }
-    return parameters;
 }
 
+
 void CustomTrackView::updateTrackNames(int track, bool added)
 {
     QList <TrackInfo> tracks = m_document->tracksList();
@@ -6914,7 +7130,7 @@ void CustomTrackView::adjustEffects(ClipItem* item, ItemInfo oldInfo, QUndoComma
     if (effects.count()) {
         QMap<int, QDomElement>::const_iterator i = effects.constBegin();
         while (i != effects.constEnd()) {
-            new EditEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), i.value(), item->effectAt(i.key()), i.key(), false, command);
+            new EditEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), i.value(), item->effectAt(i.key()), i.key(), false, false, command);
             ++i;
         }
     }
@@ -6938,9 +7154,9 @@ void CustomTrackView::slotGotFilterJobResults(const QString &/*id*/, int startPo
             kDebug()<<"// RESULT FILTER: "<<i.key()<<"="<< i.value();
             ++i;
         }
-        EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effect, newEffect, clip->selectedEffectIndex(), true);
+        EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effect, newEffect, clip->selectedEffectIndex(), true, true);
         m_commandStack->push(command);
-        emit clipItemSelected(clip, clip->selectedEffectIndex());
+        emit clipItemSelected(clip);
     }
     
 }