From c2ff32876591d3e015410ac619b4d8e3746571dc Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Sun, 21 Oct 2012 11:48:18 +0200 Subject: [PATCH] Cleanup data processing framework --- effects/automask.xml | 2 +- effects/sox_gain.xml | 2 +- src/CMakeLists.txt | 1 + src/clipproperties.cpp | 11 ++- src/clipproperties.h | 2 +- src/customtrackview.cpp | 40 +++++++--- src/customtrackview.h | 4 +- src/effectstack/collapsibleeffect.cpp | 2 +- src/effectstack/collapsibleeffect.h | 2 +- src/effectstack/effectstackview2.cpp | 6 +- src/effectstack/effectstackview2.h | 4 +- src/effectstack/parametercontainer.cpp | 7 +- src/effectstack/parametercontainer.h | 2 +- src/mainwindow.cpp | 27 ++++--- src/mainwindow.h | 2 +- src/projectlist.cpp | 100 ++++++++++++++++++++----- src/projectlist.h | 7 +- src/projecttree/meltjob.cpp | 13 +++- src/projecttree/meltjob.h | 2 +- src/widgets/scenecutdialog_ui.ui | 97 ++++++++++++++++++++++++ 20 files changed, 262 insertions(+), 71 deletions(-) create mode 100644 src/widgets/scenecutdialog_ui.ui diff --git a/effects/automask.xml b/effects/automask.xml index d2bde1ac..1d5f0b2d 100644 --- a/effects/automask.xml +++ b/effects/automask.xml @@ -12,7 +12,7 @@ Obscure - + Analyse diff --git a/effects/sox_gain.xml b/effects/sox_gain.xml index d40552b5..0a67a674 100644 --- a/effects/sox_gain.xml +++ b/effects/sox_gain.xml @@ -6,7 +6,7 @@ Gain - + Normalize diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 597dfbb0..74c44596 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -262,6 +262,7 @@ kde4_add_ui_files(kdenlive_UIS widgets/keywordval_ui.ui widgets/fontval_ui.ui widgets/cutjobdialog_ui.ui + widgets/scenecutdialog_ui.ui ) if(OPENGL_FOUND) diff --git a/src/clipproperties.cpp b/src/clipproperties.cpp index 7981f953..1d5e39ee 100644 --- a/src/clipproperties.cpp +++ b/src/clipproperties.cpp @@ -771,7 +771,9 @@ void ClipProperties::slotAddMarker() QPointer d = new MarkerDialog(m_clip, marker, m_tc, i18n("Add Marker"), this); if (d->exec() == QDialog::Accepted) { - emit addMarker(m_clip->getId(), d->newMarker()); + QList markers; + markers << d->newMarker(); + emit addMarkers(m_clip->getId(), markers); } delete d; } @@ -793,7 +795,9 @@ void ClipProperties::slotEditMarker() if (pos < 0 || pos > marks.count() - 1) return; MarkerDialog d(m_clip, marks.at(pos), m_tc, i18n("Edit Marker"), this); if (d.exec() == QDialog::Accepted) { - emit addMarker(m_clip->getId(), d.newMarker()); + QList markers; + markers << d.newMarker(); + emit addMarkers(m_clip->getId(), markers); } } @@ -808,8 +812,7 @@ void ClipProperties::slotDeleteMarker() toDelete << marker; } } - for (int i = 0; i < toDelete.count(); i++) - emit addMarker(m_clip->getId(), toDelete.at(i)); + emit addMarkers(m_clip->getId(), toDelete); } void ClipProperties::slotDeleteAnalysis() diff --git a/src/clipproperties.h b/src/clipproperties.h index 97ac8dd6..ec0dee89 100644 --- a/src/clipproperties.h +++ b/src/clipproperties.h @@ -93,7 +93,7 @@ private: QFrame* m_proxyContainer; signals: - void addMarker(const QString &, CommentedTime); + void addMarkers(const QString &, QList ); void deleteProxy(const QString); void applyNewClipProperties(const QString, QMap , QMap , bool, bool); void saveMarkers(const QString &); diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 6d6d5482..45834e5d 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -5269,15 +5269,31 @@ void CustomTrackView::slotAddClipExtraData(const QString &id, const QString &key if (!groupCommand) m_commandStack->push(command); } -void CustomTrackView::slotAddClipMarker(const QString &id, CommentedTime newMarker, QUndoCommand *groupCommand) -{ - CommentedTime oldMarker = m_document->clipManager()->getClipById(id)->markerAt(newMarker.time()); - if (oldMarker == CommentedTime()) { - oldMarker = newMarker; - oldMarker.setMarkerType(-1); +void CustomTrackView::slotAddClipMarker(const QString &id, QList newMarkers, QUndoCommand *groupCommand) +{ + QUndoCommand *subCommand = NULL; + if (newMarkers.count() > 1 && groupCommand == NULL) { + subCommand = new QUndoCommand; + subCommand->setText("Add markers"); + } + for (int i = 0; i < newMarkers.count(); i++) { + CommentedTime oldMarker = m_document->clipManager()->getClipById(id)->markerAt(newMarkers.at(i).time()); + if (oldMarker == CommentedTime()) { + oldMarker = newMarkers.at(i); + oldMarker.setMarkerType(-1); + } + if (newMarkers.count() == 1 && !groupCommand) { + AddMarkerCommand *command = new AddMarkerCommand(this, oldMarker, newMarkers.at(i), id, groupCommand); + m_commandStack->push(command); + } + else if (groupCommand) { + (void) new AddMarkerCommand(this, oldMarker, newMarkers.at(i), id, groupCommand); + } + else { + (void) new AddMarkerCommand(this, oldMarker, newMarkers.at(i), id, subCommand); + } } - AddMarkerCommand *command = new AddMarkerCommand(this, oldMarker, newMarker, id, groupCommand); - if (!groupCommand) m_commandStack->push(command); + if (subCommand) m_commandStack->push(subCommand); } void CustomTrackView::slotDeleteClipMarker(const QString &comment, const QString &id, const GenTime &position) @@ -5388,6 +5404,7 @@ void CustomTrackView::slotLoadClipMarkers(const QString &id) QUndoCommand *command = new QUndoCommand(); command->setText("Load markers"); QString markerText; + QList markersList; foreach(QString line, lines) { markerText.clear(); values = line.split("\t", QString::SkipEmptyParts); @@ -5418,13 +5435,14 @@ void CustomTrackView::slotLoadClipMarkers(const QString &id) // Marker found, add it //TODO: allow user to set a marker category CommentedTime marker1(GenTime(time1), markerText, category); - slotAddClipMarker(id, marker1, command); + markersList << marker1; if (time2 > 0 && time2 != time1) { CommentedTime marker2(GenTime(time2), markerText, category); - slotAddClipMarker(id, marker2, command); + markersList << marker2; } } } + if (!markersList.isEmpty()) slotAddClipMarker(id, markersList, command); if (command->childCount() > 0) m_commandStack->push(command); else delete command; } @@ -7472,7 +7490,7 @@ void CustomTrackView::adjustEffects(ClipItem* item, ItemInfo oldInfo, QUndoComma } -void CustomTrackView::slotGotFilterJobResults(const QString &/*id*/, int startPos, int track, const QString &filter, stringMap filterParams) +void CustomTrackView::slotGotFilterJobResults(const QString &/*id*/, int startPos, int track, const QString &filter, stringMap filterParams, QStringList extra) { ClipItem *clip = getClipItemAt(GenTime(startPos, m_document->fps()), track); if (clip == NULL) { diff --git a/src/customtrackview.h b/src/customtrackview.h index 6ba3bb2a..0c950b54 100644 --- a/src/customtrackview.h +++ b/src/customtrackview.h @@ -234,7 +234,7 @@ public slots: * @param id Id of the marker's clip * @param t Position of the marker * @param c Comment of the marker */ - void slotAddClipMarker(const QString &id, CommentedTime newMarker, QUndoCommand *groupCommand = 0); + void slotAddClipMarker(const QString &id, QList newMarker, QUndoCommand *groupCommand = 0); void slotLoadClipMarkers(const QString &id); void slotSaveClipMarkers(const QString &id); bool addGuide(const GenTime &pos, const QString &comment); @@ -494,7 +494,7 @@ private slots: * @param resetThumbs Should we recreate the timeline thumbnails. */ void slotRefreshThumbs(const QString &id, bool resetThumbs); /** @brief A Filter job producer results. */ - void slotGotFilterJobResults(const QString &id, int startPos, int track, const QString &filter, stringMap filterParams); + void slotGotFilterJobResults(const QString &id, int startPos, int track, const QString &filter, stringMap filterParams, QStringList extra); signals: diff --git a/src/effectstack/collapsibleeffect.cpp b/src/effectstack/collapsibleeffect.cpp index 22e2a02b..5d953f19 100644 --- a/src/effectstack/collapsibleeffect.cpp +++ b/src/effectstack/collapsibleeffect.cpp @@ -455,7 +455,7 @@ void CollapsibleEffect::setupWidget(ItemInfo info, EffectMetaInfo *metaInfo) } connect (m_paramWidget, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int))); - connect(m_paramWidget, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString,QStringList)), this, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString,QStringList))); + connect(m_paramWidget, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QStringList)), this, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QStringList))); connect (this, SIGNAL(syncEffectsPos(int)), m_paramWidget, SIGNAL(syncEffectsPos(int))); connect (m_paramWidget, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int))); diff --git a/src/effectstack/collapsibleeffect.h b/src/effectstack/collapsibleeffect.h index 736cba36..45398f27 100644 --- a/src/effectstack/collapsibleeffect.h +++ b/src/effectstack/collapsibleeffect.h @@ -129,7 +129,7 @@ signals: void checkMonitorPosition(int); void seekTimeline(int); /** @brief Start an MLT filter job on this clip. */ - void startFilterJob(QString filterName, QString filterParams, QString finalFilterName, QString consumer, QString consumerParams, QString properties, QStringList extraParams); + void startFilterJob(QString filterName, QString filterParams, QString finalFilterName, QString consumer, QString consumerParams, QStringList extraParams); /** @brief An effect was reset, trigger param reload. */ void resetEffect(int ix); /** @brief Ask for creation of a group. */ diff --git a/src/effectstack/effectstackview2.cpp b/src/effectstack/effectstackview2.cpp index b82d96f7..f33ecc6c 100644 --- a/src/effectstack/effectstackview2.cpp +++ b/src/effectstack/effectstackview2.cpp @@ -271,7 +271,7 @@ 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,QStringList)), this , SLOT(slotStartFilterJob(QString,QString,QString,QString,QString,QString,QStringList))); + connect(currentEffect, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QStringList)), this , SLOT(slotStartFilterJob(QString,QString,QString,QString,QString,QStringList))); 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))); @@ -643,10 +643,10 @@ void EffectStackView2::slotMoveEffectUp(QList indexes, bool up) else emit changeEffectPosition(m_clipref, -1, indexes, endPos); } -void EffectStackView2::slotStartFilterJob(const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QString&properties, const QStringList &extraParams) +void EffectStackView2::slotStartFilterJob(const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QStringList &extraParams) { if (!m_clipref) return; - emit startFilterJob(m_clipref->info(), m_clipref->clipProducer(), filterName, filterParams, finalFilterName, consumer, consumerParams, properties, extraParams); + emit startFilterJob(m_clipref->info(), m_clipref->clipProducer(), filterName, filterParams, finalFilterName, consumer, consumerParams, extraParams); } void EffectStackView2::slotResetEffect(int ix) diff --git a/src/effectstack/effectstackview2.h b/src/effectstack/effectstackview2.h index 419b07c6..4ce9580f 100644 --- a/src/effectstack/effectstackview2.h +++ b/src/effectstack/effectstackview2.h @@ -167,7 +167,7 @@ private slots: void slotSetCurrentEffect(int ix); /** @brief Triggers a filter job on this clip. */ - void slotStartFilterJob(const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QString&properties,const QStringList &extraParams); + void slotStartFilterJob(const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QStringList &extraParams); /** @brief Reset an effect to its default values. */ void slotResetEffect(int ix); @@ -223,7 +223,7 @@ signals: void updateClipRegion(ClipItem*, int, QString); void displayMessage(const QString&, int); void showComments(bool show); - void startFilterJob(ItemInfo info, const QString &clipId, const QString &filterName, const QString &filterParams, const QString&finalFilterName, const QString &consumer, const QString &consumerParams, const QString &properties,const QStringList &extraParams); + void startFilterJob(ItemInfo info, const QString &clipId, const QString &filterName, const QString &filterParams, const QString&finalFilterName, const QString &consumer, const QString &consumerParams, const QStringList &extraParams); void addEffect(ClipItem*,QDomElement); }; diff --git a/src/effectstack/parametercontainer.cpp b/src/effectstack/parametercontainer.cpp index 8bd9f709..9aaf36c1 100644 --- a/src/effectstack/parametercontainer.cpp +++ b/src/effectstack/parametercontainer.cpp @@ -816,10 +816,9 @@ void ParameterContainer::slotStartFilterJobAction() kDebug()<<"// Setting geometry: "<setWidget(m_effectStack); addDockWidget(Qt::TopDockWidgetArea, m_effectStackDock); - connect(m_effectStack, SIGNAL(startFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QStringList&)), m_projectList, SLOT(slotStartFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QStringList&))); + connect(m_effectStack, SIGNAL(startFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QStringList&)), m_projectList, SLOT(slotStartFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QStringList&))); m_transitionConfigDock = new QDockWidget(i18n("Transition"), this); m_transitionConfigDock->setObjectName("transition"); @@ -2523,7 +2523,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha disconnect(m_activeTimeline->projectView(), SIGNAL(playMonitor()), m_projectMonitor, SLOT(slotPlay())); disconnect(m_activeTimeline->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType))); disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, bool, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool, const int))); - disconnect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), m_activeTimeline->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap))); + disconnect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap,QStringList)), m_activeTimeline->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap,QStringList))); disconnect(m_activeTimeline, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(slotActivateMonitor())); disconnect(m_activeTimeline, SIGNAL(configTrack(int)), this, SLOT(slotConfigTrack(int))); @@ -2542,6 +2542,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha disconnect(m_activeTimeline, SIGNAL(zoneMoved(int, int)), this, SLOT(slotZoneMoved(int, int))); disconnect(m_projectList, SIGNAL(loadingIsOver()), m_activeTimeline->projectView(), SLOT(slotUpdateAllThumbs())); disconnect(m_projectList, SIGNAL(refreshClip(const QString &)), m_activeTimeline->projectView(), SLOT(slotRefreshThumbs(const QString &))); + disconnect(m_projectList, SIGNAL(addMarkers(const QString &, QList )), m_activeTimeline->projectView(), SLOT(slotAddClipMarker(const QString &, QList ))); m_effectStack->clear(); } //m_activeDocument->setRenderer(NULL); @@ -2599,7 +2600,9 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha connect(trackView->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*))); - connect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), trackView->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap))); + connect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap,QStringList)), trackView->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap,QStringList))); + + connect(m_projectList, SIGNAL(addMarkers(const QString &, QList )), trackView->projectView(), SLOT(slotAddClipMarker(const QString &, QList ))); // Effect stack signals connect(m_effectStack, SIGNAL(updateEffect(ClipItem*, int, QDomElement, QDomElement, int,bool)), trackView->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, int, QDomElement, QDomElement, int,bool))); @@ -2839,7 +2842,7 @@ void MainWindow::slotAddClipMarker() QPointer d = new MarkerDialog(clip, marker, m_activeDocument->timecode(), i18n("Add Marker"), this); if (d->exec() == QDialog::Accepted) - m_activeTimeline->projectView()->slotAddClipMarker(id, d->newMarker()); + m_activeTimeline->projectView()->slotAddClipMarker(id, QList () << d->newMarker()); delete d; } @@ -2924,11 +2927,11 @@ void MainWindow::slotEditClipMarker() QPointer d = new MarkerDialog(clip, oldMarker, m_activeDocument->timecode(), i18n("Edit Marker"), this); if (d->exec() == QDialog::Accepted) { - m_activeTimeline->projectView()->slotAddClipMarker(id, d->newMarker()); + m_activeTimeline->projectView()->slotAddClipMarker(id, QList () <newMarker()); if (d->newMarker().time() != pos) { // remove old marker oldMarker.setMarkerType(-1); - m_activeTimeline->projectView()->slotAddClipMarker(id, oldMarker); + m_activeTimeline->projectView()->slotAddClipMarker(id, QList () <timecode().getDisplayTimecode(pos, false), KdenliveSettings::default_marker_type()); - m_activeTimeline->projectView()->slotAddClipMarker(clip->getId(), marker); + m_activeTimeline->projectView()->slotAddClipMarker(clip->getId(), QList () <projectView()->slotAddGuide(false); } @@ -3312,7 +3315,7 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) // any type of clip but a title ClipProperties *dia = new ClipProperties(clip, m_activeDocument->timecode(), m_activeDocument->fps(), this); - connect(dia, SIGNAL(addMarker(const QString &, CommentedTime)), m_activeTimeline->projectView(), SLOT(slotAddClipMarker(const QString &, CommentedTime))); + connect(dia, SIGNAL(addMarkers(const QString &, QList )), m_activeTimeline->projectView(), SLOT(slotAddClipMarker(const QString &, QList ))); connect(dia, SIGNAL(deleteAnalysis(QString,QString)), m_activeTimeline->projectView(), SLOT(slotAddClipExtraData(QString,QString))); connect(m_activeTimeline->projectView(), SIGNAL(updateClipMarkers(DocClipBase *)), dia, SLOT(slotFillMarkersList(DocClipBase *))); connect(m_activeTimeline->projectView(), SIGNAL(updateClipExtraData(DocClipBase *)), dia, SLOT(slotUpdateAnalysisData(DocClipBase *))); @@ -3902,21 +3905,21 @@ void MainWindow::loadClipActions() delete filter; QAction *action=actionMenu->addAction(i18n("Stabilize (vstab)")); action->setData("videostab"); - connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize())); + connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction())); } filter = Mlt::Factory::filter(profile,(char*)"videostab2"); if (filter) { delete filter; QAction *action=actionMenu->addAction(i18n("Stabilize (transcode)")); action->setData("videostab2"); - connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize())); + connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction())); } filter = Mlt::Factory::filter(profile,(char*)"motion_est"); if (filter) { delete filter; QAction *action=actionMenu->addAction(i18n("Automatic scene split")); action->setData("motion_est"); - connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize())); + connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction())); } } @@ -3952,7 +3955,7 @@ void MainWindow::loadTranscoders() } } -void MainWindow::slotStabilize() +void MainWindow::slotStartClipAction() { QString condition,filtername; QStringList ids; diff --git a/src/mainwindow.h b/src/mainwindow.h index dff7177a..c7c6c83b 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -499,7 +499,7 @@ private slots: void slotShowTimeline(bool show); void slotMaximizeCurrent(bool show); void slotTranscode(KUrl::List urls = KUrl::List()); - void slotStabilize(); + void slotStartClipAction(); void slotTranscodeClip(); /** @brief Archive project: creates a copy of the project file with all clips in a new folder. */ void slotArchiveProject(); diff --git a/src/projectlist.cpp b/src/projectlist.cpp index a702d442..319a1524 100644 --- a/src/projectlist.cpp +++ b/src/projectlist.cpp @@ -44,6 +44,7 @@ #include "ui_templateclip_ui.h" #include "ui_cutjobdialog_ui.h" +#include "ui_scenecutdialog_ui.h" #include #include @@ -586,7 +587,7 @@ void ProjectList::editClipSelection(QList list) kDebug() << "Result: " << p.key() << " = " << p.value(); }*/ if (clipList.isEmpty()) { - emit displayMessage(i18n("No available clip selected"), -2); + emit displayMessage(i18n("No available clip selected"), -2); } else emit showClipProperties(clipList, commonproperties); } @@ -2994,9 +2995,9 @@ void ProjectList::slotProcessJobs() MeltJob *jb = static_cast (job); jb->setProducer(currentClip->getProducer(), currentClip->fileURL()); if (jb->isProjectFilter()) - connect(job, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap)), this, SLOT(slotGotFilterJobResults(QString,int, int, QString,stringMap))); + connect(job, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap,QStringList)), this, SLOT(slotGotFilterJobResults(QString,int, int, QString,stringMap,QStringList))); else - connect(job, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap)), this, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap))); + connect(job, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap,QStringList)), this, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap,QStringList))); } job->startJob(); if (job->jobStatus == JOBDONE) { @@ -3421,13 +3422,13 @@ void ProjectList::discardJobs(const QString &id, JOBTYPE type) { } } -void ProjectList::slotStartFilterJob(ItemInfo info, const QString&id, const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QString&properties, const QStringList &extraParams) +void ProjectList::slotStartFilterJob(ItemInfo info, const QString&id, const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QStringList &extraParams) { ProjectItem *item = getItemById(id); if (!item) return; QStringList jobParams; jobParams << QString::number(info.cropStart.frames(m_fps)) << QString::number((info.cropStart + info.cropDuration).frames(m_fps)); - jobParams << QString() << filterName << filterParams << consumer << consumerParams << properties << QString::number(info.startPos.frames(m_fps)) << QString::number(info.track) << finalFilterName; + jobParams << QString() << filterName << filterParams << consumer << consumerParams << QString::number(info.startPos.frames(m_fps)) << QString::number(info.track) << finalFilterName; MeltJob *job = new MeltJob(item->clipType(), id, jobParams, extraParams); if (job->isExclusive() && hasPendingJob(item, job->jobType)) { delete job; @@ -3455,6 +3456,20 @@ void ProjectList::startClipFilterJob(const QString &filterName, const QString &c destination = item->clipUrl().directory(); } if (filterName == "motion_est") { + // Show config dialog + QPointer d = new QDialog(this); + Ui::SceneCutDialog_UI ui; + ui.setupUi(d); + // Set up categories + for (int i = 0; i < 5; ++i) { + ui.marker_type->insertItem(i, i18n("Category %1", i)); + ui.marker_type->setItemData(i, CommentedTime::markerColor(i), Qt::DecorationRole); + } + ui.marker_type->setCurrentIndex(KdenliveSettings::default_marker_type()); + if (d->exec() != QDialog::Accepted) { + delete d; + return; + } // Autosplit filter QStringList jobParams; // Producer params @@ -3463,10 +3478,18 @@ void ProjectList::startClipFilterJob(const QString &filterName, const QString &c jobParams << filterName << "bounding=\"25%x25%:25%x25\" shot_change_list=0"; // Consumer jobParams << "null" << "all=1 terminate_on_pause=1 real_time=-1"; - // Keys - jobParams << "shot_change_list"; QStringList extraParams; + extraParams << "key:shot_change_list"; extraParams << "projecttreefilter"; + if (ui.add_markers->isChecked()) { + // We want to create markers + extraParams << QString("addmarkers:%1").arg(ui.marker_type->currentIndex()); + } + if (ui.cut_scenes->isChecked()) { + // We want to cut scenes + extraParams << "cutscenes"; + } + processClipJob(ids, QString(), false, jobParams, i18n("Auto split"), extraParams); } else { @@ -3574,15 +3597,37 @@ void ProjectList::slotClosePopup() m_errorLog.clear(); } -void ProjectList::slotGotFilterJobResults(QString id, int , int , QString filter, stringMap results) +void ProjectList::slotGotFilterJobResults(QString id, int , int , QString filter, stringMap results, QStringList extra) { - if (filter == "motion_est") { - // Autosplit filter, add sub zones - QStringList cuts = results.value("shot_change_list").split(';', QString::SkipEmptyParts); + ProjectItem *clip = getItemById(id); + if (!clip) return; + // Check for return value + QString returnKey; + int markersType = -1; + for (int i = 0; i < extra.count(); i++) { + if (extra.at(i).startsWith("key:")) + returnKey = extra.at(i).section(':', 1); + if (extra.at(i).startsWith("addmarkers:")) { + markersType = extra.at(i).section(':', 1).toInt(); + } + } + if (returnKey.isEmpty()) { + emit displayMessage(i18n("No data returned from clip analysis"), 2); + return; + } + QStringList returnData = results.value(returnKey).split(';', QString::SkipEmptyParts); + if (returnData.isEmpty()) { + emit displayMessage(i18n("No data returned from clip analysis"), 2); + return; + } + bool dataProcessed = false; + if (extra.contains("cutscenes")) { + // Check if we want to cut scenes from returned data + dataProcessed = true; int cutPos = 0; QUndoCommand *command = new QUndoCommand(); command->setText(i18n("Auto Split Clip")); - foreach (QString pos, cuts) { + foreach (QString pos, returnData) { if (!pos.contains("=")) continue; int newPos = pos.section("=", 0, 0).toInt(); // Don't use scenes shorter than 1 second @@ -3594,15 +3639,32 @@ void ProjectList::slotGotFilterJobResults(QString id, int , int , QString filter delete command; else m_commandStack->push(command); } - else if (filter.startsWith("autotrack_rectangle")) { - QString cuts = results.value("motion_vector_list"); - ProjectItem *clip = getItemById(id); - if (clip) { - clip->referencedClip()->setAnalysisData(i18n("Motion vectors"), cuts); - emit updateAnalysisData(clip->referencedClip()); + if (markersType >= 0) { + // Add markers from returned data + dataProcessed = true; + int cutPos = 0; + QUndoCommand *command = new QUndoCommand(); + command->setText(i18n("Add Markers")); + QList markersList; + int index = 1; + foreach (QString pos, returnData) { + if (!pos.contains("=")) continue; + int newPos = pos.section("=", 0, 0).toInt(); + // Don't use scenes shorter than 1 second + if (newPos - cutPos < 24) continue; + CommentedTime m(GenTime(newPos, m_fps), QString::number(index), markersType); + markersList << m; + index++; + cutPos = newPos; } + emit addMarkers(id, markersList); + } + if (!dataProcessed || extra.contains("storedata")) { + // Store returned data as clip extra data + + clip->referencedClip()->setAnalysisData(i18n("Motion vectors"), results.value(returnKey)); + emit updateAnalysisData(clip->referencedClip()); } - } #include "projectlist.moc" diff --git a/src/projectlist.h b/src/projectlist.h index 9f3d91e8..7019595c 100644 --- a/src/projectlist.h +++ b/src/projectlist.h @@ -330,7 +330,7 @@ public slots: /** @brief Start transcoding selected clips. */ void slotTranscodeClipJob(const QString &condition, QString params, QString desc); /** @brief Start an MLT process job. */ - void slotStartFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QStringList&); + void slotStartFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QStringList&); private: @@ -491,7 +491,7 @@ private slots: /** @brief close warning info passive popup. */ void slotClosePopup(); /** @brief process clip job result. */ - void slotGotFilterJobResults(QString ,int , int, QString, stringMap); + void slotGotFilterJobResults(QString ,int , int, QString, stringMap, QStringList); signals: void clipSelected(DocClipBase *, QPoint zone = QPoint(), bool forceUpdate = false); @@ -524,9 +524,10 @@ signals: void gotProxy(const QString); void checkJobProcess(); /** @brief A Filter Job produced results, send them back to the clip. */ - void gotFilterJobResults(const QString &id, int startPos, int track, const QString &filterName, stringMap params); + void gotFilterJobResults(const QString &id, int startPos, int track, const QString &filterName, stringMap params, QStringList extre); void pauseMonitor(); void updateAnalysisData(DocClipBase *); + void addMarkers(const QString &, QList ); }; #endif diff --git a/src/projecttree/meltjob.cpp b/src/projecttree/meltjob.cpp index 1e24caff..ed170fdb 100644 --- a/src/projecttree/meltjob.cpp +++ b/src/projecttree/meltjob.cpp @@ -76,8 +76,6 @@ void MeltJob::startJob() QString consumerParams = m_params.takeFirst(); // optional params - QString properties; - if (!m_params.isEmpty()) properties = m_params.takeFirst(); int startPos = -1; if (!m_params.isEmpty()) startPos = m_params.takeFirst().toInt(); int track = -1; @@ -86,6 +84,15 @@ void MeltJob::startJob() if (!m_params.isEmpty()) finalFilter = m_params.takeFirst(); else finalFilter = filter; + // Check if we want to return analysis data + QString properties; + for (int i = 0; i < m_extra.count(); i++) { + if (m_extra.at(i).startsWith("key:")) { + properties = m_extra.at(i).section(':', 1); + break; + } + } + if (out != -1 && out <= in) { m_errorMessage.append(i18n("Clip zone undefined (%1 - %2).", in, out)); @@ -173,7 +180,7 @@ void MeltJob::startJob() QString value = mltFilter.get(key.toUtf8().constData()); jobResults.insert(key, value); } - if (!jobResults.isEmpty()) emit gotFilterJobResults(m_clipId, startPos, track, finalFilter, jobResults); + if (!jobResults.isEmpty() && jobStatus != JOBABORTED) emit gotFilterJobResults(m_clipId, startPos, track, finalFilter, jobResults, m_extra); setStatus(JOBDONE); delete m_consumer; delete prod; diff --git a/src/projecttree/meltjob.h b/src/projecttree/meltjob.h index 63a34d24..d3736503 100644 --- a/src/projecttree/meltjob.h +++ b/src/projecttree/meltjob.h @@ -65,7 +65,7 @@ private: QStringList m_extra; signals: - void gotFilterJobResults(const QString &id, int startPos, int track, const QString &filterName, stringMap params); + void gotFilterJobResults(const QString &id, int startPos, int track, const QString &filterName, stringMap params, QStringList extraParam); }; #endif diff --git a/src/widgets/scenecutdialog_ui.ui b/src/widgets/scenecutdialog_ui.ui new file mode 100644 index 00000000..462ff597 --- /dev/null +++ b/src/widgets/scenecutdialog_ui.ui @@ -0,0 +1,97 @@ + + + SceneCutDialog_UI + + + + 0 + 0 + 352 + 90 + + + + Scene Cut + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 218 + 2 + + + + + + + + Add clip markers + + + true + + + + + + + + + + Cut scenes + + + + + + + + + buttonBox + accepted() + SceneCutDialog_UI + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SceneCutDialog_UI + reject() + + + 316 + 260 + + + 286 + 274 + + + + + -- 2.39.2