...
 
Commits (5)
......@@ -534,31 +534,35 @@ void ProjectClip::createDisabledMasterProducer()
m_effectStack->addService(m_disabledProducer);
}
}
std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int clipId, PlaylistState::ClipState state, double speed)
std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int trackId, int clipId, PlaylistState::ClipState state, double speed)
{
if (!m_masterProducer) {
return nullptr;
}
if (qFuzzyCompare(speed, 1.0)) {
// we are requesting a normal speed producer
// We can first cleen the speed producers we have for the current id
if (trackId == -1) {
// Temporary copy, return clone of master
return std::shared_ptr<Mlt::Producer>(m_masterProducer->cut());
}
if (m_timewarpProducers.count(clipId) > 0) {
m_effectStack->removeService(m_timewarpProducers[clipId]);
m_timewarpProducers.erase(clipId);
}
if (state == PlaylistState::AudioOnly) {
// We need to get an audio producer, if none exists
if (m_audioProducers.count(clipId) == 0) {
m_audioProducers[clipId] = cloneProducer(true);
m_audioProducers[clipId]->set("set.test_audio", 0);
m_audioProducers[clipId]->set("set.test_image", 1);
m_effectStack->addService(m_audioProducers[clipId]);
if (m_audioProducers.count(trackId) == 0) {
m_audioProducers[trackId] = cloneProducer(true);
m_audioProducers[trackId]->set("set.test_audio", 0);
m_audioProducers[trackId]->set("set.test_image", 1);
m_effectStack->addService(m_audioProducers[trackId]);
}
return std::shared_ptr<Mlt::Producer>(m_audioProducers[clipId]->cut());
return std::shared_ptr<Mlt::Producer>(m_audioProducers[trackId]->cut());
}
if (m_audioProducers.count(clipId) > 0) {
m_effectStack->removeService(m_audioProducers[clipId]);
m_audioProducers.erase(clipId);
if (m_audioProducers.count(trackId) > 0) {
m_effectStack->removeService(m_audioProducers[trackId]);
m_audioProducers.erase(trackId);
}
if (state == PlaylistState::VideoOnly) {
// we return the video producer
......@@ -567,18 +571,18 @@ std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int clipId, Play
int duration = m_masterProducer->time_to_frames(m_masterProducer->get("kdenlive:duration"));
return std::shared_ptr<Mlt::Producer>(m_masterProducer->cut(-1, duration > 0 ? duration : -1));
}
if (m_videoProducers.count(clipId) == 0) {
m_videoProducers[clipId] = cloneProducer(true);
m_videoProducers[clipId]->set("set.test_audio", 1);
m_videoProducers[clipId]->set("set.test_image", 0);
m_effectStack->addService(m_videoProducers[clipId]);
if (m_videoProducers.count(trackId) == 0) {
m_videoProducers[trackId] = cloneProducer(true);
m_videoProducers[trackId]->set("set.test_audio", 1);
m_videoProducers[trackId]->set("set.test_image", 0);
m_effectStack->addService(m_videoProducers[trackId]);
}
int duration = m_masterProducer->time_to_frames(m_masterProducer->get("kdenlive:duration"));
return std::shared_ptr<Mlt::Producer>(m_videoProducers[clipId]->cut(-1, duration > 0 ? duration : -1));
return std::shared_ptr<Mlt::Producer>(m_videoProducers[trackId]->cut(-1, duration > 0 ? duration : -1));
}
if (m_videoProducers.count(clipId) > 0) {
m_effectStack->removeService(m_videoProducers[clipId]);
m_videoProducers.erase(clipId);
if (m_videoProducers.count(trackId) > 0) {
m_effectStack->removeService(m_videoProducers[trackId]);
m_videoProducers.erase(trackId);
}
Q_ASSERT(state == PlaylistState::Disabled);
createDisabledMasterProducer();
......@@ -586,16 +590,7 @@ std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int clipId, Play
return std::shared_ptr<Mlt::Producer>(m_disabledProducer->cut(-1, duration > 0 ? duration : -1));
}
// in that case, we need to create a warp producer, if we don't have one
if (m_audioProducers.count(clipId) > 0) {
m_effectStack->removeService(m_audioProducers[clipId]);
m_audioProducers.erase(clipId);
}
if (m_videoProducers.count(clipId) > 0) {
m_effectStack->removeService(m_videoProducers[clipId]);
m_videoProducers.erase(clipId);
}
// For timewarp clips, we keep one separate producer for each clip.
std::shared_ptr<Mlt::Producer> warpProducer;
if (m_timewarpProducers.count(clipId) > 0) {
// remove in all cases, we add it unconditionally anyways
......@@ -656,7 +651,7 @@ std::pair<std::shared_ptr<Mlt::Producer>, bool> ProjectClip::giveMasterAndGetTim
if (state != PlaylistState::Disabled || timeWarp) {
// In that case, we must create copies
std::shared_ptr<Mlt::Producer> prod(getTimelineProducer(clipId, state, speed)->cut(in, out));
std::shared_ptr<Mlt::Producer> prod(getTimelineProducer(-1, clipId, state, speed)->cut(in, out));
return {prod, false};
}
if (state == PlaylistState::Disabled && !m_disabledProducer) {
......@@ -704,7 +699,7 @@ std::pair<std::shared_ptr<Mlt::Producer>, bool> ProjectClip::giveMasterAndGetTim
if (QString::fromUtf8(master->parent().get("mlt_service")) == QLatin1String("timewarp")) {
speed = master->get_double("warp_speed");
}
return {getTimelineProducer(clipId, state, speed), false};
return {getTimelineProducer(-1, clipId, state, speed), false};
}
// we have a problem
return {std::shared_ptr<Mlt::Producer>(ClipController::mediaUnavailable->cut()), false};
......
......@@ -202,7 +202,7 @@ public:
/** @brief This function returns a cut to the master producer associated to the timeline clip with given ID.
Each clip must have a different master producer (see comment of the class)
*/
std::shared_ptr<Mlt::Producer> getTimelineProducer(int clipId, PlaylistState::ClipState st, double speed = 1.0);
std::shared_ptr<Mlt::Producer> getTimelineProducer(int trackId, int clipId, PlaylistState::ClipState st, double speed = 1.0);
/* @brief This function should only be used at loading. It takes a producer that was read from mlt, and checks whether the master producer is already in
use. If yes, then we must create a new one, because of the mixing bug. In any case, we return a cut of the master that can be used in the timeline The
......
......@@ -75,7 +75,7 @@ int ClipModel::construct(const std::shared_ptr<TimelineModel> &parent, const QSt
videoAudio.first = videoAudio.first && binClip->hasVideo();
videoAudio.second = videoAudio.second && binClip->hasAudio();
state = stateFromBool(videoAudio);
std::shared_ptr<Mlt::Producer> cutProducer = binClip->getTimelineProducer(id, state, speed);
std::shared_ptr<Mlt::Producer> cutProducer = binClip->getTimelineProducer(-1, id, state, speed);
std::shared_ptr<ClipModel> clip(new ClipModel(parent, cutProducer, binClipId, id, state, speed));
clip->setClipState_lambda(state)();
parent->registerClip(clip);
......@@ -379,7 +379,7 @@ void ClipModel::refreshProducerFromBin(PlaylistState::ClipState state, double sp
qDebug() << "changing speed" << in << out << m_speed;
}
std::shared_ptr<ProjectClip> binClip = pCore->projectItemModel()->getClipByBinID(m_binClipId);
std::shared_ptr<Mlt::Producer> binProducer = binClip->getTimelineProducer(m_id, state, m_speed);
std::shared_ptr<Mlt::Producer> binProducer = binClip->getTimelineProducer(m_currentTrackId, m_id, state, m_speed);
m_producer = std::move(binProducer);
m_producer->set_in_and_out(in, out);
// replant effect stack in updated service
......@@ -510,6 +510,17 @@ void ClipModel::setShowKeyframes(bool show)
service()->set("kdenlive:hide_keyframes", (int)!show);
}
void ClipModel::setCurrentTrackId(int tid, bool finalMove)
{
if (tid == m_currentTrackId) {
return;
}
MoveableItem::setCurrentTrackId(tid, finalMove);
if (finalMove) {
refreshProducerFromBin(m_currentState);
}
}
Fun ClipModel::setClipState_lambda(PlaylistState::ClipState state)
{
QWriteLocker locker(&m_lock);
......
......@@ -157,6 +157,8 @@ protected:
*/
bool requestResize(int size, bool right, Fun &undo, Fun &redo, bool logUndo = true) override;
void setCurrentTrackId(int tid, bool finalMove = true) override;
/* @brief This function change the global (timeline-wise) enabled state of the effects
*/
void setTimelineEffectsEnabled(bool enabled);
......
......@@ -244,8 +244,9 @@ void CompositionModel::setInOut(int in, int out)
setPosition(in);
}
void CompositionModel::setCurrentTrackId(int tid)
void CompositionModel::setCurrentTrackId(int tid, bool finalMove)
{
Q_UNUSED(finalMove);
MoveableItem::setCurrentTrackId(tid);
}
......
......@@ -99,7 +99,7 @@ public:
protected:
Mlt::Transition *service() const override;
void setInOut(int in, int out) override;
void setCurrentTrackId(int tid) override;
void setCurrentTrackId(int tid, bool finalMove = true) override;
int getOut() const override;
int getIn() const override;
......
......@@ -105,7 +105,7 @@ protected:
If you wish to actually change the track the item, use the slot in the timeline
slot.
*/
virtual void setCurrentTrackId(int tid);
virtual void setCurrentTrackId(int tid, bool finalMove = true);
/* Set in and out of service */
virtual void setInOut(int in, int out);
......
......@@ -81,8 +81,9 @@ template <typename Service> void MoveableItem<Service>::setPosition(int pos)
m_position = pos;
}
template <typename Service> void MoveableItem<Service>::setCurrentTrackId(int tid)
template <typename Service> void MoveableItem<Service>::setCurrentTrackId(int tid, bool finalMove)
{
Q_UNUSED(finalMove);
QWriteLocker locker(&m_lock);
m_currentTrackId = tid;
}
......
......@@ -2682,9 +2682,9 @@ void TimelineModel::requestClipReload(int clipId)
bool refreshView = oldOut > (int)binClip->frameDuration();
if (old_trackId != -1) {
getTrackById(old_trackId)->requestClipDeletion(clipId, refreshView, true, local_undo, local_redo);
}
m_allClips[clipId]->refreshProducerFromBin();
}
if (old_trackId != -1) {
m_allClips[clipId]->refreshProducerFromBin();
getTrackById(old_trackId)->requestClipInsertion(clipId, oldPos, refreshView, true, local_undo, local_redo);
}
}
......
......@@ -134,7 +134,7 @@ Fun TrackModel::requestClipInsertion_lambda(int clipId, int position, bool updat
m_allClips[clip->getId()] = clip; // store clip
// update clip position and track
clip->setPosition(position);
clip->setCurrentTrackId(m_id);
clip->setCurrentTrackId(m_id, finalMove);
int new_in = clip->getPosition();
int new_out = new_in + clip->getPlaytime();
ptr->m_snaps->addPoint(new_in);
......@@ -164,6 +164,7 @@ Fun TrackModel::requestClipInsertion_lambda(int clipId, int position, bool updat
// Lock MLT playlist so that we don't end up with an invalid frame being displayed
m_playlists[0].lock();
std::shared_ptr<ClipModel> clip = ptr->getClipPtr(clipId);
clip->setCurrentTrackId(m_id, finalMove);
int index = m_playlists[0].insert_at(position, *clip, 1);
m_playlists[0].consolidate_blanks();
m_playlists[0].unlock();
......@@ -189,6 +190,7 @@ Fun TrackModel::requestClipInsertion_lambda(int clipId, int position, bool updat
// Lock MLT playlist so that we don't end up with an invalid frame being displayed
m_playlists[0].lock();
std::shared_ptr<ClipModel> clip = ptr->getClipPtr(clipId);
clip->setCurrentTrackId(m_id);
int index = m_playlists[0].insert_at(position, *clip, 1);
m_playlists[0].consolidate_blanks();
m_playlists[0].unlock();
......