endInfo.startPos = d.startPos();
endInfo.endPos = m_dragItem->endPos() + (endInfo.startPos - startInfo.startPos);
endInfo.track = m_dragItem->track();
- MoveClipCommand *command = new MoveClipCommand(this, startInfo, endInfo, false, true);
+ MoveClipCommand *command = new MoveClipCommand(this, startInfo, endInfo, true);
m_commandStack->push(command);
} else {
//TODO: move transition
if (item->type() == AVWIDGET) {
ClipItem *clip = static_cast <ClipItem *>(item);
// We add a move clip command so that we get the correct producer for new track number
- /*if (clip->clipType() == AV || clip->clipType() == AUDIO)
- moveClip(clipinfo, clipinfo, true);*/
+ if (clip->clipType() == AV || clip->clipType() == AUDIO) {
+ m_document->renderer()->mltUpdateClipProducer((int)(m_scene->m_tracksList.count() - clipinfo.track), clipinfo.startPos.frames(m_document->fps()), clip->baseClip()->producer(clipinfo.track));
+ kDebug() << "// UPDATING CLIP TO TRACK PROD: " << clipinfo.track;
+ }
} else if (item->type() == TRANSITIONWIDGET) {
Transition *tr = static_cast <Transition *>(item);
int track = tr->transitionEndTrack();
ItemInfo clipinfo = clip->info();
kDebug() << "// CLIP TRK IS: " << clipinfo.track;
// We add a move clip command so that we get the correct producer for new track number
- /*if (clip->clipType() == AV || clip->clipType() == AUDIO)
- moveClip(clipinfo, clipinfo, true);*/
+ if (clip->clipType() == AV || clip->clipType() == AUDIO)
+ m_document->renderer()->mltUpdateClipProducer((int)(m_scene->m_tracksList.count() - clipinfo.track), clipinfo.startPos.frames(m_document->fps()), clip->baseClip()->producer(clipinfo.track));
} else if (children.at(i)->type() == TRANSITIONWIDGET) {
Transition *tr = static_cast <Transition *>(children.at(i));
tr->updateItem();
}
} else {
// undo last move and emit error message
- MoveClipCommand *command = new MoveClipCommand(this, info, m_dragItemInfo, false, true);
+ MoveClipCommand *command = new MoveClipCommand(this, info, m_dragItemInfo, true);
m_commandStack->push(command);
emit displayMessage(i18n("Cannot move clip to position %1seconds", QString::number(m_dragItemInfo.startPos.seconds(), 'g', 2)), ErrorMessage);
}
return getTransitionItemAt(framepos, track);
}
-void CustomTrackView::moveClip(const ItemInfo start, const ItemInfo end, bool forceProducer) {
+void CustomTrackView::moveClip(const ItemInfo start, const ItemInfo end) {
ClipItem *item = getClipItemAt((int) start.startPos.frames(m_document->fps()) + 1, start.track);
if (!item) {
emit displayMessage(i18n("Cannot move clip at time: %1s on track %2", QString::number(start.startPos.seconds(), 'g', 2), start.track), ErrorMessage);
}
//kDebug() << "---------------- Move CLIP FROM: " << startPos.x() << ", END:" << endPos.x() << ",TRACKS: " << startPos.y() << " TO " << endPos.y();
- bool success = m_document->renderer()->mltMoveClip((int)(m_scene->m_tracksList.count() - start.track), (int)(m_scene->m_tracksList.count() - end.track), (int) start.startPos.frames(m_document->fps()), (int)end.startPos.frames(m_document->fps()), item->baseClip()->producer(end.track), forceProducer);
+ bool success = m_document->renderer()->mltMoveClip((int)(m_scene->m_tracksList.count() - start.track), (int)(m_scene->m_tracksList.count() - end.track), (int) start.startPos.frames(m_document->fps()), (int)end.startPos.frames(m_document->fps()), item->baseClip()->producer(end.track));
if (success) {
item->setPos((int) end.startPos.frames(m_document->fps()), (int)(end.track * m_tracksHeight + 1));
if (item->baseClip()->isTransparent()) {
info.isBlind = false;
}
addTimelineTrack(ix, info);
+ m_document->setModified(true);
/*AddTrackCommand* command = new AddTrackCommand(this, ix, info, true, true);
m_commandStack->push(command);*/
}
if (ok) {
TrackInfo info = m_scene->m_tracksList.at(m_scene->m_tracksList.count() - ix);
deleteTimelineTrack(ix, info);
+ m_document->setModified(true);
/*AddTrackCommand* command = new AddTrackCommand(this, ix, info, false, true);
m_commandStack->push(command);*/
}
for (int i = 0; i < selection.count(); i++) {
if (selection.at(i)->type() == AVWIDGET) {
ClipItem *item = static_cast <ClipItem *>(selection.at(i));
- new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), item->info(), item->effectList(), false, false, deleteTrack);
+ new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), item->info(), item->effectList(), false, true, deleteTrack);
m_scene->removeItem(item);
delete item;
item = NULL;
void removeTrack(int ix);
int cursorPos();
void checkAutoScroll();
- void moveClip(const ItemInfo start, const ItemInfo end, bool forceProducer);
+ void moveClip(const ItemInfo start, const ItemInfo end);
/** move transition, startPos = (old start, old end), endPos = (new start, new end) */
void moveTransition(const ItemInfo start, const ItemInfo end);
void resizeClip(const ItemInfo start, const ItemInfo end);
}
void DocClipBase::updateAudioThumbnail(QMap<int, QMap<int, QByteArray> > data) {
- kDebug() << "CLIPBASE RECIEDVED AUDIO DATA*********************************************";
+ //kDebug() << "CLIPBASE RECIEDVED AUDIO DATA*********************************************";
audioFrameChache = data;
m_audioThumbCreated = true;
emit gotAudioData();
void DocClipBase::setProducer(Mlt::Producer *producer) {
if (producer == NULL) return;
QString id = producer->get("id");
- kDebug() << "// SET PRODUCER: " << id;
if (id.contains('_')) {
// this is a subtrack producer, insert it at correct place
int pos = id.section('_', 1, 1).toInt();
- kDebug() << "// POS = " << pos << ", MAX: " << m_baseTrackProducers.count();
if (pos >= m_baseTrackProducers.count()) {
while (m_baseTrackProducers.count() - 1 < pos) {
m_baseTrackProducers.append(NULL);
}
}
- kDebug() << "// POS = " << pos << ", NEW MAX: " << m_baseTrackProducers.count();
if (m_baseTrackProducers.at(pos) == NULL) m_baseTrackProducers[pos] = producer;
- } else m_baseTrackProducers.append(producer);
+ } else {
+ if (m_baseTrackProducers.isEmpty()) m_baseTrackProducers.append(producer);
+ else if (m_baseTrackProducers.at(0) == NULL) m_baseTrackProducers[0] = producer;
+ }
//m_clipProducer = producer;
//m_clipProducer->set("transparency", m_properties.value("transparency").toInt());
if (m_thumbProd && !m_thumbProd->hasProducer()) m_thumbProd->setProducer(producer);
}
Mlt::Producer *DocClipBase::producer(int track) {
+ for (int i = 0; i < m_baseTrackProducers.count(); i++) {
+ if (m_baseTrackProducers.at(i)) kDebug() << "// PROD: " << i << ", ID: " << m_baseTrackProducers.at(i)->get("id");
+ }
if (track == -1 || (m_clipType != AUDIO && m_clipType != AV)) {
if (m_baseTrackProducers.count() == 0) return NULL;
int i;
#include "moveclipcommand.h"
#include "customtrackview.h"
-MoveClipCommand::MoveClipCommand(CustomTrackView *view, const ItemInfo start, const ItemInfo end, bool forceProducer, bool doIt, QUndoCommand * parent) : QUndoCommand(parent), m_view(view), m_startPos(start), m_endPos(end), m_forceProducer(forceProducer), m_doIt(doIt) {
+MoveClipCommand::MoveClipCommand(CustomTrackView *view, const ItemInfo start, const ItemInfo end, bool doIt, QUndoCommand * parent) : QUndoCommand(parent), m_view(view), m_startPos(start), m_endPos(end), m_doIt(doIt) {
setText(i18n("Move clip"));
}
void MoveClipCommand::undo() {
// kDebug()<<"---- undoing action";
m_doIt = true;
- m_view->moveClip(m_endPos, m_startPos, m_forceProducer);
+ m_view->moveClip(m_endPos, m_startPos);
}
// virtual
void MoveClipCommand::redo() {
kDebug() << "---- redoing action";
if (m_doIt)
- m_view->moveClip(m_startPos, m_endPos, m_forceProducer);
+ m_view->moveClip(m_startPos, m_endPos);
m_doIt = true;
}
class MoveClipCommand : public QUndoCommand {
public:
- MoveClipCommand(CustomTrackView *view, const ItemInfo start, const ItemInfo end, bool forceProducer, bool doIt, QUndoCommand * parent = 0);
+ MoveClipCommand(CustomTrackView *view, const ItemInfo start, const ItemInfo end, bool doIt, QUndoCommand * parent = 0);
virtual void undo();
virtual void redo();
const ItemInfo m_startPos;
const ItemInfo m_endPos;
bool m_doIt;
- bool m_forceProducer;
};
#endif
return true;
}
-bool Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTime moveEnd, Mlt::Producer *prod, bool forceProducer) {
- return mltMoveClip(startTrack, endTrack, (int) moveStart.frames(m_fps), (int) moveEnd.frames(m_fps), prod, forceProducer);
+bool Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTime moveEnd, Mlt::Producer *prod) {
+ return mltMoveClip(startTrack, endTrack, (int) moveStart.frames(m_fps), (int) moveEnd.frames(m_fps), prod);
}
-bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd, Mlt::Producer *prod, bool forceProducer) {
+void Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod) {
+ kDebug() << "NEW PROD ID: " << prod->get("id");
+ m_mltConsumer->set("refresh", 0);
+ kDebug() << "// TRYING TO UPDATE CLIP at: " << pos << ", TK: " << track;
+ mlt_service_lock(m_mltConsumer->get_service());
+ Mlt::Service service(m_mltProducer->parent().get_service());
+ if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+ int clipIndex = trackPlaylist.get_clip_index_at(pos + 1);
+ Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
+ if (clipProducer.is_blank()) {
+ kDebug() << "// ERROR UPDATING CLIP PROD";
+ mlt_service_unlock(m_mltConsumer->get_service());
+ m_isBlocked = false;
+ return;
+ }
+ Mlt::Producer *clip = prod->cut(clipProducer.get_in(), clipProducer.get_out());
+
+ // move all effects to the correct producer
+ Mlt::Service clipService(clipProducer.get_service());
+ Mlt::Service newClipService(clip->get_service());
+
+ int ct = 0;
+ Mlt::Filter *filter = clipService.filter(ct);
+ while (filter) {
+ if (filter->get("kdenlive_ix") != 0) {
+ clipService.detach(*filter);
+ newClipService.attach(*filter);
+ } else ct++;
+ filter = clipService.filter(ct);
+ }
+
+ trackPlaylist.insert_at(pos, clip, 1);
+ mlt_service_unlock(m_mltConsumer->get_service());
+ m_isBlocked = false;
+}
+
+bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd, Mlt::Producer *prod) {
m_isBlocked = true;
m_mltConsumer->set("refresh", 0);
if (endTrack == startTrack) {
//mlt_service_lock(service.get_service());
Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
- if (forceProducer) {
- if (clipProducer.is_blank()) {
- kDebug() << "// ERROR RESTTING CLIP PROD: " << moveEnd << ", TRK: " << startTrack;
- mlt_service_unlock(m_mltConsumer->get_service());
- m_isBlocked = false;
- return false;
- }
- trackPlaylist.insert(clipProducer, moveEnd, clipProducer.get_in(), clipProducer.get_out());
+ if (!trackPlaylist.is_blank_at(moveEnd) || clipProducer.is_blank()) {
+ // error, destination is not empty
+ //int ix = trackPlaylist.get_clip_index_at(moveEnd);
+ kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd;
+ mlt_service_unlock(m_mltConsumer->get_service());
+ m_isBlocked = false;
+ return false;
} else {
- if (!trackPlaylist.is_blank_at(moveEnd) || clipProducer.is_blank()) {
- // error, destination is not empty
- //int ix = trackPlaylist.get_clip_index_at(moveEnd);
- kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd;
- mlt_service_unlock(m_mltConsumer->get_service());
- m_isBlocked = false;
- return false;
- } else {
- trackPlaylist.consolidate_blanks(0);
- int newIndex = trackPlaylist.insert_at(moveEnd, clipProducer, 1);
- /*if (QString(clipProducer.parent().get("transparency")).toInt() == 1) {
- mltMoveTransparency(moveStart, moveEnd, startTrack, endTrack, QString(clipProducer.parent().get("id")).toInt());
- }*/
- if (newIndex + 1 == trackPlaylist.count()) checkLength = true;
- }
+ trackPlaylist.consolidate_blanks(0);
+ int newIndex = trackPlaylist.insert_at(moveEnd, clipProducer, 1);
+ /*if (QString(clipProducer.parent().get("transparency")).toInt() == 1) {
+ mltMoveTransparency(moveStart, moveEnd, startTrack, endTrack, QString(clipProducer.parent().get("id")).toInt());
+ }*/
+ if (newIndex + 1 == trackPlaylist.count()) checkLength = true;
}
//mlt_service_unlock(service.get_service());
} else {
void Render::mltDeleteTrack(int ix) {
QDomDocument doc;
doc.setContent(sceneList(), false);
+ int tracksCount = doc.elementsByTagName("track").count() - 1;
QDomNode track = doc.elementsByTagName("track").at(ix);
QDomNode tractor = doc.elementsByTagName("tractor").at(0);
+ QDomNodeList transitions = doc.elementsByTagName("transition");
+ for (int i = 0; i < transitions.count(); i++) {
+ QDomElement e = transitions.at(i).toElement();
+ QDomNodeList props = e.elementsByTagName("property");
+ QMap <QString, QString> mappedProps;
+ for (int j = 0; j < props.count(); j++) {
+ QDomElement f = props.at(j).toElement();
+ mappedProps.insert(f.attribute("name"), f.firstChild().nodeValue());
+ }
+ if (mappedProps.value("mlt_service") == "mix" && mappedProps.value("b_track").toInt() == tracksCount) {
+ tractor.removeChild(transitions.at(i));
+ } else if (mappedProps.value("mlt_service") != "mix" && mappedProps.value("b_track").toInt() >= ix) {
+ // Transition needs to be moved
+ int a_track = mappedProps.value("a_track").toInt();
+ int b_track = mappedProps.value("b_track").toInt();
+ if (a_track > 0) a_track --;
+ if (b_track > 0) b_track --;
+ for (int j = 0; j < props.count(); j++) {
+ QDomElement f = props.at(j).toElement();
+ if (f.attribute("name") == "a_track") f.firstChild().setNodeValue(QString::number(a_track));
+ else if (f.attribute("name") == "b_track") f.firstChild().setNodeValue(QString::number(b_track));
+ }
+
+ }
+ }
tractor.removeChild(track);
setSceneList(doc.toString(), m_framePosition);
return;
int mltGetSpaceLength(const GenTime pos, int track);
bool mltResizeClipEnd(ItemInfo info, GenTime clipDuration);
bool mltResizeClipStart(ItemInfo info, GenTime diff);
- bool mltMoveClip(int startTrack, int endTrack, GenTime pos, GenTime moveStart, Mlt::Producer *prod, bool forceProducer = false);
- bool mltMoveClip(int startTrack, int endTrack, int pos, int moveStart, Mlt::Producer *prod, bool forceProducer = false);
+ bool mltMoveClip(int startTrack, int endTrack, GenTime pos, GenTime moveStart, Mlt::Producer *prod);
+ bool mltMoveClip(int startTrack, int endTrack, int pos, int moveStart, Mlt::Producer *prod);
bool mltRemoveClip(int track, GenTime position);
bool mltRemoveEffect(int track, GenTime position, QString index, bool doRefresh = true);
bool mltAddEffect(int track, GenTime position, QHash <QString, QString> args, bool doRefresh = true);
void mltResizeTransparency(int oldStart, int newStart, int newEnd, int track, int id);
void mltInsertTrack(int ix);
void mltDeleteTrack(int ix);
+ void mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod);
/** Change speed of a clip in playlist. To do this, we create a new "framebuffer" producer.
This new producer must have its "resource" param set to: video.mpg?0.6 where video.mpg is the path