Correctly load same track transitions when opening project

parent f371478a
......@@ -39,6 +39,7 @@
#include <mlt++/MltProducer.h>
#include <mlt++/MltProfile.h>
#include <mlt++/MltFilter.h>
#include <mlt++/MltField.h>
#include <mlt++/MltTransition.h>
#include <QApplication>
......@@ -47,7 +48,7 @@ static QStringList m_errorMessage;
bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline, int tid, Mlt::Tractor &track,
const std::unordered_map<QString, QString> &binIdCorresp, Fun &undo, Fun &redo, bool audioTrack, QString originalDecimalPoint, QProgressDialog *progressDialog = nullptr);
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, QString originalDecimalPoint, QProgressDialog *progressDialog = nullptr);
const std::unordered_map<QString, QString> &binIdCorresp, Fun &undo, Fun &redo, bool audioTrack, QString originalDecimalPoint, int playlist, QMap <int, int> mixList, QProgressDialog *progressDialog = nullptr);
bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timeline, Mlt::Tractor tractor, QProgressDialog *progressDialog, QString originalDecimalPoint)
{
......@@ -127,7 +128,7 @@ bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timelin
timeline->setTrackProperty(tid, QStringLiteral("hide"), QString::number(muteState));
}
ok = ok && constructTrackFromMelt(timeline, tid, local_playlist, binIdCorresp, undo, redo, audioTrack, originalDecimalPoint, progressDialog);
ok = ok && constructTrackFromMelt(timeline, tid, local_playlist, binIdCorresp, undo, redo, audioTrack, originalDecimalPoint, 0, {}, progressDialog);
if (local_playlist.get_int("kdenlive:locked_track") > 0) {
lockedTracksIndexes << tid;
}
......@@ -221,6 +222,23 @@ bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline,
qDebug() << "ERROR : wrong number of subtracks";
return false;
}
// Check same track transitions
QScopedPointer<Mlt::Service> service(track.field());
QList<Mlt::Transition *> compositions;
QMap <int, int> mixList;
while ((service != nullptr) && service->is_valid()) {
if (service->type() == transition_type) {
Mlt::Transition t((mlt_transition)service->get_service());
mixList.insert(t.get_in(), t.get_out());
QString id(t.get("kdenlive_id"));
compositions << new Mlt::Transition(t);
if (id.isEmpty()) {
qDebug() << "// Warning, this should not happen, transition without id: " << t.get("id") << " = " << t.get("mlt_service");
t.set("kdenlive_id", t.get("mlt_service"));
}
}
service.reset(service->producer());
}
for (int i = 0; i < track.count(); i++) {
std::unique_ptr<Mlt::Producer> sub_track(track.track(i));
if (sub_track->type() != playlist_type) {
......@@ -228,7 +246,7 @@ bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline,
return false;
}
Mlt::Playlist playlist(*sub_track);
constructTrackFromMelt(timeline, tid, playlist, binIdCorresp, undo, redo, audioTrack, originalDecimalPoint, progressDialog);
constructTrackFromMelt(timeline, tid, playlist, binIdCorresp, undo, redo, audioTrack, originalDecimalPoint, i, mixList, progressDialog);
if (i == 0) {
// Pass track properties
int height = track.get_int("kdenlive:trackheight");
......@@ -252,6 +270,9 @@ bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline,
}
}
}
for (auto compo : compositions) {
timeline->plantMix(tid, *compo);
}
std::shared_ptr<Mlt::Service> serv = std::make_shared<Mlt::Service>(track.get_service());
timeline->importTrackEffects(tid, serv);
return true;
......@@ -289,9 +310,10 @@ PlaylistState::ClipState inferState(const std::shared_ptr<Mlt::Producer> &prod,
} // namespace
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, QString originalDecimalPoint, QProgressDialog *progressDialog)
const std::unordered_map<QString, QString> &binIdCorresp, Fun &undo, Fun &redo, bool audioTrack, QString originalDecimalPoint, int playlist, QMap <int, int> mixList, QProgressDialog *progressDialog)
{
int max = track.count();
qDebug()<<"=====GOT MIXLIST FOR TID:\n"<<mixList<<"\n\n______________________________________________________";
for (int i = 0; i < max; i++) {
if (track.is_blank(i)) {
continue;
......@@ -341,7 +363,13 @@ bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline,
int cid = -1;
if (pCore->bin()->getBinClip(binId)) {
PlaylistState::ClipState st = inferState(clip, audioTrack);
cid = ClipModel::construct(timeline, binId, clip, st, tid, originalDecimalPoint);
qDebug()<<"==== INSERTING CLIP IN PLAYLIST: "<<playlist<<"\n8888888888888888888888";
int mixDuration = 0;
if (mixList.contains(position)) {
// Clip has a mix
mixDuration = mixList.value(position) - position;
}
cid = ClipModel::construct(timeline, binId, clip, st, tid, originalDecimalPoint, playlist, mixDuration);
ok = timeline->requestClipMove(cid, tid, position, true, true, false, true, undo, redo);
} else {
qDebug() << "// Cannot find bin clip: " << binId << " - " << clip->get("id");
......
......@@ -101,7 +101,7 @@ void ClipModel::allSnaps(std::vector<int> &snaps, int offset)
}
int ClipModel::construct(const std::shared_ptr<TimelineModel> &parent, const QString &binClipId, const std::shared_ptr<Mlt::Producer> &producer,
PlaylistState::ClipState state, int tid, QString originalDecimalPoint)
PlaylistState::ClipState state, int tid, QString originalDecimalPoint, int playlist, int mixDuration)
{
// we hand the producer to the bin clip, and in return we get a cut to a good master producer
......@@ -129,6 +129,8 @@ int ClipModel::construct(const std::shared_ptr<TimelineModel> &parent, const QSt
result.first->parent().set("warp_pitch", 1);
}
clip->setClipState_lambda(state)();
clip->setSubPlaylistIndex(playlist);
clip->setMixDuration(mixDuration);
parent->registerClip(clip);
clip->m_effectStack->importEffects(producer, state, result.second, originalDecimalPoint);
clip->m_clipMarkerModel->setReferenceModel(binClip->getMarkerModel(), speed);
......
......@@ -65,7 +65,7 @@ public:
Note that there is no guarantee that this producer is actually going to be used. It might be discarded.
*/
static int construct(const std::shared_ptr<TimelineModel> &parent, const QString &binClipId, const std::shared_ptr<Mlt::Producer> &producer,
PlaylistState::ClipState state, int tid, QString originalDecimalPoint);
PlaylistState::ClipState state, int tid, QString originalDecimalPoint, int playlist = 0, int mixDuration = 0);
/** @brief returns a property of the clip, or from it's parent if it's a cut
*/
......
......@@ -654,16 +654,6 @@ bool TimelineModel::requestClipMove(int clipId, int trackId, int position, bool
std::pair<MixInfo, MixInfo> mixData = getTrackById_const(old_trackId)->getMixInfo(clipId);
if (mixData.first.firstClipId > -1) {
// We have a mix at clip start
bool mixGroupMove = false;
if (m_groups->isInGroup(clipId)) {
int parentGroup = m_groups->getRootId(clipId);
if (parentGroup > -1) {
std::unordered_set<int> sub = m_groups->getLeaves(parentGroup);
if (sub.count(mixData.first.firstClipId) > 0 && sub.count(mixData.first.secondClipId) > 0) {
mixGroupMove = true;
}
}
}
sync_mix = [this, old_trackId, finalMove]() {
getTrackById_const(old_trackId)->syncronizeMixes(finalMove);
return true;
......@@ -4504,3 +4494,9 @@ void TimelineModel::switchComposition(int cid, const QString &compoId)
undo();
}
}
void TimelineModel::plantMix(int tid, Mlt::Transition &t)
{
getTrackById_const(tid)->getTrackService()->plant_transition(t, 0, 1);
getTrackById_const(tid)->loadMix(t);
}
......@@ -417,6 +417,9 @@ public:
* @param compoId the name of the new composition we want to insert
*/
void switchComposition(int cid, const QString &compoId);
/** @brief Plant a same track composition in track tid
*/
void plantMix(int tid, Mlt::Transition &t);
protected:
/* @brief Creates a new clip instance without inserting it.
......
......@@ -1706,3 +1706,16 @@ bool TrackModel::hasMix(int cid) const
}
return false;
}
bool TrackModel::loadMix(Mlt::Transition &t)
{
//TODO: manage case where both mix clips would start at same position
int in = t.get_in();
int out = t.get_out();
int cid1 = getClipByPosition(in);
int cid2 = getClipByPosition(out);
std::shared_ptr<Mlt::Transition>tr(&t);
m_sameCompositions[cid2] = tr;
m_mixList.insert(cid1, cid2);
return true;
}
......@@ -132,6 +132,8 @@ public:
void syncronizeMixes(bool finalMove);
/** @brief Switch a clip from one playlist to the other */
bool switchPlaylist(int clipId, int position, int playlist);
/** @brief Load a same track transition from project */
bool loadMix(Mlt::Transition &t);
protected:
/* @brief This will lock the track: it will no longer allow insertion/deletion/resize of items
......
Markdown is supported
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