<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<gui name="kdenlive" version="69">
+<gui name="kdenlive" version="72">
<ToolBar name="extraToolBar" >
<text>Extra Toolbar</text>
<Action name="project_render" />
<Action name="download_resource" />
<Menu name="extract_audio" ><text>Extract Audio</text>
</Menu>
- <Menu name="stabilize" ><text>Stabilize</text>
+ <Menu name="clip_actions" ><text>Clip Jobs</text>
</Menu>
<Menu name="transcoders" ><text>Transcode</text>
</Menu>
loadPlugins();
loadTranscoders();
- loadStabilize();
+ loadClipActions();
m_projectMonitor->setupMenu(static_cast<QMenu*>(factory()->container("monitor_go", this)), m_playZone, m_loopZone, NULL, m_loopClip);
m_clipMonitor->setupMenu(static_cast<QMenu*>(factory()->container("monitor_go", this)), m_playZone, m_loopZone, static_cast<QMenu*>(factory()->container("marker_menu", this)));
menus.insert("addMenu",static_cast<QMenu*>(factory()->container("generators", this)));
menus.insert("extractAudioMenu",static_cast<QMenu*>(factory()->container("extract_audio", this)));
menus.insert("transcodeMenu",static_cast<QMenu*>(factory()->container("transcoders", this)));
- menus.insert("stabilizeMenu",static_cast<QMenu*>(factory()->container("stabilize", this)));
+ menus.insert("clipActionsMenu",static_cast<QMenu*>(factory()->container("clip_actions", this)));
menus.insert("inTimelineMenu",clipInTimeline);
m_projectList->setupGeneratorMenu(menus);
// Update list of transcoding profiles
loadTranscoders();
- loadStabilize();
+ loadClipActions();
#ifdef USE_JOGSHUTTLE
activateShuttleDevice();
#endif
kDebug() << "CURRENT WIDGET: " << par->objectName();
}
-void MainWindow::loadStabilize()
+void MainWindow::loadClipActions()
{
- QMenu* stabMenu= static_cast<QMenu*>(factory()->container("stabilize", this));
- if (stabMenu){
- stabMenu->clear();
+ QMenu* actionMenu= static_cast<QMenu*>(factory()->container("clip_actions", this));
+ if (actionMenu){
+ actionMenu->clear();
Mlt::Profile profile;
- if (Mlt::Factory::filter(profile,(char*)"videostab")){
- QAction *action=stabMenu->addAction("Videostab (vstab)");
+ Mlt::Filter *filter = Mlt::Factory::filter(profile,(char*)"videostab");
+ if (filter) {
+ delete filter;
+ QAction *action=actionMenu->addAction("Videostab (vstab)");
action->setData("videostab");
connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize()));
}
- if (Mlt::Factory::filter(profile,(char*)"videostab2")){
- QAction *action=stabMenu->addAction("Videostab (transcode)");
+ filter = Mlt::Factory::filter(profile,(char*)"videostab2");
+ if (filter) {
+ delete filter;
+ QAction *action=actionMenu->addAction("Videostab (transcode)");
action->setData("videostab2");
connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize()));
}
+ filter = Mlt::Factory::filter(profile,(char*)"motion_est");
+ if (filter) {
+ delete filter;
+ QAction *action=actionMenu->addAction("Automatic scene split");
+ action->setData("motion_est");
+ connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize()));
+ }
}
-
}
void MainWindow::loadTranscoders()
QStringList m_pluginFileNames;
QByteArray m_timelineState;
void loadTranscoders();
- void loadStabilize();
+ void loadClipActions();
QPixmap createSchemePreviewIcon(const KSharedConfigPtr &config);
/** @brief Checks that the Kdenlive mime type is correctly installed.
transcodeMenu->setEnabled(false);
m_transcodeAction = transcodeMenu;
}
- if (menus.contains("stabilizeMenu") && menus.value("stabilizeMenu") ){
- QMenu* stabilizeMenu=menus.value("stabilizeMenu");
+ if (menus.contains("clipActionsMenu") && menus.value("clipActionsMenu") ){
+ QMenu* stabilizeMenu=menus.value("clipActionsMenu");
m_menu->addMenu(stabilizeMenu);
if (stabilizeMenu->isEmpty())
stabilizeMenu->setEnabled(false);
void ProjectList::adjustStabilizeActions(ProjectItem *clip) const
{
- if (clip == NULL || clip->type() != PROJECTCLIPTYPE || clip->clipType() == COLOR || clip->clipType() == TEXT || clip->clipType() == PLAYLIST || clip->clipType() == SLIDESHOW) {
+ if (clip == NULL || clip->type() != PROJECTCLIPTYPE || clip->clipType() == COLOR || clip->clipType() == TEXT || clip->clipType() == SLIDESHOW) {
m_stabilizeAction->setEnabled(false);
return;
}
}
connect(job, SIGNAL(jobProgress(QString, int, int)), this, SIGNAL(processLog(QString, int, int)));
connect(job, SIGNAL(cancelRunningJob(const QString, stringMap)), this, SIGNAL(cancelRunningJob(const QString, stringMap)));
- connect(job, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap)), this, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap)));
if (job->jobType == MLTJOB) {
MeltJob *jb = static_cast<MeltJob *> (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)));
+ else
+ connect(job, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap)), this, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap)));
}
job->startJob();
if (job->jobStatus == JOBDONE) {
else {
destination = item->clipUrl().directory();
}
- QPointer<ClipStabilize> d = new ClipStabilize(destination, ids.count(), filterName);
- if (d->exec() == QDialog::Accepted) {
- processClipJob(ids, d->destination(), d->autoAddClip(), d->params(), d->desc());
+ if (filterName == "motion_est") {
+ // Autosplit filter
+ QStringList jobParams;
+ // Producer params
+ jobParams << QString();
+ // Filter params, use a smaller region of the image to speed up operation
+ jobParams << filterName << "bounding=\"25%x25%:25%x25";
+ // Consumer
+ jobParams << "null" << "all=1 terminate_on_pause=1 real_time=-1";
+ // Keys
+ jobParams << "scene_cuts";
+ QStringList extraParams;
+ extraParams << "projecttreefilter" << "project_profile";
+ processClipJob(ids, QString(), false, jobParams, i18n("Auto split"), extraParams);
+ }
+ else {
+ QPointer<ClipStabilize> d = new ClipStabilize(destination, ids.count(), filterName);
+ if (d->exec() == QDialog::Accepted) {
+ processClipJob(ids, d->destination(), d->autoAddClip(), d->params(), d->desc());
+ }
+ delete d;
}
- delete d;
}
-void ProjectList::processClipJob(QStringList ids, const QString&destination, bool autoAdd, QStringList jobParams, const QString &description)
+void ProjectList::processClipJob(QStringList ids, const QString&destination, bool autoAdd, QStringList jobParams, const QString &description, QStringList extraParams)
{
QStringList preParams;
// in and out
}
jobArgs << jobParams;
- MeltJob *job = new MeltJob(item->clipType(), id, jobArgs);
+ MeltJob *job = new MeltJob(item->clipType(), id, jobArgs, extraParams);
if (autoAdd) {
job->setAddClipToProject(true);
kDebug()<<"// ADDING TRUE";
}
else kDebug()<<"// ADDING FALSE!!!";
+
if (job->isExclusive() && hasPendingJob(item, job->jobType)) {
delete job;
return;
m_errorLog.clear();
}
+void ProjectList::slotGotFilterJobResults(QString id, int , int , QString filter, stringMap results)
+{
+ if (filter == "motion_est") {
+ // Autosplit filter, add sub zones
+ QStringList cuts = results.value("scene_cuts").split(':', QString::SkipEmptyParts);
+ int cutPos = 0;
+ QUndoCommand *command = new QUndoCommand();
+ command->setText(i18n("Auto Split Clip"));
+ foreach (const QString &pos, cuts) {
+ int newPos = pos.toInt();
+ kDebug()<<"// SCENE CUT: "<<cutPos<<" - "<<newPos;
+ if (newPos - cutPos < 24) continue;
+ (void) new AddClipCutCommand(this, id, cutPos, newPos, QString(), true, false, command);
+ cutPos = newPos;
+ }
+ if (command->childCount() == 0)
+ delete command;
+ else m_commandStack->push(command);
+ }
+
+}
+
#include "projectlist.moc"
/** @brief Get the list of job names for current clip. */
QStringList getPendingJobs(const QString &id);
/** @brief Start an MLT process job. */
- void processClipJob(QStringList ids, const QString&destination, bool autoAdd, QStringList jobParams, const QString &description);
+ void processClipJob(QStringList ids, const QString&destination, bool autoAdd, QStringList jobParams, const QString &description, QStringList extraParams = QStringList());
private slots:
void slotClipSelected();
void slotResetInfoMessage();
/** @brief close warning info passive popup. */
void slotClosePopup();
+ /** @brief process clip job result. */
+ void slotGotFilterJobResults(QString ,int , int, QString, stringMap);
signals:
void clipSelected(DocClipBase *, QPoint zone = QPoint(), bool forceUpdate = false);
signals:
void jobProgress(QString, int, int);
void cancelRunningJob(const QString, stringMap);
- void gotFilterJobResults(const QString &id, int startPos, int track, const QString &filterName, stringMap params);
};
self->emitFrameNumber();
}
-MeltJob::MeltJob(CLIPTYPE cType, const QString &id, QStringList parameters) : AbstractClipJob(MLTJOB, cType, id, parameters),
+MeltJob::MeltJob(CLIPTYPE cType, const QString &id, QStringList parameters, QStringList extraParams) : AbstractClipJob(MLTJOB, cType, id, parameters),
addClipToProject(0),
m_producer(NULL),
m_profile(NULL),
m_consumer(NULL),
m_showFrameEvent(NULL),
- m_length(0)
+ m_length(0),
+ m_extra(extraParams)
{
jobStatus = JOBWAITING;
m_params = parameters;
QString filter = m_params.takeFirst();
QString filterParams = m_params.takeFirst();
QString consumer = m_params.takeFirst();
- kDebug()<<"consumer: "<<consumer;
if (consumer.contains(':')) m_dest = consumer.section(':', 1);
QString consumerParams = m_params.takeFirst();
if (!m_params.isEmpty()) finalFilter = m_params.takeFirst();
else finalFilter = filter;
+
if (out != -1 && out <= in) {
m_errorMessage.append(i18n("Clip zone undefined (%1 - %2).", in, out));
setStatus(JOBCRASHED);
return;
}
Mlt::Producer *prod ;
- m_profile = new Mlt::Profile;
- m_profile->set_explicit(false);
+ if (m_extra.contains("project_profile")) {
+ m_profile = new Mlt::Profile(KdenliveSettings::current_profile().toUtf8().constData());
+ }
+ else {
+ m_profile = new Mlt::Profile;
+ m_profile->set_explicit(false);
+ }
if (out == -1) {
prod = new Mlt::Producer(*m_profile, m_url.toUtf8().constData());
}
prod = tmp->cut(in, out);
delete tmp;
}
- m_profile->from_producer(*prod);
- m_profile->set_explicit(true);
+ if (!m_extra.contains("project_profile")) {
+ m_profile->from_producer(*prod);
+ m_profile->set_explicit(true);
+ }
QStringList list = producerParams.split(' ', QString::SkipEmptyParts);
foreach(const QString &data, list) {
if (data.contains('=')) {
//m_consumer->set("eof", "pause" );
m_consumer->set("real_time", -KdenliveSettings::mltthreads() );
+
list = consumerParams.split(' ', QString::SkipEmptyParts);
foreach(const QString &data, list) {
if (data.contains('=')) {
}
}
+bool MeltJob::isProjectFilter() const
+{
+ return m_extra.contains("projecttreefilter");
+}
+
+
+
Q_OBJECT
public:
- MeltJob(CLIPTYPE cType, const QString &id, QStringList parameters);
+ MeltJob(CLIPTYPE cType, const QString &id, QStringList parameters, QStringList extraParams = QStringList());
virtual ~ MeltJob();
const QString destination() const;
void startJob();
const QString statusMessage();
void setProducer(Mlt::Producer *producer, KUrl url);
void emitFrameNumber();
+ /** Make the job work on a project tree clip. */
+ bool isProjectFilter() const;
private:
Mlt::Producer *m_producer;
QString m_dest;
QString m_url;
int m_length;
+ QStringList m_extra;
+
+signals:
+ void gotFilterJobResults(const QString &id, int startPos, int track, const QString &filterName, stringMap params);
};
#endif