Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Multimedia
Kdenlive
Commits
380e508f
Commit
380e508f
authored
Sep 27, 2016
by
Jean-Baptiste Mardelle
Browse files
Fix duplicate producers created on library import, patch by Harald Albrecht
REVIEW: 129034
parent
e6561652
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/bin/bin.cpp
View file @
380e508f
...
...
@@ -64,6 +64,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include
<QDebug>
#include
<QtConcurrent>
#include
<QUndoCommand>
#include
<QCryptographicHash>
MyListView
::
MyListView
(
QWidget
*
parent
)
:
QListView
(
parent
)
...
...
@@ -2547,7 +2548,12 @@ void Bin::slotExpandUrl(ItemInfo info, QUrl url, QUndoCommand *command)
delete
command
;
return
;
}
// Maps playlist producer IDs to (project) bin producer IDs.
QMap
<
QString
,
QString
>
idMap
;
// Maps hash IDs to (project) first playlist producer instance ID. This is
// necessary to detect duplicate producer serializations produced by MLT.
// This covers, for instance, images and titles.
QMap
<
QString
,
QString
>
hashToIdMap
;
QDir
mltRoot
(
doc
.
documentElement
().
attribute
(
QStringLiteral
(
"root"
)));
for
(
int
i
=
0
;
i
<
producers
.
count
();
i
++
)
{
QDomElement
prod
=
producers
.
at
(
i
).
toElement
();
...
...
@@ -2557,14 +2563,57 @@ void Bin::slotExpandUrl(ItemInfo info, QUrl url, QUndoCommand *command)
// slowmotion producer
if
(
originalId
.
contains
(
QLatin1Char
(
':'
)))
originalId
=
originalId
.
section
(
QLatin1Char
(
':'
),
1
,
1
);
// We already have seen and mapped this producer.
if
(
idMap
.
contains
(
originalId
))
continue
;
// Check for duplicate producers, based on hash value of producer.
// Be careful as to the kdenlive:file_hash! It is not unique for
// title clips, nor color clips. Also not sure about image sequences.
// So we use mlt service-specific hashes to identify duplicate producers.
QString
hash
;
QString
mltService
=
EffectsList
::
property
(
prod
,
QStringLiteral
(
"mlt_service"
));
if
(
mltService
==
QLatin1String
(
"pixbuf"
)
||
mltService
==
QLatin1String
(
"kdenlivetitle"
)
||
mltService
==
QLatin1String
(
"color"
)
||
mltService
==
QLatin1String
(
"colour"
))
{
hash
=
mltService
+
QStringLiteral
(
":"
)
+
EffectsList
::
property
(
prod
,
QStringLiteral
(
"kdenlive:clipname"
))
+
QStringLiteral
(
":"
)
+
EffectsList
::
property
(
prod
,
QStringLiteral
(
"kdenlive:folderid"
))
+
QStringLiteral
(
":"
);
if
(
mltService
==
QLatin1String
(
"kdenlivetitle"
))
{
// Calculate hash based on title contents.
hash
.
append
(
QString
(
QCryptographicHash
::
hash
(
EffectsList
::
property
(
prod
,
QStringLiteral
(
"xmldata"
)).
toUtf8
(),
QCryptographicHash
::
Md5
).
toHex
()));
}
else
if
(
mltService
==
QLatin1String
(
"pixbuf"
)
||
mltService
==
QLatin1String
(
"color"
)
||
mltService
==
QLatin1String
(
"colour"
))
{
hash
.
append
(
EffectsList
::
property
(
prod
,
QStringLiteral
(
"resource"
)));
}
QString
singletonId
=
hashToIdMap
.
value
(
hash
,
QString
());
if
(
singletonId
.
length
())
{
// map duplicate producer ID to single bin clip producer ID.
qDebug
()
<<
"found duplicate producer:"
<<
hash
<<
", reusing newID:"
<<
singletonId
;
idMap
.
insert
(
originalId
,
singletonId
);
continue
;
}
}
// First occurence of a producer, so allocate new bin clip producer ID.
QString
newId
=
QString
::
number
(
getFreeClipId
());
idMap
.
insert
(
originalId
,
newId
);
qDebug
()
<<
"originalId: "
<<
originalId
<<
", newId: "
<<
newId
;
// Ensure to register new bin clip producer ID in hash hashmap for
// those clips that MLT likes to serialize multiple times. This is
// indicated by having a hash "value" unqual "". See also above.
if
(
hash
.
length
())
{
hashToIdMap
.
insert
(
hash
,
newId
);
}
// Add clip
QDomElement
clone
=
prod
.
cloneNode
(
true
).
toElement
();
EffectsList
::
setProperty
(
clone
,
QStringLiteral
(
"kdenlive:folderid"
),
folderId
);
QString
mltService
=
EffectsList
::
property
(
clone
,
QStringLiteral
(
"mlt_service"
));
// Do we have a producer that uses a resource property that contains a path?
if
(
mltService
==
QLatin1String
(
"avformat-novalidate"
)
// av clip
||
mltService
==
QLatin1String
(
"avformat"
)
// av clip
...
...
src/timeline/customtrackview.cpp
View file @
380e508f
...
...
@@ -8194,27 +8194,28 @@ bool CustomTrackView::hasSelection() const
void
CustomTrackView
::
exportTimelineSelection
(
QString
path
)
{
if
(
!
m_selectionGroup
&&
!
m_dragItem
)
{
qDebug()<<"/// ARGH, NO SELECTION GRP";
return;
qDebug
()
<<
"/// ARGH, NO SELECTION GRP"
;
emit
displayMessage
(
i18n
(
"No clips and transitions selected in timeline for exporting."
),
ErrorMessage
);
return
;
}
if
(
path
.
isEmpty
())
{
QString
clipFolder
=
KRecentDirs
::
dir
(
QStringLiteral
(
":KdenliveClipFolder"
));
if
(
clipFolder
.
isEmpty
())
{
clipFolder
=
QDir
::
homePath
();
}
path = QFileDialog::getSaveFileName(this, i18n("Save
Zone
"), clipFolder, i18n("MLT playlist (*.mlt)"));
path
=
QFileDialog
::
getSaveFileName
(
this
,
i18n
(
"Save
Timeline Selection
"
),
clipFolder
,
i18n
(
"MLT playlist (*.mlt)"
));
if
(
path
.
isEmpty
())
return
;
}
QList
<
QGraphicsItem
*>
children
;
QRectF
bounding
;
if
(
m_selectionGroup
)
{
children = m_selectionGroup->childItems();
bounding = m_selectionGroup->sceneBoundingRect();
children
=
m_selectionGroup
->
childItems
();
bounding
=
m_selectionGroup
->
sceneBoundingRect
();
}
else
{
// only one clip selected
children << m_dragItem;
bounding = m_dragItem->sceneBoundingRect();
// only one clip selected
children
<<
m_dragItem
;
bounding
=
m_dragItem
->
sceneBoundingRect
();
}
int
firstTrack
=
getTrackFromPos
(
bounding
.
bottom
());
int
lastTrack
=
getTrackFromPos
(
bounding
.
top
());
...
...
@@ -8222,34 +8223,33 @@ void CustomTrackView::exportTimelineSelection(QString path)
Mlt
::
Tractor
*
newTractor
=
new
Mlt
::
Tractor
(
*
(
m_document
->
renderer
()
->
getProducer
()
->
profile
()));
Mlt
::
Field
*
field
=
newTractor
->
field
();
for
(
int
i
=
firstTrack
;
i
<=
lastTrack
;
i
++
)
{
QScopedPointer<Mlt::Playlist> newTrackPlaylist(new Mlt::Playlist(*newTractor->profile()));
newTractor->set_track(*newTrackPlaylist, i - firstTrack);
QScopedPointer
<
Mlt
::
Playlist
>
newTrackPlaylist
(
new
Mlt
::
Playlist
(
*
newTractor
->
profile
()));
newTractor
->
set_track
(
*
newTrackPlaylist
,
i
-
firstTrack
);
}
int
startOffest
=
m_projectDuration
;
// Find first frame of selection
for
(
int
i
=
0
;
i
<
children
.
count
();
++
i
)
{
QGraphicsItem *item = children.at(i);
if (item->type() != TransitionWidget && item->type() != AVWidget) {
continue;
}
AbstractClipItem *it = static_cast<AbstractClipItem *>(item);
if (!it) continue;
int pos = it->startPos().frames(m_document->fps());
if (pos < startOffest) startOffest = pos;
QGraphicsItem
*
item
=
children
.
at
(
i
);
if
(
item
->
type
()
!=
TransitionWidget
&&
item
->
type
()
!=
AVWidget
)
{
continue
;
}
AbstractClipItem
*
it
=
static_cast
<
AbstractClipItem
*>
(
item
);
if
(
!
it
)
continue
;
int
pos
=
it
->
startPos
().
frames
(
m_document
->
fps
());
if
(
pos
<
startOffest
)
startOffest
=
pos
;
}
for
(
int
i
=
0
;
i
<
children
.
count
();
++
i
)
{
QGraphicsItem *item = children.at(i);
if (item->type() == AVWidget) {
QGraphicsItem
*
item
=
children
.
at
(
i
);
if
(
item
->
type
()
==
AVWidget
)
{
ClipItem
*
clip
=
static_cast
<
ClipItem
*>
(
item
);
int track = clip->track() - firstTrack;
m_timeline->duplicateClipOnPlaylist(clip->track(), clip->startPos().seconds(), startOffest, newTractor->track(track));
}
else if (item->type() == TransitionWidget) {
Transition *tr = static_cast<Transition*>(item);
int a_track = qBound(0, tr->transitionEndTrack() - firstTrack, lastTrack - firstTrack + 1);
int b_track = qBound(0, tr->track() - firstTrack, lastTrack - firstTrack + 1);;
m_timeline->transitionHandler->duplicateTransitionOnPlaylist(tr->startPos().frames(m_document->fps()) - startOffest, tr->endPos().frames(m_document->fps()) - startOffest, tr->transitionTag(), tr->toXML(), a_track, b_track, field);
}
int
track
=
clip
->
track
()
-
firstTrack
;
m_timeline
->
duplicateClipOnPlaylist
(
clip
->
track
(),
clip
->
startPos
().
seconds
(),
startOffest
,
newTractor
->
track
(
track
));
}
else
if
(
item
->
type
()
==
TransitionWidget
)
{
Transition
*
tr
=
static_cast
<
Transition
*>
(
item
);
int
a_track
=
qBound
(
0
,
tr
->
transitionEndTrack
()
-
firstTrack
,
lastTrack
-
firstTrack
+
1
);
int
b_track
=
qBound
(
0
,
tr
->
track
()
-
firstTrack
,
lastTrack
-
firstTrack
+
1
);;
m_timeline
->
transitionHandler
->
duplicateTransitionOnPlaylist
(
tr
->
startPos
().
frames
(
m_document
->
fps
())
-
startOffest
,
tr
->
endPos
().
frames
(
m_document
->
fps
())
-
startOffest
,
tr
->
transitionTag
(),
tr
->
toXML
(),
a_track
,
b_track
,
field
);
}
}
Mlt
::
Consumer
xmlConsumer
(
*
newTractor
->
profile
(),
(
"xml:"
+
path
).
toUtf8
().
constData
());
xmlConsumer
.
set
(
"terminate_on_pause"
,
1
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment