Skip to content

Commit b55b4c9

Browse files
committed
Fix crash on two undo/redo operations
When the clip was added back with a redo, it was not getting a UUID. As a result, the filter redo could not find the clip to put the filter back onto. As reported here: https://forum.shotcut.org/t/brightness-filter-gets-deleted-after-undo-and-redo/47556
1 parent be54b02 commit b55b4c9

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

src/commands/timelinecommands.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,23 @@ Mlt::Producer *deserializeProducer(QString &xml)
3737
return new Mlt::Producer(MLT.profile(), "xml-string", xml.toUtf8().constData());
3838
}
3939

40+
QVector<QUuid> getProducerUuids(Mlt::Producer *producer)
41+
{
42+
QVector<QUuid> uuids;
43+
if (producer->type() == mlt_service_playlist_type) {
44+
Mlt::Playlist playlist(*producer);
45+
int count = playlist.count();
46+
for (int i = 0; i < count; i++) {
47+
QScopedPointer<Mlt::ClipInfo> info(playlist.clip_info(i));
48+
Mlt::Producer clip = Mlt::Producer(info->producer);
49+
uuids << MLT.ensureHasUuid(clip.parent());
50+
}
51+
} else {
52+
uuids << MLT.ensureHasUuid(*producer);
53+
}
54+
return uuids;
55+
}
56+
4057
int getUniqueGroupNumber(MultitrackModel &model)
4158
{
4259
QSet<int> groups;
@@ -88,6 +105,14 @@ void AppendCommand::redo()
88105
Mlt::Producer *producer = longTask.runAsync<Mlt::Producer *>(QObject::tr("Preparing"), [=]() {
89106
return deserializeProducer(m_xml);
90107
});
108+
if (!producer || !producer->is_valid()) {
109+
LOG_ERROR() << "Invalid producer";
110+
m_undoHelper.recordAfterState();
111+
return;
112+
}
113+
if (m_uuids.empty()) {
114+
m_uuids = getProducerUuids(producer);
115+
}
91116
if (producer->type() == mlt_service_playlist_type) {
92117
Mlt::Playlist playlist(*producer);
93118
int count = playlist.count();
@@ -98,10 +123,12 @@ void AppendCommand::redo()
98123
if (!m_skipProxy)
99124
ProxyManager::generateIfNotExists(clip);
100125
clip.set_in_and_out(info->frame_in, info->frame_out);
126+
MLT.setUuid(clip.parent(), m_uuids[i]);
101127
bool lastClip = i == (count - 1);
102128
m_model.appendClip(m_trackIndex, clip, false, lastClip);
103129
}
104130
} else {
131+
MLT.setUuid(*producer, m_uuids[0]);
105132
if (!m_skipProxy)
106133
ProxyManager::generateIfNotExists(*producer);
107134
m_model.appendClip(m_trackIndex, *producer, m_seek);
@@ -146,6 +173,14 @@ void InsertCommand::redo()
146173
int shift = 0;
147174
m_undoHelper.recordBeforeState();
148175
Mlt::Producer clip(MLT.profile(), "xml-string", m_xml.toUtf8().constData());
176+
if (!clip.is_valid()) {
177+
LOG_ERROR() << "Invalid producer";
178+
m_undoHelper.recordAfterState();
179+
return;
180+
}
181+
if (m_uuids.empty()) {
182+
m_uuids = getProducerUuids(&clip);
183+
}
149184
if (clip.type() == mlt_service_playlist_type) {
150185
LongUiTask longTask(QObject::tr("Add Files"));
151186
Mlt::Playlist playlist(clip);
@@ -159,12 +194,14 @@ void InsertCommand::redo()
159194
n);
160195
ProxyManager::generateIfNotExists(clip);
161196
clip.set_in_and_out(info->frame_in, info->frame_out);
197+
MLT.setUuid(clip.parent(), m_uuids[i]);
162198
bool lastClip = i == 0;
163199
m_model.insertClip(m_trackIndex, clip, m_position, m_rippleAllTracks, false, lastClip);
164200
shift += info->frame_count;
165201
}
166202
} else {
167203
shift = clip.get_playtime();
204+
MLT.setUuid(clip, m_uuids[0]);
168205
ProxyManager::generateIfNotExists(clip);
169206
m_model.insertClip(m_trackIndex, clip, m_position, m_rippleAllTracks, m_seek);
170207
}
@@ -207,6 +244,9 @@ void OverwriteCommand::redo()
207244
LOG_DEBUG() << "trackIndex" << m_trackIndex << "position" << m_position;
208245
m_undoHelper.recordBeforeState();
209246
Mlt::Producer clip(MLT.profile(), "xml-string", m_xml.toUtf8().constData());
247+
if (m_uuids.empty()) {
248+
m_uuids = getProducerUuids(&clip);
249+
}
210250
if (clip.type() == mlt_service_playlist_type) {
211251
LongUiTask longTask(QObject::tr("Add Files"));
212252
Mlt::Playlist playlist(clip);
@@ -218,11 +258,13 @@ void OverwriteCommand::redo()
218258
longTask.reportProgress(QFileInfo(ProxyManager::resource(clip)).fileName(), i, n);
219259
ProxyManager::generateIfNotExists(clip);
220260
clip.set_in_and_out(info->frame_in, info->frame_out);
261+
MLT.setUuid(clip.parent(), m_uuids[i]);
221262
bool lastClip = i == (n - 1);
222263
m_model.overwrite(m_trackIndex, clip, position, false, lastClip);
223264
position += info->frame_count;
224265
}
225266
} else {
267+
MLT.setUuid(clip, m_uuids[0]);
226268
ProxyManager::generateIfNotExists(clip);
227269
m_model.overwrite(m_trackIndex, clip, m_position, m_seek);
228270
}

src/commands/timelinecommands.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class AppendCommand : public QUndoCommand
8787
UndoHelper m_undoHelper;
8888
bool m_skipProxy;
8989
bool m_seek;
90+
QVector<QUuid> m_uuids;
9091
};
9192

9293
class InsertCommand : public QUndoCommand
@@ -114,6 +115,7 @@ class InsertCommand : public QUndoCommand
114115
bool m_rippleAllTracks;
115116
bool m_rippleMarkers;
116117
int m_markersShift;
118+
QVector<QUuid> m_uuids;
117119
};
118120

119121
class OverwriteCommand : public QUndoCommand
@@ -135,6 +137,7 @@ class OverwriteCommand : public QUndoCommand
135137
QString m_xml;
136138
UndoHelper m_undoHelper;
137139
bool m_seek;
140+
QVector<QUuid> m_uuids;
138141
};
139142

140143
class LiftCommand : public QUndoCommand

0 commit comments

Comments
 (0)