+void ProjectList::startClipFilterJob(const QString &filterName, const QString &condition)
+{
+ QMap <QString, QString> ids = getConditionalIds(condition);
+ QStringList destination;
+ QMap<QString, QString>::const_iterator first = ids.constBegin();
+ if (first == ids.constEnd()) {
+ emit displayMessage(i18n("Cannot find clip to process filter %1", filterName), -2, ErrorMessage);
+ return;
+ }
+ ProjectItem *item = getItemById(first.key());
+ if (!item) {
+ emit displayMessage(i18n("Cannot find clip to process filter %1", filterName), -2, ErrorMessage);
+ return;
+ }
+ if (ids.count() == 1) {
+ destination << item->clipUrl().path();
+ }
+ else {
+ destination = ids.values();
+ }
+ if (filterName == "framebuffer") {
+ Mlt::Profile profile;
+ QStringList keys = ids.keys();
+ int ix = 0;
+ foreach(const QString &url, destination) {
+ QString prodstring = QString("framebuffer:" + url + "?-1");
+ Mlt::Producer *reversed = new Mlt::Producer(profile, prodstring.toUtf8().constData());
+ if (!reversed || !reversed->is_valid()) {
+ emit displayMessage(i18n("Cannot reverse clip"), -2, ErrorMessage);
+ continue;
+ }
+ QString dest = url + ".mlt";
+ if (QFile::exists(dest)) {
+ if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", dest)) == KMessageBox::No) continue;
+ }
+ Mlt::Consumer *cons = new Mlt::Consumer(profile, "xml", dest.toUtf8().constData());
+ if (cons == NULL || !cons->is_valid()) {
+ emit displayMessage(i18n("Cannot render reversed clip"), -2, ErrorMessage);
+ continue;
+ }
+ Mlt::Playlist list;
+ list.insert_at(0, reversed, 0);
+ delete reversed;
+ cons->connect(list);
+ cons->run();
+ delete cons;
+ QString groupId;
+ QString groupName;
+ DocClipBase *base = m_doc->clipManager()->getClipById(keys.at(ix));
+ if (base) {
+ groupId = base->getProperty("groupid");
+ groupName = base->getProperty("groupname");
+ }
+ emit addClip(dest, groupId, groupName);
+ ix++;
+ }
+ return;
+ }
+
+ if (filterName == "motion_est") {
+ // Show config dialog
+ QPointer<QDialog> 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
+ jobParams << QString();
+ // Filter params, use a smaller region of the image to speed up operation
+ // In fact, it's faster to rescale whole image than using part of it (bounding=\"25%x25%:15%x15\")
+ jobParams << filterName << "shot_change_list=0 denoise=0";
+ // Consumer
+ jobParams << "null" << "all=1 terminate_on_pause=1 real_time=-1 rescale=nearest deinterlace_method=onefield top_field_first=-1";
+ QMap <QString, QString> extraParams;
+ extraParams.insert("key", "shot_change_list");
+ extraParams.insert("projecttreefilter", "1");
+ QString keyword("%count");
+ extraParams.insert("resultmessage", i18n("Found %1 scenes.", keyword));
+ extraParams.insert("resize_profile", "160");
+ if (ui.store_data->isChecked()) {
+ // We want to save result as clip metadata
+ extraParams.insert("storedata", "1");
+ }
+ if (ui.zone_only->isChecked()) {
+ // We want to analyze only clip zone
+ extraParams.insert("zoneonly", "1");
+ }
+ if (ui.add_markers->isChecked()) {
+ // We want to create markers
+ extraParams.insert("addmarkers", QString::number(ui.marker_type->currentIndex()));
+ }
+ if (ui.cut_scenes->isChecked()) {
+ // We want to cut scenes
+ extraParams.insert("cutscenes", "1");
+ }
+ delete d;
+ processClipJob(ids.keys(), QString(), false, jobParams, i18n("Auto split"), extraParams);
+ }
+ else {
+ QPointer<ClipStabilize> d = new ClipStabilize(destination, filterName);
+ if (d->exec() == QDialog::Accepted) {
+ QMap <QString, QString> extraParams;
+ extraParams.insert("producer_profile", "1");
+ processClipJob(ids.keys(), d->destination(), d->autoAddClip(), d->params(), d->desc(), extraParams);
+ }
+ delete d;
+ }
+}
+
+void ProjectList::processClipJob(QStringList ids, const QString&destination, bool autoAdd, QStringList jobParams, const QString &description, QMap <QString, QString> extraParams)
+{
+ QStringList preParams;
+ // in and out
+ preParams << QString::number(0) << QString::number(-1);
+ // producer params
+ preParams << jobParams.takeFirst();
+ // filter name
+ preParams << jobParams.takeFirst();
+ // filter params
+ preParams << jobParams.takeFirst();
+ // consumer
+ QString consumer = jobParams.takeFirst();
+
+ foreach(const QString&id, ids) {
+ ProjectItem *item = getItemById(id);
+ if (!item) continue;
+ QStringList jobArgs;
+ if (extraParams.contains("zoneonly")) {
+ // Analyse clip zone only, remove in / out and replace with zone
+ preParams.takeFirst();
+ preParams.takeFirst();
+ QPoint zone = item->referencedClip()->zone();
+ jobArgs << QString::number(zone.x()) << QString::number(zone.y());
+ }
+ jobArgs << preParams;
+ if (ids.count() == 1) {
+ jobArgs << consumer + ':' + destination;
+ }
+ else {
+ jobArgs << consumer + ':' + destination + item->clipUrl().fileName() + ".mlt";
+ }
+ jobArgs << jobParams;
+
+ 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;
+ }
+ job->description = description;
+ m_jobList.append(job);
+ setJobStatus(item, job->jobType, JobWaiting, 0, job->statusMessage());
+ slotCheckJobProcess();
+ }
+}
+
+