[multimedia/kdenlive/release/26.08] src: Fix crash on time remap title clip

Jean-Baptiste Mardelle <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit f34d29cd1a394199d41833221b971b86b8ddef29 by Jean-Baptiste Mardelle.
Committed on 21/07/2026 at 07:51.
Pushed by mardelle into branch 'release/26.08'.

Fix crash on time remap title clip
BUG: 523277
FIXED-IN: 26.08.0

M  +53   -47   src/dialogs/timeremap.cpp
M  +0    -4    src/timeline2/model/clipmodel.cpp
M  +1    -3    src/timeline2/model/timelinemodel.cpp

https://invent.kde.org/multimedia/kdenlive/-/commit/f34d29cd1a394199d41833221b971b86b8ddef29

diff --git a/src/dialogs/timeremap.cpp b/src/dialogs/timeremap.cpp
index 95bbf49f4e..9923c30d75 100644
--- a/src/dialogs/timeremap.cpp
+++ b/src/dialogs/timeremap.cpp
@@ -1739,69 +1739,75 @@ void TimeRemap::selectedClip(int cid, const QUuid uuid)
     m_lastLength = pCore->getItemDuration(oid);
     m_view->m_startPos = pCore->getItemPosition(oid);
     model->requestClipTimeRemap(cid);
+    prod = model->getClipProducer(cid);
+    if (prod->parent().type() != mlt_service_chain_type) {
+        m_binId.clear();
+        m_view->setDuration(nullptr, -1);
+        remap_box->setEnabled(false);
+        return;
+    }
     connect(model.get(), &TimelineItemModel::dataChanged, this, &TimeRemap::checkClipUpdate);
     m_view->m_maxLength = prod->get_length();
+
     m_in->setRange(0, m_view->m_maxLength - prod->get_in());
     // m_in->setRange(0, m_lastLength - 1);
     m_out->setRange(0, INT_MAX);
     m_view->setDuration(prod, m_lastLength, prod->parent().get_length());
     bool remapFound = false;
-    if (prod->parent().type() == mlt_service_chain_type) {
-        Mlt::Chain fromChain(prod->parent());
-        int count = fromChain.link_count();
-        QScopedPointer<Mlt::Link> fromLink;
-        for (int i = 0; i < count; i++) {
-            fromLink.reset(fromChain.link(i));
-            if (fromLink && fromLink->is_valid() && fromLink->get("mlt_service")) {
-                if (fromLink->get("mlt_service") == QLatin1String("timeremap")) {
-                    // Found a timeremap effect, read params
-                    if (!fromLink->property_exists("time_map")) {
-                        fromLink->set("time_map", fromLink->get("map"));
-                    }
-                    QString mapData(fromLink->get("time_map"));
-                    m_remapLink.reset(fromChain.link(i));
-                    m_view->m_remapProps.inherit(*m_remapLink.get());
-                    // This is a fake query to force the animation to be parsed
-                    (void)m_view->m_remapProps.anim_get_double("time_map", 0, m_lastLength + prod->get_in());
-                    m_view->loadKeyframes(mapData);
-                    if (mapData.isEmpty()) {
-                        // We are just adding the remap effect, set default params
-                        if (model->clipIsAudio(cid)) {
-                            fromLink->set("pitch", 1);
-                        }
-                        fromLink->set("image_mode", "nearest");
+    Mlt::Chain fromChain(prod->parent());
+    int count = fromChain.link_count();
+    QScopedPointer<Mlt::Link> fromLink;
+    for (int i = 0; i < count; i++) {
+        fromLink.reset(fromChain.link(i));
+        if (fromLink && fromLink->is_valid() && fromLink->get("mlt_service")) {
+            if (fromLink->get("mlt_service") == QLatin1String("timeremap")) {
+                // Found a timeremap effect, read params
+                if (!fromLink->property_exists("time_map")) {
+                    fromLink->set("time_map", fromLink->get("map"));
+                }
+                QString mapData(fromLink->get("time_map"));
+                m_remapLink.reset(fromChain.link(i));
+                m_view->m_remapProps.inherit(*m_remapLink.get());
+                // This is a fake query to force the animation to be parsed
+                (void)m_view->m_remapProps.anim_get_double("time_map", 0, m_lastLength + prod->get_in());
+                qDebug() << ":::: LOADING KF CASE B...";
+                m_view->loadKeyframes(mapData);
+                if (mapData.isEmpty()) {
+                    // We are just adding the remap effect, set default params
+                    if (model->clipIsAudio(cid)) {
+                        fromLink->set("pitch", 1);
                     }
-                    remapFound = true;
-                    break;
+                    fromLink->set("image_mode", "nearest");
                 }
+                remapFound = true;
+                break;
             }
         }
-        if (remapFound && m_splitId > -1) {
-            std::shared_ptr<Mlt::Producer> prod2 = model->getClipProducer(m_splitId);
-            if (prod2->parent().type() == mlt_service_chain_type) {
-                Mlt::Chain fromChain2(prod2->parent());
-                count = fromChain2.link_count();
-                for (int j = 0; j < count; j++) {
-                    QScopedPointer<Mlt::Link> fromLink2(fromChain2.link(j));
-                    if (fromLink2 && fromLink2->is_valid() && fromLink2->get("mlt_service")) {
-                        if (fromLink2->get("mlt_service") == QLatin1String("timeremap")) {
-                            m_splitRemap.reset(fromChain2.link(j));
-                            break;
-                        }
+    }
+    if (remapFound && m_splitId > -1) {
+        std::shared_ptr<Mlt::Producer> prod2 = model->getClipProducer(m_splitId);
+        if (prod2->parent().type() == mlt_service_chain_type) {
+            Mlt::Chain fromChain2(prod2->parent());
+            count = fromChain2.link_count();
+            for (int j = 0; j < count; j++) {
+                QScopedPointer<Mlt::Link> fromLink2(fromChain2.link(j));
+                if (fromLink2 && fromLink2->is_valid() && fromLink2->get("mlt_service")) {
+                    if (fromLink2->get("mlt_service") == QLatin1String("timeremap")) {
+                        m_splitRemap.reset(fromChain2.link(j));
+                        break;
                     }
                 }
             }
         }
-        if (remapFound) {
-            QSignalBlocker bk(pitch_compensate);
-            QSignalBlocker bk2(frame_blending);
-            pitch_compensate->setChecked(m_remapLink->get_int("pitch") == 1 || (m_splitRemap && m_splitRemap->get_int("pitch")));
-            frame_blending->setChecked(m_remapLink->get("image_mode") != QLatin1String("nearest"));
-            remap_box->setEnabled(true);
-        }
-    } else {
-        qDebug() << "/// PRODUCER IS NOT A CHAIN!!!!";
     }
+    if (remapFound) {
+        QSignalBlocker bk(pitch_compensate);
+        QSignalBlocker bk2(frame_blending);
+        pitch_compensate->setChecked(m_remapLink->get_int("pitch") == 1 || (m_splitRemap && m_splitRemap->get_int("pitch")));
+        frame_blending->setChecked(m_remapLink->get("image_mode") != QLatin1String("nearest"));
+        remap_box->setEnabled(true);
+    }
+
     if (!m_binId.isEmpty() && pCore->getMonitor(Kdenlive::ClipMonitor)->activeClipId() == m_binId) {
         connect(pCore->getMonitor(Kdenlive::ClipMonitor), &Monitor::seekPosition, pCore->getMonitor(Kdenlive::ClipMonitor), &Monitor::seekRemap,
                 Qt::UniqueConnection);
diff --git a/src/timeline2/model/clipmodel.cpp b/src/timeline2/model/clipmodel.cpp
index bd9d4dce87..dbbef954d4 100644
--- a/src/timeline2/model/clipmodel.cpp
+++ b/src/timeline2/model/clipmodel.cpp
@@ -998,10 +998,6 @@ void ClipModel::refreshProducerFromBin(int trackId)
 
 bool ClipModel::useTimeRemapProducer(bool enable, Fun &undo, Fun &redo)
 {
-    if (m_endlessResize) {
-        // no timewarp for endless producers
-        return false;
-    }
     std::function<bool(void)> local_undo = []() { return true; };
     std::function<bool(void)> local_redo = []() { return true; };
     int audioStream = getIntProperty(QStringLiteral("audio_index"));
diff --git a/src/timeline2/model/timelinemodel.cpp b/src/timeline2/model/timelinemodel.cpp
index 5f762e684c..3a8df7d359 100644
--- a/src/timeline2/model/timelinemodel.cpp
+++ b/src/timeline2/model/timelinemodel.cpp
@@ -7257,9 +7257,7 @@ bool TimelineModel::requestClipTimeRemap(int clipId, bool enable, Fun &undo, Fun
     if (trackId != -1) {
         success = success && getTrackById(trackId)->requestClipDeletion(clipId, true, true, local_undo, local_redo, false, false);
     }
-    if (success) {
-        success = m_allClips[clipId]->useTimeRemapProducer(enable, local_undo, local_redo);
-    }
+    success = success && m_allClips[clipId]->useTimeRemapProducer(enable, local_undo, local_redo);
     if (trackId != -1) {
         success = success && getTrackById(trackId)->requestClipInsertion(clipId, oldPos, true, true, local_undo, local_redo, false, false);
         if (success && !enable && previousDuration > 0) {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.