void BinController::duplicateFilters(Mlt::Producer original, Mlt::Producer clone) { Mlt::Service clipService(original.get_service()); Mlt::Service dupService(clone.get_service()); //delete original; //delete clone; int ct = 0; Mlt::Filter *filter = clipService.filter(ct); while (filter) { // Only duplicate Kdenlive filters, and skip the fade in effects //fprintf(stderr, "CHKNG FILTER: %s\n", filter->get("kdenlive_id")); if (filter->is_valid()/* && strcmp(filter->get("kdenlive_id"), "") && strcmp(filter->get("kdenlive_id"), "fadein") && strcmp(filter->get("kdenlive_id"), "fade_from_black")*/) { // looks like there is no easy way to duplicate a filter, // so we will create a new one and duplicate its properties Mlt::Filter *dup = new Mlt::Filter(*original.profile(), filter->get("mlt_service")); if (dup && dup->is_valid()) { Mlt::Properties entries(filter->get_properties()); for (int i = 0; i < entries.count(); ++i) { dup->set(entries.get_name(i), entries.get(i)); } dupService.attach(*dup); } } ct++; filter = clipService.filter(ct); } }
QVariant AttachedFiltersModel::data(const QModelIndex &index, int role) const { if ( !m_producer || !m_producer->is_valid() || index.row() >= m_producer->filter_count()) return QVariant(); switch (role ) { case Qt::DisplayRole: { QVariant result; Mlt::Filter* filter = filterForRow(index.row()); if (filter && filter->is_valid()) { // Relabel by QML UI QmlMetadata* meta = MAIN.filtersDock()->qmlMetadataForService(filter); if (meta) result = meta->name(); // Fallback is raw mlt_service name else if (filter->get("mlt_service")) result = QString::fromUtf8(filter->get("mlt_service")); } // Relabel for widgets UIs if (result == "movit.blur" || result == "boxblur") result = tr("Blur"); else if (result == "movit.lift_gamma_gain" || result == "frei0r.coloradj_RGB") result = tr("Color Grading"); else if (result == "crop") result = tr("Crop"); else if (result == "movit.glow" || result == "frei0r.glow") result = tr("Glow"); else if (result == "movit.mirror" || result == "mirror") result = tr("Mirror"); else if (result == "webvfx") result = tr("Overlay HTML"); else if (result == "movit.sharpen" || result == "frei0r.sharpness") result = tr("Sharpen"); else if (result == "movit.white_balance" || result == "frei0r.colgate") result = tr("White Balance"); else if (result == "sox" && filter->get("use_peak")) result = tr("Normalize"); delete filter; return result; } case Qt::CheckStateRole: { Mlt::Filter* filter = filterForRow(index.row()); QVariant result = Qt::Unchecked; if (filter && filter->is_valid() && !filter->get_int("disable")) result = Qt::Checked; delete filter; return result; } break; default: break; } return QVariant(); }
QVariant AttachedFiltersModel::data(const QModelIndex &index, int role) const { if ( !m_producer || !m_producer->is_valid() || index.row() >= m_producer->filter_count()) return QVariant(); switch (role ) { case Qt::DisplayRole: { QVariant result; const QmlMetadata* meta = m_metaList[index.row()]; if (meta) { result = meta->name(); } else { // Fallback is raw mlt_service name Mlt::Filter* filter = getFilter(index.row()); if (filter && filter->is_valid() && filter->get("mlt_service")) { result = QString::fromUtf8(filter->get("mlt_service")); } delete filter; } return result; } case Qt::CheckStateRole: { Mlt::Filter* filter = getFilter(index.row()); QVariant result = Qt::Unchecked; if (filter && filter->is_valid() && !filter->get_int("disable")) result = Qt::Checked; delete filter; return result; } break; case TypeDisplayRole: { QVariant result; const QmlMetadata* meta = m_metaList[index.row()]; if (meta && meta->isAudio()) { result = tr("Audio"); } else if (meta && meta->needsGPU()) { result = tr("GPU"); } else { result = tr("Video"); } return result; } break; default: break; } return QVariant(); }
void AttachedFiltersModel::add(QmlMetadata* meta) { if (!meta->allowMultiple()) { for (int i = 0; i < m_metaList.count(); i++) { const QmlMetadata* attachedMeta = m_metaList[i]; if (attachedMeta && meta->uniqueId() == attachedMeta->uniqueId()) { emit duplicateAddFailed(i); return; } } } int insertIndex = -1; int mltIndex = -1; Mlt::Filter* filter = new Mlt::Filter(MLT.profile(), meta->mlt_service().toUtf8().constData()); if (filter->is_valid()) { if (!meta->objectName().isEmpty()) filter->set(kShotcutFilterProperty, meta->objectName().toUtf8().constData()); // Put the filter after the last filter that is greater than or equal // in sort order. insertIndex = 0; for (int i = m_metaList.count() - 1; i >= 0; i--) { if (!sortIsLess(m_metaList[i], meta)) { insertIndex = i + 1; break; } } // Calculate the MLT index for the new filter. if (m_mltIndexMap.count() == 0) { mltIndex = m_producer->filter_count(); } else if (insertIndex == 0) { mltIndex = m_mltIndexMap[0]; } else { mltIndex = m_mltIndexMap[insertIndex -1] + 1; } beginInsertRows(QModelIndex(), insertIndex, insertIndex); if (MLT.isSeekable()) MLT.pause(); m_event->block(); m_producer->attach(*filter); m_producer->move_filter(m_producer->filter_count() - 1, mltIndex); m_event->unblock(); // Adjust MLT index map for indices that just changed. for (int i = 0; i < m_mltIndexMap.count(); i++) { if (m_mltIndexMap[i] >= mltIndex) { m_mltIndexMap[i] = m_mltIndexMap[i] + 1; } } m_mltIndexMap.insert(insertIndex, mltIndex); m_metaList.insert(insertIndex, meta); endInsertRows(); emit changed(); } else qWarning() << "Failed to load filter" << meta->mlt_service(); delete filter; }
void AttachedFiltersModel::remove(int row) { Mlt::Filter* filter = filterForRow(row); if (filter && filter->is_valid()) { beginRemoveRows(QModelIndex(), row, row); MLT.pause(); m_producer->detach(*filter); m_rows--; endRemoveRows(); emit changed(); } delete filter; }
QVariant AttachedFiltersModel::data(const QModelIndex &index, int role) const { if ( !m_producer || !m_producer->is_valid() || index.row() >= m_producer->filter_count()) return QVariant(); switch (role ) { case Qt::DisplayRole: { QVariant result; Mlt::Filter* filter = filterForRow(index.row()); if (filter && filter->is_valid()) { // Relabel by QML UI QmlMetadata* meta = MAIN.filtersDock()->qmlMetadataForService(filter); if (meta) result = meta->name(); // Fallback is raw mlt_service name else if (filter->get("mlt_service")) result = QString::fromUtf8(filter->get("mlt_service")); } // Relabel for widgets UIs if (result == "movit.mirror" || result == "mirror") result = tr("Mirror"); delete filter; return result; } case Qt::CheckStateRole: { Mlt::Filter* filter = filterForRow(index.row()); QVariant result = Qt::Unchecked; if (filter && filter->is_valid() && !filter->get_int("disable")) result = Qt::Checked; delete filter; return result; } break; default: break; } return QVariant(); }
bool AttachedFiltersModel::setData(const QModelIndex& index, const QVariant& , int role) { if (role == Qt::CheckStateRole) { Mlt::Filter* filter = getFilter(index.row()); if (filter && filter->is_valid()) { filter->set("disable", !filter->get_int("disable")); emit changed(); emit dataChanged(createIndex(index.row(), 0), createIndex(index.row(), 0)); } delete filter; return true; } return false; }
void AttachedFiltersModel::calculateRows() { m_rows =-0; if (MLT.isPlaylist()) return; if (m_producer && m_producer->is_valid()) { int n = m_producer->filter_count(); while (n--) { Mlt::Filter* filter = m_producer->filter(n); if (filter && filter->is_valid() && !filter->get_int("_loader")) m_rows++; delete filter; } } }
bool AttachedFiltersModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (role == Qt::CheckStateRole) { Mlt::Filter* filter = filterForRow(index.row()); if (filter && filter->is_valid()) { double speed = MLT.producer()->get_speed(); MLT.pause(); filter->set("disable", !filter->get_int("disable")); MLT.play(speed); emit changed(); emit dataChanged(createIndex(index.row(), 0), createIndex(index.row(), 0)); } delete filter; return true; } return false; }
Mlt::Filter *AttachedFiltersModel::add(const QString& mlt_service, const QString& shotcutName) { Mlt::Filter* filter = new Mlt::Filter(MLT.profile(), mlt_service.toUtf8().constData()); if (filter->is_valid()) { if (!shotcutName.isEmpty()) filter->set("shotcut:filter", shotcutName.toUtf8().constData()); int count = rowCount(); beginInsertRows(QModelIndex(), count, count); MLT.pause(); m_producer->attach(*filter); m_rows++; endInsertRows(); emit changed(); } else qWarning() << "Failed to load filter" << mlt_service; return filter; }
void AttachedFiltersModel::reset(Mlt::Producer* producer) { beginResetModel(); m_event.reset(); if (producer && producer->is_valid()) m_producer.reset(new Mlt::Producer(producer)); else if (MLT.isClip()) m_producer.reset(new Mlt::Producer(MLT.producer())); else m_producer.reset(); m_metaList.clear(); m_mltIndexMap.clear(); if (m_producer && m_producer->is_valid()) { Mlt::Event* event = m_producer->listen("service-changed", this, (mlt_listener)AttachedFiltersModel::producerChanged); m_event.reset(event); int count = m_producer->filter_count(); for (int i = 0; i < count; i++) { Mlt::Filter* filter = m_producer->filter(i); if (filter && filter->is_valid() && !filter->get_int("_loader")) { QmlMetadata* newMeta = MAIN.filterController()->metadataForService(filter); int newIndex = m_metaList.count(); for (int j = newIndex - 1; j >= 0; j--) { const QmlMetadata* prevMeta = m_metaList[j]; if (sortIsLess(prevMeta, newMeta)) { newIndex = j; } else { break; } } m_metaList.insert(newIndex, newMeta); m_mltIndexMap.insert(newIndex, i); } delete filter; } } endResetModel(); emit trackTitleChanged(); emit isProducerSelectedChanged(); emit readyChanged(); }
int AttachedFiltersModel::indexForRow(int row) const { int result = -1; if (m_producer && m_producer->is_valid()) { int count = m_producer->filter_count(); int j = 0; for (int i = 0; i < count; i++) { Mlt::Filter* filter = m_producer->filter(i); if (filter && filter->is_valid() && !filter->get_int("_loader")) { if (j == row) { result = i; break; } j++; } delete filter; } } return result; }
bool EffectManager::doAddFilter(EffectsParameterList params, int duration) { // create filter QString tag = params.paramValue(QStringLiteral("tag")); QLocale locale; ////qDebug() << " / / INSERTING EFFECT: " << tag << ", REGI: " << region; QString kfr = params.paramValue(QStringLiteral("keyframes")); if (!kfr.isEmpty()) { QStringList keyFrames = kfr.split(';', QString::SkipEmptyParts); char *starttag = qstrdup(params.paramValue(QStringLiteral("starttag"), QStringLiteral("start")).toUtf8().constData()); char *endtag = qstrdup(params.paramValue(QStringLiteral("endtag"), QStringLiteral("end")).toUtf8().constData()); ////qDebug() << "// ADDING KEYFRAME TAGS: " << starttag << ", " << endtag; //double max = params.paramValue("max").toDouble(); double min = params.paramValue(QStringLiteral("min")).toDouble(); double factor = params.paramValue(QStringLiteral("factor"), QStringLiteral("1")).toDouble(); double paramOffset = params.paramValue(QStringLiteral("offset"), QStringLiteral("0")).toDouble(); params.removeParam(QStringLiteral("starttag")); params.removeParam(QStringLiteral("endtag")); params.removeParam(QStringLiteral("keyframes")); params.removeParam(QStringLiteral("min")); params.removeParam(QStringLiteral("max")); params.removeParam(QStringLiteral("factor")); params.removeParam(QStringLiteral("offset")); // Special case, only one keyframe, means we want a constant value if (keyFrames.count() == 1) { Mlt::Filter *filter = new Mlt::Filter(*m_producer.profile(), qstrdup(tag.toUtf8().constData())); if (filter && filter->is_valid()) { filter->set("kdenlive_id", qstrdup(params.paramValue(QStringLiteral("id")).toUtf8().constData())); int x1 = keyFrames.at(0).section('=', 0, 0).toInt(); double y1 = keyFrames.at(0).section('=', 1, 1).toDouble(); for (int j = 0; j < params.count(); ++j) { filter->set(params.at(j).name().toUtf8().constData(), params.at(j).value().toUtf8().constData()); } filter->set("in", x1); ////qDebug() << "// ADDING KEYFRAME vals: " << min<<" / "<<max<<", "<<y1<<", factor: "<<factor; filter->set(starttag, locale.toString(((min + y1) - paramOffset) / factor).toUtf8().data()); m_producer.attach(*filter); delete filter; } else { delete[] starttag; delete[] endtag; //qDebug() << "filter is NULL"; m_producer.unlock(); return false; } } else for (int i = 0; i < keyFrames.size() - 1; ++i) { Mlt::Filter *filter = new Mlt::Filter(*m_producer.profile(), qstrdup(tag.toUtf8().constData())); if (filter && filter->is_valid()) { filter->set("kdenlive_id", qstrdup(params.paramValue(QStringLiteral("id")).toUtf8().constData())); int x1 = keyFrames.at(i).section('=', 0, 0).toInt(); double y1 = keyFrames.at(i).section('=', 1, 1).toDouble(); int x2 = keyFrames.at(i + 1).section('=', 0, 0).toInt(); double y2 = keyFrames.at(i + 1).section('=', 1, 1).toDouble(); if (x2 == -1) x2 = duration; // non-overlapping sections if (i > 0) { y1 += (y2 - y1) / (x2 - x1); ++x1; } for (int j = 0; j < params.count(); ++j) { filter->set(params.at(j).name().toUtf8().constData(), params.at(j).value().toUtf8().constData()); } filter->set("in", x1); filter->set("out", x2); ////qDebug() << "// ADDING KEYFRAME vals: " << min<<" / "<<max<<", "<<y1<<", factor: "<<factor; filter->set(starttag, locale.toString(((min + y1) - paramOffset) / factor).toUtf8().data()); filter->set(endtag, locale.toString(((min + y2) - paramOffset) / factor).toUtf8().data()); m_producer.attach(*filter); delete filter; } else { delete[] starttag; delete[] endtag; //qDebug() << "filter is NULL"; m_producer.unlock(); return false; } } delete[] starttag; delete[] endtag; } else { Mlt::Filter *filter; QString prefix; filter = new Mlt::Filter(*m_producer.profile(), qstrdup(tag.toUtf8().constData())); if (filter && filter->is_valid()) { filter->set("kdenlive_id", qstrdup(params.paramValue(QStringLiteral("id")).toUtf8().constData())); } else { //qDebug() << "filter is NULL"; m_producer.unlock(); return false; } params.removeParam(QStringLiteral("kdenlive_id")); if (params.paramValue(QStringLiteral("kdenlive:sync_in_out")) == QLatin1String("1")) { // This effect must sync in / out with parent clip //params.removeParam(QStringLiteral("_sync_in_out")); filter->set_in_and_out(m_producer.get_int("in"), m_producer.get_int("out")); } for (int j = 0; j < params.count(); ++j) { filter->set((prefix + params.at(j).name()).toUtf8().constData(), params.at(j).value().toUtf8().constData()); } if (tag == QLatin1String("sox")) { QString effectArgs = params.paramValue(QStringLiteral("id")).section('_', 1); params.removeParam(QStringLiteral("id")); params.removeParam(QStringLiteral("kdenlive_ix")); params.removeParam(QStringLiteral("tag")); params.removeParam(QStringLiteral("disable")); params.removeParam(QStringLiteral("region")); for (int j = 0; j < params.count(); ++j) { effectArgs.append(' ' + params.at(j).value()); } ////qDebug() << "SOX EFFECTS: " << effectArgs.simplified(); filter->set("effect", effectArgs.simplified().toUtf8().constData()); } // attach filter to the clip m_producer.attach(*filter); delete filter; } return true; }