File indexing completed on 2025-01-19 04:29:46
0001 /* 0002 SPDX-FileCopyrightText: 2017 Nicolas Carion 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 #include "transitionsrepository.hpp" 0007 #include "core.h" 0008 #include "kdenlivesettings.h" 0009 #include "xml/xml.hpp" 0010 #include <QFile> 0011 #include <QStandardPaths> 0012 0013 #include "profiles/profilemodel.hpp" 0014 #include <mlt++/Mlt.h> 0015 0016 std::unique_ptr<TransitionsRepository> TransitionsRepository::instance; 0017 std::once_flag TransitionsRepository::m_onceFlag; 0018 0019 TransitionsRepository::TransitionsRepository() 0020 : AbstractAssetsRepository<AssetListType::AssetType>() 0021 { 0022 init(); 0023 QStringList invalidTransition; 0024 for (const QString &effect : KdenliveSettings::favorite_transitions()) { 0025 if (!exists(effect)) { 0026 invalidTransition << effect; 0027 } 0028 } 0029 if (!invalidTransition.isEmpty()) { 0030 pCore->displayMessage(i18n("Some of your favorite compositions are invalid and were removed: %1", invalidTransition.join(QLatin1Char(','))), 0031 ErrorMessage); 0032 QStringList newFavorites = KdenliveSettings::favorite_transitions(); 0033 for (const QString &effect : qAsConst(invalidTransition)) { 0034 newFavorites.removeAll(effect); 0035 } 0036 KdenliveSettings::setFavorite_transitions(newFavorites); 0037 } 0038 } 0039 0040 Mlt::Properties *TransitionsRepository::retrieveListFromMlt() const 0041 { 0042 return pCore->getMltRepository()->transitions(); 0043 } 0044 0045 Mlt::Properties *TransitionsRepository::getMetadata(const QString &assetId) const 0046 { 0047 return pCore->getMltRepository()->metadata(mlt_service_transition_type, assetId.toLatin1().data()); 0048 } 0049 0050 void TransitionsRepository::parseCustomAssetFile(const QString &file_name, std::unordered_map<QString, Info> &customAssets) const 0051 { 0052 QDomDocument doc; 0053 if (!Xml::docContentFromFile(doc, file_name, false)) { 0054 return; 0055 } 0056 0057 QDomElement base = doc.documentElement(); 0058 QDomNodeList transitions = doc.elementsByTagName(QStringLiteral("transition")); 0059 0060 int nbr_transition = transitions.count(); 0061 if (nbr_transition == 0) { 0062 qWarning() << "broken transition" << file_name; 0063 return; 0064 } 0065 0066 for (int i = 0; i < nbr_transition; ++i) { 0067 QDomNode currentNode = transitions.item(i); 0068 if (currentNode.isNull()) { 0069 continue; 0070 } 0071 Info result; 0072 bool ok = parseInfoFromXml(currentNode.toElement(), result); 0073 if (!ok) { 0074 continue; 0075 } 0076 if (customAssets.count(result.id) > 0) { 0077 // qDebug() << "duplicate transition" << result.id; 0078 } 0079 result.xml = currentNode.toElement(); 0080 QString type = result.xml.attribute(QStringLiteral("type"), QString()); 0081 if (type == QLatin1String("hidden")) { 0082 result.type = AssetListType::AssetType::Hidden; 0083 } else if (type == QLatin1String("short")) { 0084 result.type = AssetListType::AssetType::VideoShortComposition; 0085 } 0086 if (getSingleTrackTransitions().contains(result.id)) { 0087 if (type == QLatin1String("audio")) { 0088 result.type = AssetListType::AssetType::AudioTransition; 0089 } else { 0090 result.type = AssetListType::AssetType::VideoTransition; 0091 } 0092 } 0093 customAssets[result.id] = result; 0094 } 0095 } 0096 0097 std::unique_ptr<TransitionsRepository> &TransitionsRepository::get() 0098 { 0099 std::call_once(m_onceFlag, [] { instance.reset(new TransitionsRepository()); }); 0100 return instance; 0101 } 0102 0103 QStringList TransitionsRepository::assetDirs() const 0104 { 0105 return QStandardPaths::locateAll(QStandardPaths::AppDataLocation, QStringLiteral("transitions"), QStandardPaths::LocateDirectory); 0106 } 0107 0108 void TransitionsRepository::parseType(Mlt::Properties *metadata, Info &res) 0109 { 0110 Mlt::Properties tags(mlt_properties(metadata->get_data("tags"))); 0111 bool audio = QString(tags.get(0)) == QLatin1String("Audio"); 0112 0113 if (getSingleTrackTransitions().contains(res.id)) { 0114 if (audio) { 0115 res.type = AssetListType::AssetType::AudioTransition; 0116 } else { 0117 res.type = AssetListType::AssetType::VideoTransition; 0118 } 0119 } else { 0120 if (audio) { 0121 res.type = AssetListType::AssetType::AudioComposition; 0122 } else { 0123 res.type = AssetListType::AssetType::VideoComposition; 0124 } 0125 } 0126 } 0127 0128 QSet<QString> TransitionsRepository::getSingleTrackTransitions() 0129 { 0130 // Disabled until same track transitions is implemented 0131 return {QStringLiteral("slide"), QStringLiteral("dissolve"), QStringLiteral("wipe"), QStringLiteral("mix")}; 0132 } 0133 0134 QString TransitionsRepository::assetBlackListPath() const 0135 { 0136 return QStringLiteral(":data/blacklisted_transitions.txt"); 0137 } 0138 0139 QString TransitionsRepository::assetPreferredListPath() const 0140 { 0141 // Transitions do not have "Main" filter implemented, so we return an empty 0142 // string instead of path to a file with that list 0143 return QLatin1String(""); 0144 } 0145 0146 std::unique_ptr<Mlt::Transition> TransitionsRepository::getTransition(const QString &transitionId) const 0147 { 0148 Q_ASSERT(exists(transitionId)); 0149 QString service_name = m_assets.at(transitionId).mltId; 0150 // We create the Mlt element from its name 0151 auto transition = std::make_unique<Mlt::Transition>(pCore->getProjectProfile(), service_name.toUtf8().constData()); 0152 transition->set("kdenlive_id", transitionId.toUtf8().constData()); 0153 return transition; 0154 } 0155 0156 bool TransitionsRepository::isAudio(const QString &transitionId) const 0157 { 0158 auto type = getType(transitionId); 0159 return type == AssetListType::AssetType::AudioComposition || type == AssetListType::AssetType::AudioTransition; 0160 } 0161 0162 bool TransitionsRepository::isComposition(const QString &transitionId) const 0163 { 0164 auto type = getType(transitionId); 0165 return type == AssetListType::AssetType::AudioComposition || type == AssetListType::AssetType::VideoComposition || 0166 type == AssetListType::AssetType::VideoShortComposition; 0167 } 0168 0169 const QString TransitionsRepository::getCompositingTransition() 0170 { 0171 if (KdenliveSettings::gpu_accel()) { 0172 return QStringLiteral("movit.overlay"); 0173 } 0174 if (KdenliveSettings::preferredcomposite() != i18n("auto") && exists(KdenliveSettings::preferredcomposite())) { 0175 return KdenliveSettings::preferredcomposite(); 0176 } 0177 QStringList trackComposites = KdenliveSettings::compositingList(); 0178 while (!trackComposites.isEmpty()) { 0179 const QString &cmp = trackComposites.takeFirst(); 0180 if (exists(cmp)) { 0181 qDebug() << ":::: USING TRACK COMPOSITING: " << cmp; 0182 return cmp; 0183 } 0184 } 0185 qWarning() << "no compositing found"; 0186 return QString(); 0187 }