Several fixes for region effect

parent bd18e035
......@@ -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;
}
......
......@@ -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.
......
......@@ -100,9 +100,12 @@
</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" />
......
......@@ -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"
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment