Commit ef813c9c authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Fix timeline preview sometimes using old rendered file instead of recreating a preview

parent 76b0eeac
Pipeline #140889 passed with stage
in 6 minutes and 55 seconds
......@@ -1207,7 +1207,7 @@ void Core::addBin(const QString &id)
m_mainWindow->addBin(bin, folderName);
}
void Core::loadTimelinePreview(const QString &chunks, const QString &dirty, const QDateTime &documentDate, int enablePreview, Mlt::Playlist &playlist)
void Core::loadTimelinePreview(const QString &chunks, const QString &dirty, int enablePreview, Mlt::Playlist &playlist)
{
pCore->window()->getMainTimeline()->controller()->loadPreview(chunks, dirty, documentDate, enablePreview, playlist);
pCore->window()->getMainTimeline()->controller()->loadPreview(chunks, dirty, enablePreview, playlist);
}
......@@ -275,7 +275,7 @@ public:
int getNewStuff(const QString &configFile);
/** @brief Get the frame size of the clip above a composition */
const QSize getCompositionSizeOnTrack(const ObjectId &id);
void loadTimelinePreview(const QString &chunks, const QString &dirty, const QDateTime &documentDate, int enablePreview, Mlt::Playlist &playlist);
void loadTimelinePreview(const QString &chunks, const QString &dirty, int enablePreview, Mlt::Playlist &playlist);
QString packageType() { return m_packageType; };
......
......@@ -1878,3 +1878,33 @@ void KdenliveDoc::useOriginals(QDomDocument &doc)
}
}
}
void KdenliveDoc::cleanupTimelinePreview(const QDateTime &documentDate)
{
if (m_url.isEmpty()) {
// Document was never saved, nothing to do
return;
}
bool ok;
QDir cacheDir = getCacheDir(CachePreview, &ok);
if (cacheDir.exists() && cacheDir.dirName() == QLatin1String("preview") && ok) {
QFileInfoList chunksList = cacheDir.entryInfoList(QDir::Files, QDir::Time);
for (auto &chunkFile : chunksList) {
if (chunkFile.lastModified() > documentDate) {
// This chunk is invalid
QString chunkName = chunkFile.fileName().section(QLatin1Char('.'), 0, 0);
bool ok;
chunkName.toInt(&ok);
if (!ok) {
// This is not one of our chunks
continue;
}
// Physically remove chunk file
cacheDir.remove(chunkFile.fileName());
} else {
// Done
break;
}
}
}
}
......@@ -154,6 +154,8 @@ public:
QMap <QString, QString> getProjectTags();
/** @brief Returns the number of audio channels for this project */
int audioChannels() const;
/** @brief Ensure we don't have leftover preview chunks (created after last save */
void cleanupTimelinePreview(const QDateTime &documentDate);
/**
......
......@@ -1000,7 +1000,8 @@ bool ProjectManager::updateTimeline(int pos, const QString &chunks, const QStrin
m_mainTimelineModel->addSnap(0);
pCore->window()->getMainTimeline()->setModel(m_mainTimelineModel, pCore->monitorManager()->projectMonitor()->getControllerProxy());
bool projectErrors = false;
if (!constructTimelineFromMelt(m_mainTimelineModel, tractor, m_progressDialog, m_project->modifiedDecimalPoint(), chunks, dirty, documentDate, enablePreview, &projectErrors)) {
m_project->cleanupTimelinePreview(documentDate);
if (!constructTimelineFromMelt(m_mainTimelineModel, tractor, m_progressDialog, m_project->modifiedDecimalPoint(), chunks, dirty, enablePreview, &projectErrors)) {
//TODO: act on project load failure
qDebug()<<"// Project failed to load!!";
}
......
......@@ -36,7 +36,7 @@ bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline,
bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline, int tid, Mlt::Playlist &track,
const std::unordered_map<QString, QString> &binIdCorresp, Fun &undo, Fun &redo, bool audioTrack, const QString &originalDecimalPoint, int playlist, const QList<Mlt::Transition *> &compositions, QProgressDialog *progressDialog = nullptr);
bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timeline, Mlt::Tractor tractor, QProgressDialog *progressDialog, const QString &originalDecimalPoint, const QString &chunks, const QString &dirty, const QDateTime &documentDate, int enablePreview, bool *projectErrors)
bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timeline, Mlt::Tractor tractor, QProgressDialog *progressDialog, const QString &originalDecimalPoint, const QString &chunks, const QString &dirty, int enablePreview, bool *projectErrors)
{
Fun undo = []() { return true; };
Fun redo = []() { return true; };
......@@ -76,7 +76,7 @@ bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timelin
if (reserved_names.contains(playlist_name)) {
if (playlist_name == QLatin1String("timeline_preview")) {
Mlt::Playlist local_playlist(*track);
pCore->loadTimelinePreview(chunks, dirty, documentDate, enablePreview, local_playlist);
pCore->loadTimelinePreview(chunks, dirty, enablePreview, local_playlist);
}
continue;
}
......
......@@ -8,13 +8,12 @@
#include <memory>
#include <mlt++/MltTractor.h>
#include <QtCore/QString>
#include <QDateTime>
class TimelineItemModel;
class QProgressDialog;
/** @brief This function can be used to construct a TimelineModel object from a Mlt object hierarchy
*/
bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timeline, Mlt::Tractor mlt_timeline, QProgressDialog *progressDialog = nullptr, const QString &originalDecimalPoint = QString(), const QString &chunks = QString(), const QString &dirty = QString(), const QDateTime &documentDate = QDateTime(), int enablePreview = 0, bool *projectErrors = nullptr);
bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timeline, Mlt::Tractor mlt_timeline, QProgressDialog *progressDialog = nullptr, const QString &originalDecimalPoint = QString(), const QString &chunks = QString(), const QString &dirty = QString(), int enablePreview = 0, bool *projectErrors = nullptr);
#endif
......@@ -131,7 +131,7 @@ bool PreviewManager::buildPreviewTrack()
return true;
}
void PreviewManager::loadChunks(QVariantList previewChunks, QVariantList dirtyChunks, const QDateTime &documentDate, Mlt::Playlist &playlist)
void PreviewManager::loadChunks(QVariantList previewChunks, QVariantList dirtyChunks, Mlt::Playlist &playlist)
{
if (previewChunks.isEmpty()) {
previewChunks = m_renderedChunks;
......@@ -140,27 +140,6 @@ void PreviewManager::loadChunks(QVariantList previewChunks, QVariantList dirtyCh
dirtyChunks = m_dirtyChunks;
}
// First chech if there are invalid chunks (created after document date)
QFileInfoList chunksList = m_cacheDir.entryInfoList({QString("*.%1").arg(m_extension)}, QDir::Files, QDir::Time);
for (auto &chunkFile : chunksList) {
if (chunkFile.lastModified() > documentDate) {
// This chunk is invalid
QString chunkName = chunkFile.fileName().section(QLatin1Char('.'), 0, 0);
bool ok;
int chunkFrame = chunkName.toInt(&ok);
if (!ok) {
// This is not one of our chunks
continue;
}
previewChunks.removeAll(chunkName);
dirtyChunks << chunkFrame;
// Physically remove chunk file
m_cacheDir.remove(chunkFile.fileName());
} else {
// Done
break;
}
}
QStringList existingChuncks;
if (!previewChunks.isEmpty()) {
existingChuncks = m_cacheDir.entryList(QDir::Files);
......
......@@ -65,7 +65,7 @@ public:
/** @brief: Returns directory currently used to store the preview files. */
const QDir getCacheDir() const;
/** @brief: Load existing ruler chunks. */
void loadChunks(QVariantList previewChunks, QVariantList dirtyChunks, const QDateTime &documentDate, Mlt::Playlist &playlist);
void loadChunks(QVariantList previewChunks, QVariantList dirtyChunks, Mlt::Playlist &playlist);
int setOverlayTrack(Mlt::Playlist *overlay);
/** @brief Remove the effect compare overlay track */
void removeOverlayTrack();
......
......@@ -2402,7 +2402,7 @@ void TimelineController::disablePreview(bool disable)
m_model->m_tractor->unlock();
}
Mlt::Playlist playlist;
m_timelinePreview->loadChunks(QVariantList(), QVariantList(), QDateTime(), playlist);
m_timelinePreview->loadChunks(QVariantList(), QVariantList(), playlist);
m_usePreview = true;
}
}
......@@ -2442,7 +2442,7 @@ void TimelineController::resetPreview()
}
}
void TimelineController::loadPreview(const QString &chunks, const QString &dirty, const QDateTime &documentDate, int enable, Mlt::Playlist &playlist)
void TimelineController::loadPreview(const QString &chunks, const QString &dirty, int enable, Mlt::Playlist &playlist)
{
if (chunks.isEmpty() && dirty.isEmpty()) {
return;
......@@ -2498,7 +2498,7 @@ void TimelineController::loadPreview(const QString &chunks, const QString &dirty
m_usePreview = true;
m_model->m_overlayTrackCount = m_timelinePreview->addedTracks();
}
m_timelinePreview->loadChunks(renderedChunks, dirtyChunks, documentDate, playlist);
m_timelinePreview->loadChunks(renderedChunks, dirtyChunks, playlist);
}
}
......
......@@ -564,7 +564,7 @@ public:
/** @brief Load timeline preview from saved doc
*/
void loadPreview(const QString &chunks, const QString &dirty, const QDateTime &documentDate, int enable, Mlt::Playlist &playlist);
void loadPreview(const QString &chunks, const QString &dirty, int enable, Mlt::Playlist &playlist);
/** @brief Return document properties with added settings from timeline
*/
QMap<QString, QString> documentProperties();
......
......@@ -148,7 +148,7 @@ TEST_CASE("Save File", "[SF]")
Mlt::Service s(*xmlProd);
Mlt::Tractor tractor(s);
bool projectErrors;
constructTimelineFromMelt(timeline, tractor, nullptr, QString(), QString(), QString(), QDateTime(), 0, &projectErrors);
constructTimelineFromMelt(timeline, tractor, nullptr, QString(), QString(), QString(), 0, &projectErrors);
REQUIRE(timeline->checkConsistency());
int tid1 = timeline->getTrackIndexFromPosition(2);
int cid1 = timeline->getClipByStartPosition(tid1, 0);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment