]> git.sesse.net Git - kdenlive/commitdiff
Several fixes for region effect
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Thu, 12 Apr 2012 19:29:48 +0000 (21:29 +0200)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Thu, 12 Apr 2012 19:29:48 +0000 (21:29 +0200)
src/effectstack/effectstackview2.cpp
src/effectstack/effectstackview2.h
src/kdenliveui.rc
src/mainwindow.cpp
src/mainwindow.h
src/renderer.cpp
src/renderer.h

index dc09c99ebb5ecea1bbbd320f14b382570fed742c..27f77f42722e6bd7bd9551b30cc9ad9871640ed6 100644 (file)
@@ -225,26 +225,7 @@ void EffectStackView2::setupListView()
        } else {
            vbox1->addWidget(currentEffect);
        }
-
-       // Check drag & drop
-       currentEffect->installEventFilter( this );
-
-        connect(currentEffect, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this , SLOT(slotUpdateEffectParams(const QDomElement, const QDomElement, int)));
-       connect(currentEffect, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString)), this , SLOT(slotStartFilterJob(QString,QString,QString,QString,QString,QString)));
-        connect(currentEffect, SIGNAL(deleteEffect(const QDomElement)), this , SLOT(slotDeleteEffect(const QDomElement)));
-       connect(currentEffect, SIGNAL(reloadEffects()), this , SIGNAL(reloadEffects()));
-       connect(currentEffect, SIGNAL(resetEffect(int)), this , SLOT(slotResetEffect(int)));
-        connect(currentEffect, SIGNAL(changeEffectPosition(int,bool)), this , SLOT(slotMoveEffectUp(int , bool)));
-        connect(currentEffect, SIGNAL(effectStateChanged(bool,int,bool)), this, SLOT(slotUpdateEffectState(bool,int,bool)));
-        connect(currentEffect, SIGNAL(activateEffect(int)), this, SLOT(slotSetCurrentEffect(int)));
-        connect(currentEffect, SIGNAL(checkMonitorPosition(int)), this, SLOT(slotCheckMonitorPosition(int)));
-        connect(currentEffect, SIGNAL(seekTimeline(int)), this , SLOT(slotSeekTimeline(int)));
-       connect(currentEffect, SIGNAL(createGroup(int)), this , SLOT(slotCreateGroup(int)));
-       connect(currentEffect, SIGNAL(moveEffect(int,int,int,QString)), this , SLOT(slotMoveEffect(int,int,int,QString)));
-       connect(currentEffect, SIGNAL(addEffect(QDomElement)), this , SLOT(slotAddEffect(QDomElement)));
-       connect(currentEffect, SIGNAL(createRegion(int,KUrl)), this, SLOT(slotCreateRegion(int,KUrl)));
-       
-        //ui.title->setPixmap(icon.pixmap(QSize(12, 12)));
+       connectEffect(currentEffect);
     }
     vbox1->addStretch(10);
     slotUpdateCheckAllButton();
@@ -254,6 +235,25 @@ void EffectStackView2::setupListView()
     QTimer::singleShot(200, this, SLOT(slotCheckWheelEventFilter()));
 }
 
+void EffectStackView2::connectEffect(CollapsibleEffect *currentEffect)
+{
+    // Check drag & drop
+    currentEffect->installEventFilter( this );
+    connect(currentEffect, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this , SLOT(slotUpdateEffectParams(const QDomElement, const QDomElement, int)));
+    connect(currentEffect, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString)), this , SLOT(slotStartFilterJob(QString,QString,QString,QString,QString,QString)));
+    connect(currentEffect, SIGNAL(deleteEffect(const QDomElement)), this , SLOT(slotDeleteEffect(const QDomElement)));
+    connect(currentEffect, SIGNAL(reloadEffects()), this , SIGNAL(reloadEffects()));
+    connect(currentEffect, SIGNAL(resetEffect(int)), this , SLOT(slotResetEffect(int)));
+    connect(currentEffect, SIGNAL(changeEffectPosition(int,bool)), this , SLOT(slotMoveEffectUp(int , bool)));
+    connect(currentEffect, SIGNAL(effectStateChanged(bool,int,bool)), this, SLOT(slotUpdateEffectState(bool,int,bool)));
+    connect(currentEffect, SIGNAL(activateEffect(int)), this, SLOT(slotSetCurrentEffect(int)));
+    connect(currentEffect, SIGNAL(checkMonitorPosition(int)), this, SLOT(slotCheckMonitorPosition(int)));
+    connect(currentEffect, SIGNAL(seekTimeline(int)), this , SLOT(slotSeekTimeline(int)));
+    connect(currentEffect, SIGNAL(createGroup(int)), this , SLOT(slotCreateGroup(int)));
+    connect(currentEffect, SIGNAL(moveEffect(int,int,int,QString)), this , SLOT(slotMoveEffect(int,int,int,QString)));
+    connect(currentEffect, SIGNAL(addEffect(QDomElement)), this , SLOT(slotAddEffect(QDomElement)));
+    connect(currentEffect, SIGNAL(createRegion(int,KUrl)), this, SLOT(slotCreateRegion(int,KUrl)));
+}
 
 void EffectStackView2::slotCheckWheelEventFilter()
 {
@@ -660,7 +660,8 @@ void EffectStackView2::slotCreateRegion(int ix, KUrl url)
     m_currentEffectList.insert(region);
     current->deleteLater();
     CollapsibleEffect *currentEffect = new CollapsibleEffect(region, m_currentEffectList.itemFromIndex(ix), info, &m_effectMetaInfo, ix == m_currentEffectList.count() - 1, m_ui.container->widget());
-    connect(currentEffect, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this , SLOT(slotUpdateEffectParams(const QDomElement, const QDomElement, int)));
+    connectEffect(currentEffect);
+    
     if (m_effectMetaInfo.trackMode) {
        isSelected = currentEffect->effectIndex() == 1;
     }
index 1c4b5e680e83df2c72c572281ccdb474cf90fe14..2a1da03202313c1d52e09b9c1cb96df650cdd437 100644 (file)
@@ -107,6 +107,9 @@ private:
     
     /** @brief Build the drag info and start it. */
     void startDrag();
+    
+    /** @brief Connect an effect to its signals. */
+    void connectEffect(CollapsibleEffect *currentEffect);
 
 public slots:
     /** @brief Sets the clip whose effect list should be managed.
index 1cb088d43e2ac046ef6e38f88aa4202c0b6a2125..c6b393fb23db48cbdf79280aaf21417467396850 100644 (file)
       </Menu>
       <Action name="resize_timeline_clip_start" />
       <Action name="resize_timeline_clip_end" />
-      <Action name="cut_timeline_clip" />
-      <Action name="delete_timeline_clip" />
-      <Action name="edit_item_duration" />
+      <Menu name="current_clip" ><text>Current clip</text>
+         <Action name="cut_timeline_clip" />
+         <Action name="delete_timeline_clip" />
+         <Action name="edit_item_duration" />
+         <Action name="save_timeline_clip" />
+      </Menu>
       <Menu name="guide_menu" ><text>Guides</text>
                <Action name="add_guide" />
                <Action name="edit_guide" />
index 409dfaa91aa0bf49157b8cba2eefb78f7c77cb07..d03ff48f7dc62cc6cf4a198e2ea3053b3bb489ba 100644 (file)
@@ -538,7 +538,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
 
     m_timelineContextClipMenu->addAction(actionCollection()->action("clip_in_project_tree"));
     //m_timelineContextClipMenu->addAction(actionCollection()->action("clip_to_project_tree"));
-    m_timelineContextClipMenu->addAction(actionCollection()->action("edit_item_duration"));
     m_timelineContextClipMenu->addAction(actionCollection()->action("delete_item"));
     m_timelineContextClipMenu->addSeparator();
     m_timelineContextClipMenu->addAction(actionCollection()->action("group_clip"));
@@ -556,7 +555,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_timelineContextClipMenu->addMenu(m_transitionsMenu);
     m_timelineContextClipMenu->addMenu(m_effectsMenu);
 
-    m_timelineContextTransitionMenu->addAction(actionCollection()->action("edit_item_duration"));
     m_timelineContextTransitionMenu->addAction(actionCollection()->action("delete_item"));
     m_timelineContextTransitionMenu->addAction(actionCollection()->action(KStandardAction::name(KStandardAction::Copy)));
 
@@ -1393,6 +1391,10 @@ void MainWindow::setupActions()
     KAction* editItemDuration = new KAction(KIcon("measure"), i18n("Edit Duration"), this);
     collection.addAction("edit_item_duration", editItemDuration);
     connect(editItemDuration, SIGNAL(triggered(bool)), this, SLOT(slotEditItemDuration()));
+    
+    KAction* saveTimelineClip = new KAction(KIcon("document-save"), i18n("Save clip"), this);
+    collection.addAction("save_timeline_clip", saveTimelineClip);
+    connect(saveTimelineClip, SIGNAL(triggered(bool)), this, SLOT(slotSaveTimelineClip()));
 
     KAction* clipInProjectTree = new KAction(KIcon("go-jump-definition"), i18n("Clip in Project Tree"), this);
     collection.addAction("clip_in_project_tree", clipInProjectTree);
@@ -4446,6 +4448,19 @@ void MainWindow::slotChangePalette()
     }
 }
 
+void MainWindow::slotSaveTimelineClip()
+{
+    if (m_activeTimeline && m_projectMonitor->render) {
+       ClipItem *clip = m_activeTimeline->projectView()->getActiveClipUnderCursor(true);
+       if (!clip) {
+           m_messageLabel->setMessage(i18n("Select a clip to save"), InformationMessage);
+           return;
+       }
+       KUrl url = KFileDialog::getSaveUrl(m_activeDocument->projectFolder(), "video/mlt-playlist");
+       if (!url.isEmpty()) m_projectMonitor->render->saveClip(m_activeDocument->tracksCount() - clip->track(), clip->startPos(), url);
+    }
+}
+
 
 #include "mainwindow.moc"
 
index c54a2325de4dc1c564e9d21886ef88a00d16f812..3b33dad7a91b0e49bc4a76871a477c97aad96e66 100644 (file)
@@ -554,6 +554,8 @@ private slots:
     void slotDownloadResources();
     
     void slotChangePalette();
+    /** @brief Save current timeline clip as mlt playlist. */
+    void slotSaveTimelineClip();
 
 signals:
     Q_SCRIPTABLE void abortRenderJob(const QString &url);
index 14927a75045a807cd64cefc97748a809aae9087e..a0b2c61073bff31abc62a4098b9eb47fc08add6f 100644 (file)
@@ -1320,6 +1320,34 @@ void Render::saveZone(KUrl url, QString desc, QPoint zone)
     xmlConsumer.start();
 }
 
+
+bool Render::saveClip(int track, GenTime position, KUrl url, QString desc)
+{
+    // find clip
+    Mlt::Service service(m_mltProducer->parent().get_service());
+    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((int) position.frames(m_fps));
+    Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
+    if (!clip) {
+        kDebug() << "WARINIG, CANNOT FIND CLIP ON track: " << track << ", AT POS: " << position.frames(m_fps);
+        return false;
+    }
+    
+    Mlt::Consumer xmlConsumer(*m_mltProfile, ("xml:" + url.path()).toUtf8().constData());
+    xmlConsumer.set("terminate_on_pause", 1);
+    Mlt::Playlist list;
+    list.insert_at(0, clip, 0);
+    //delete clip;
+    list.set("title", desc.toUtf8().constData());
+    xmlConsumer.connect(list);
+    xmlConsumer.run();
+    kDebug()<<"// SAVED: "<<url;
+    return true;
+}
+
 double Render::fps() const
 {
     return m_fps;
@@ -2532,7 +2560,6 @@ bool Render::mltAddEffect(Mlt::Service service, EffectsParameterList params, int
 {
     bool updateIndex = false;
     const int filter_ix = params.paramValue("kdenlive_ix").toInt();
-    const QString region =  params.paramValue("region");
     int ct = 0;
     service.lock();
 
@@ -2576,15 +2603,30 @@ bool Render::mltAddEffect(Mlt::Service service, EffectsParameterList params, int
         filter = service.filter(ct);
     }
 
-    // create filter
+    addFilterToService(service, params, duration);
+
+    // re-add following filters
+    for (int i = 0; i < filtersList.count(); i++) {
+        Mlt::Filter *filter = filtersList.at(i);
+        if (updateIndex)
+            filter->set("kdenlive_ix", filter->get_int("kdenlive_ix") + 1);
+        service.attach(*filter);
+    }
+    service.unlock();
+    if (doRefresh) refresh();
+    return true;
+}
+
+
+bool Render::addFilterToService(Mlt::Service service, EffectsParameterList params, int duration)
+{
+      // create filter
     QString tag =  params.paramValue("tag");
     //kDebug() << " / / INSERTING EFFECT: " << tag << ", REGI: " << region;
     char *filterTag = qstrdup(tag.toUtf8().constData());
     char *filterId = qstrdup(params.paramValue("id").toUtf8().constData());
-    QHash<QString, QString>::Iterator it;
     QString kfr = params.paramValue("keyframes");
-
-    if (!kfr.isEmpty()) {
+  if (!kfr.isEmpty()) {
         QStringList keyFrames = kfr.split(';', QString::SkipEmptyParts);
         //kDebug() << "// ADDING KEYFRAME EFFECT: " << params.paramValue("keyframes");
         char *starttag = qstrdup(params.paramValue("starttag", "start").toUtf8().constData());
@@ -2645,20 +2687,9 @@ bool Render::mltAddEffect(Mlt::Service service, EffectsParameterList params, int
     } else {
         Mlt::Filter *filter;
         QString prefix;
-        if (!region.isEmpty()) {
-            filter = new Mlt::Filter(*m_mltProfile, "region");
-        } else filter = new Mlt::Filter(*m_mltProfile, filterTag);
+        filter = new Mlt::Filter(*m_mltProfile, filterTag);
         if (filter && filter->is_valid()) {
             filter->set("kdenlive_id", filterId);
-            if (!region.isEmpty()) {
-                filter->set("resource", region.toUtf8().constData());
-                filter->set("kdenlive_ix", params.paramValue("kdenlive_ix").toUtf8().constData());
-                filter->set("filter0", filterTag);
-                prefix = "filter0.";
-                params.removeParam("id");
-                params.removeParam("region");
-                params.removeParam("kdenlive_ix");
-            }
         } else {
             kDebug() << "filter is NULL";
             service.unlock();
@@ -2690,22 +2721,12 @@ bool Render::mltAddEffect(Mlt::Service service, EffectsParameterList params, int
             //kDebug() << "SOX EFFECTS: " << effectArgs.simplified();
             filter->set("effect", effectArgs.simplified().toUtf8().constData());
         }
-
         // attach filter to the clip
         service.attach(*filter);
     }
+       
     delete[] filterId;
     delete[] filterTag;
-
-    // re-add following filters
-    for (int i = 0; i < filtersList.count(); i++) {
-        Mlt::Filter *filter = filtersList.at(i);
-        if (updateIndex)
-            filter->set("kdenlive_ix", filter->get_int("kdenlive_ix") + 1);
-        service.attach(*filter);
-    }
-    service.unlock();
-    if (doRefresh) refresh();
     return true;
 }
 
@@ -2755,7 +2776,7 @@ bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList par
     int index = params.paramValue("kdenlive_ix").toInt();
     QString tag =  params.paramValue("tag");
 
-    if (!params.paramValue("keyframes").isEmpty() || (tag == "affine" && params.hasParam("background")) || tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle" || params.hasParam("region")) {
+    if (!params.paramValue("keyframes").isEmpty() || (tag == "affine" && params.hasParam("background")) || tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle") {
         // This is a keyframe effect, to edit it, we remove it and re-add it.
         bool success = mltRemoveEffect(track, position, index, false);
 //         if (!success) kDebug() << "// ERROR Removing effect : " << index;
@@ -2806,17 +2827,45 @@ bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList par
         bool success = mltAddEffect(track, position, params);
         return success;
     }
-    QString prefix;
+    ct = 0;
     QString ser = filter->get("mlt_service");
-    if (ser == "region") prefix = "filter0.";
+    QList <Mlt::Filter *> filtersList;
+    service.lock();
+    if (ser != tag) {
+       // Effect service changes, delete effect and re-add it
+       clip->detach(*filter);  
+       
+       // Delete all effects after deleted one
+       filter = clip->filter(ct);
+        while (filter) {
+            if (filter->get_int("kdenlive_ix") > index) {
+                filtersList.append(filter);
+                clip->detach(*filter);
+           }
+           else ct++;
+            filter = clip->filter(ct);
+       }
+       
+       // re-add filter
+       addFilterToService(*clip, params, clip->get_playtime());
+       delete clip;
+       service.unlock();
+
+       if (doRefresh) refresh();
+       return true;
+    }
     if (params.hasParam("_sync_in_out")) {
         // This effect must sync in / out with parent clip
         params.removeParam("_sync_in_out");
         filter->set_in_and_out(clip->get_in(), clip->get_out());
     }
-    service.lock();
+
     for (int j = 0; j < params.count(); j++) {
-        filter->set((prefix + params.at(j).name()).toUtf8().constData(), params.at(j).value().toUtf8().constData());
+        filter->set((params.at(j).name()).toUtf8().constData(), params.at(j).value().toUtf8().constData());
+    }
+    
+    for (int j = 0; j < filtersList.count(); j++) {
+       clip->attach(*(filtersList.at(j)));
     }
 
     delete clip;
index c71f4b6a9441c42550bd60e4fc0671f1e51393a5..cd81010e50bd46b3025af7e8bfdcc91b8bdf15f8 100644 (file)
@@ -155,6 +155,9 @@ Q_OBJECT public:
     void loopZone(const GenTime & startTime, const GenTime & stopTime);
 
     void saveZone(KUrl url, QString desc, QPoint zone);
+    
+    /** @brief Save a clip in timeline to an xml playlist. */
+    bool saveClip(int track, GenTime position, KUrl url, QString desc = QString());
 
     /** @brief Returns the speed at which the renderer is currently playing.
      *
@@ -223,6 +226,7 @@ Q_OBJECT public:
 
     /** @brief Adds an effect to a clip in MLT's playlist. */
     bool mltAddEffect(int track, GenTime position, EffectsParameterList params, bool doRefresh = true);
+    bool addFilterToService(Mlt::Service service, EffectsParameterList params, int duration);
     bool mltAddEffect(Mlt::Service service, EffectsParameterList params, int duration, bool doRefresh);
     bool mltAddTrackEffect(int track, EffectsParameterList params);