Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

* new: crash recovery feature

* fix project file corruption when the same clip was inserted several time

svn path=/branches/KDE4/; revision=2319
parent 7b4db988
......@@ -932,8 +932,11 @@ void CustomTrackView::dropEvent(QDropEvent * event) {
m_commandStack->push(command);
m_dropItem->baseClip()->addReference();
m_document->updateClip(m_dropItem->baseClip()->getId());
ItemInfo info;
info = m_dropItem->info();
info.track = m_tracksList.count() - m_dropItem->track();
// kDebug()<<"IIIIIIIIIIIIIIIIIIIIIIII TRAX CNT: "<<m_tracksList.count()<<", DROP: "<<m_dropItem->track();
m_document->renderer()->mltInsertClip(m_tracksList.count() - m_dropItem->track(), m_dropItem->startPos(), m_dropItem->cropStart(), m_dropItem->xml());
m_document->renderer()->mltInsertClip(info, m_dropItem->xml());
m_document->setModified(true);
} else QGraphicsView::dropEvent(event);
m_dropItem = NULL;
......@@ -1125,7 +1128,9 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) {
if (item->type() == AVWIDGET) {
ClipItem *clip = static_cast <ClipItem*>(item);
new AddTimelineClipCommand(this, clip->xml(), clip->clipProducer(), item->info(), false, false, moveClips);
m_document->renderer()->mltInsertClip(m_tracksList.count() - item->track(), item->startPos(), item->cropStart(), clip->xml());
ItemInfo info = item->info();
info.track = m_tracksList.count() - item->track();
m_document->renderer()->mltInsertClip(info, clip->xml());
} else {
Transition *tr = static_cast <Transition*>(item);
ItemInfo transitionInfo = tr->info();
......@@ -1257,10 +1262,10 @@ void CustomTrackView::deleteSelectedClips() {
deleteSelected->setText("Delete selected items");
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i)->type() == AVWIDGET) {
ClipItem *item = static_cast <ClipItem *> (itemList.at(i));
ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), item->info(), true, true, deleteSelected);
} else if (itemList.at(i)->type() == TRANSITIONWIDGET) {
Transition *item = static_cast <Transition *> (itemList.at(i));
Transition *item = static_cast <Transition *>(itemList.at(i));
ItemInfo info;
info.startPos = item->startPos();
info.endPos = item->endPos();
......@@ -1295,7 +1300,8 @@ void CustomTrackView::addClip(QDomElement xml, int clipId, ItemInfo info) {
scene()->addItem(item);
baseclip->addReference();
m_document->updateClip(baseclip->getId());
m_document->renderer()->mltInsertClip(m_tracksList.count() - info.track, info.startPos, info.cropStart, xml);
info.track = m_tracksList.count() - info.track;
m_document->renderer()->mltInsertClip(info, xml);
m_document->renderer()->doRefresh();
}
......@@ -1307,7 +1313,9 @@ void CustomTrackView::slotUpdateClip(int clipId) {
clip = static_cast <ClipItem *>(list.at(i));
if (clip->clipProducer() == clipId) {
clip->refreshClip();
m_document->renderer()->mltUpdateClip(m_tracksList.count() - clip->track(), clip->startPos(), clip->cropStart(), clip->xml());
ItemInfo info = clip->info();
info.track = m_tracksList.count() - clip->track();
m_document->renderer()->mltUpdateClip(info, clip->xml());
}
}
}
......@@ -1725,6 +1733,7 @@ void CustomTrackView::editGuide(const GenTime oldPos, const GenTime pos, const Q
}
if (!found) emit displayMessage(i18n("No guide at cursor time"), ErrorMessage);
}
m_document->syncGuides(m_guides);
}
bool CustomTrackView::addGuide(const GenTime pos, const QString &comment) {
......@@ -1737,6 +1746,7 @@ bool CustomTrackView::addGuide(const GenTime pos, const QString &comment) {
Guide *g = new Guide(this, pos, comment, m_scale, m_document->fps(), m_tracksHeight * m_tracksList.count());
scene()->addItem(g);
m_guides.append(g);
m_document->syncGuides(m_guides);
return true;
}
......@@ -1859,19 +1869,6 @@ void CustomTrackView::drawBackground(QPainter * painter, const QRectF & rect) {
painter->fillRect(QRectF(rectInView.left(), lowerLimit, rectInView.width(), height() - lowerLimit), QBrush(base));
}
QDomElement CustomTrackView::xmlInfo() {
QDomDocument doc;
QDomElement e;
QDomElement guides = doc.createElement("guides");
for (int i = 0; i < m_guides.count(); i++) {
e = doc.createElement("guide");
e.setAttribute("time", m_guides.at(i)->position().ms() / 1000);
e.setAttribute("comment", m_guides.at(i)->label());
guides.appendChild(e);
}
return guides;
}
bool CustomTrackView::findString(const QString &text) {
QString marker;
for (int i = 0; i < m_searchPoints.size(); ++i) {
......
......@@ -84,7 +84,6 @@ public:
void slotSeekToPreviousSnap();
void slotSeekToNextSnap();
double getSnapPointForPos(double pos);
QDomElement xmlInfo();
void editKeyFrame(const GenTime pos, const int track, const int index, const QString keyframes);
bool findString(const QString &text);
bool findNextString(const QString &text);
......
......@@ -36,6 +36,7 @@
#include "titlewidget.h"
#include "mainwindow.h"
KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, MltVideoProfile profile, QUndoGroup *undoGroup, MainWindow *parent): QObject(parent), m_render(NULL), m_url(url), m_projectFolder(projectFolder), m_profile(profile), m_fps((double)profile.frame_rate_num / profile.frame_rate_den), m_width(profile.width), m_height(profile.height), m_commandStack(new KUndoStack(undoGroup)), m_modified(false), m_documentLoadingProgress(0), m_documentLoadingStep(0.0), m_startPos(0) {
kDebug() << "// init profile, ratnum: " << profile.frame_rate_num << ", " << profile.frame_rate_num << ", width: " << profile.width;
m_clipManager = new ClipManager(this);
......@@ -199,11 +200,44 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, MltVideoPro
kDebug() << "KDEnnlive document, init timecode: " << m_fps;
if (m_fps == 30000.0 / 1001.0) m_timecode.setFormat(30, true);
else m_timecode.setFormat((int) m_fps);
m_autoSaveTimer = new QTimer(this);
m_autoSaveTimer->setSingleShot(true);
QString directory = m_url.directory();
QString fileName = m_url.fileName();
m_recoveryUrl.setDirectory(directory);
m_recoveryUrl.setFileName("~" + fileName);
connect(m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave()));
}
KdenliveDoc::~KdenliveDoc() {
delete m_commandStack;
delete m_clipManager;
delete m_autoSaveTimer;
if (!m_url.isEmpty()) {
// remove backup file
if (KIO::NetAccess::exists(m_recoveryUrl, KIO::NetAccess::SourceSide, NULL))
KIO::NetAccess::del(m_recoveryUrl, NULL);
}
}
void KdenliveDoc::syncGuides(QList <Guide *> guides) {
QDomDocument doc;
QDomElement e;
m_guidesXml.clear();
m_guidesXml = doc.createElement("guides");
for (int i = 0; i < guides.count(); i++) {
e = doc.createElement("guide");
e.setAttribute("time", guides.at(i)->position().ms() / 1000);
e.setAttribute("comment", guides.at(i)->label());
m_guidesXml.appendChild(e);
}
}
void KdenliveDoc::slotAutoSave() {
if (m_render)
m_render->saveSceneList(m_recoveryUrl.path(), documentInfoXml());
}
void KdenliveDoc::convertDocument(double version) {
......@@ -313,7 +347,7 @@ void KdenliveDoc::convertDocument(double version) {
//kDebug() << "///////////////// END CONVERTED DOC:";
}
QDomElement KdenliveDoc::documentInfoXml(QDomElement timelineInfo) {
QDomElement KdenliveDoc::documentInfoXml() {
QDomDocument doc;
QDomElement e;
QDomElement addedXml = doc.createElement("kdenlivedoc");
......@@ -336,7 +370,7 @@ QDomElement KdenliveDoc::documentInfoXml(QDomElement timelineInfo) {
}
}
addedXml.appendChild(markers);
addedXml.appendChild(doc.importNode(timelineInfo, true));
if (!m_guidesXml.isNull()) addedXml.appendChild(doc.importNode(m_guidesXml, true));
//kDebug() << m_document.toString();
return addedXml;
}
......@@ -494,9 +528,16 @@ KUrl KdenliveDoc::url() const {
void KdenliveDoc::setUrl(KUrl url) {
m_url = url;
QString directory = m_url.directory();
QString fileName = m_url.fileName();
m_recoveryUrl.setDirectory(directory);
m_recoveryUrl.setFileName("~" + fileName);
}
void KdenliveDoc::setModified(bool mod) {
if (!m_url.isEmpty() && mod && KdenliveSettings::crashrecovery()) {
m_autoSaveTimer->start(3000);
}
if (mod == m_modified) return;
m_modified = mod;
emit docModified(m_modified);
......
......@@ -27,6 +27,7 @@
#include <QList>
#include <QObject>
#include <QUndoGroup>
#include <QTimer>
#include <KUndoStack>
#include <kurl.h>
......@@ -34,6 +35,7 @@
#include "gentime.h"
#include "timecode.h"
#include "definitions.h"
#include "guide.h"
class Render;
class ClipManager;
......@@ -59,6 +61,7 @@ Q_OBJECT public:
void setProducerDuration(int id, int duration);
int getProducerDuration(int id);
Render *renderer();
QDomElement m_guidesXml;
ClipManager *clipManager();
void addClip(const QDomElement &elem, const int clipId);
void addFolder(const QString foldername, int clipId, bool edit);
......@@ -84,7 +87,7 @@ Q_OBJECT public:
/** Returns the document format: PAL or NTSC */
QString getDocumentStandard();
void setUrl(KUrl url);
QDomElement documentInfoXml(QDomElement timelineInfo);
QDomElement documentInfoXml();
void setProfilePath(QString path);
/** Set to true if document needs saving, false otherwise */
void setModified(bool mod);
......@@ -96,9 +99,11 @@ Q_OBJECT public:
/** Used to inform main app of the current document loading progress */
void loadingProgressed();
void updateAllProjectClips();
void syncGuides(QList <Guide *> guides);
private:
KUrl m_url;
KUrl m_recoveryUrl;
QDomDocument m_document;
QString m_projectName;
double m_fps;
......@@ -113,6 +118,7 @@ private:
ClipManager *m_clipManager;
MltVideoProfile m_profile;
QString m_scenelist;
QTimer *m_autoSaveTimer;
/** tells whether current doc has been changed since last save event */
bool m_modified;
/** Project folder, used to store project files (titles, effects,...) */
......@@ -124,6 +130,9 @@ private:
public slots:
void slotCreateTextClip(QString group, int groupId);
private slots:
void slotAutoSave();
signals:
void addProjectClip(DocClipBase *);
void addProjectFolder(const QString, int, bool, bool edit = false);
......
......@@ -9,6 +9,11 @@
<default>false</default>
</entry>
<entry name="crashrecovery" type="Bool">
<label>Auto save document in backup file on each change.</label>
<default>true</default>
</entry>
<entry name="color_duration" type="String">
<label>Default color clip duration.</label>
<default>00:00:05:00</default>
......
......@@ -48,6 +48,7 @@
#include <KMenu>
#include <locale.h>
#include <ktogglefullscreenaction.h>
#include <KFileItem>
#include <mlt++/Mlt.h>
......@@ -280,6 +281,7 @@ bool MainWindow::queryClose() {
switch (KMessageBox::warningYesNoCancel(this, i18n("Save changes to document ?"))) {
case KMessageBox::Yes :
// save document here. If saving fails, return false;
saveFile();
return true;
case KMessageBox::No :
return true;
......@@ -750,7 +752,7 @@ void MainWindow::slotRemoveTab() {
}
void MainWindow::saveFileAs(const QString &outputFileName) {
m_projectMonitor->saveSceneList(outputFileName, m_activeDocument->documentInfoXml(m_activeTimeline->projectView()->xmlInfo()));
m_projectMonitor->saveSceneList(outputFileName, m_activeDocument->documentInfoXml());
m_activeDocument->setUrl(KUrl(outputFileName));
setCaption(m_activeDocument->description());
m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description());
......@@ -776,7 +778,7 @@ void MainWindow::saveFile() {
}
}
void MainWindow::openFile() { //changed
void MainWindow::openFile() {
KUrl url = KFileDialog::getOpenUrl(KUrl(), "*.kdenlive|Kdenlive project files (*.kdenlive)\n*.westley|MLT project files (*.westley)");
if (url.isEmpty()) return;
m_fileOpenRecent->addUrl(url);
......@@ -789,11 +791,32 @@ void MainWindow::openLastFile() {
openFile(KUrl(Lastproject));
}
void MainWindow::openFile(const KUrl &url) { //new
void MainWindow::openFile(const KUrl &url) {
// Check for backup file
bool recovery = false;
QString directory = url.directory();
QString fileName = url.fileName();
KUrl recoveryUrl;
recoveryUrl.setDirectory(directory);
recoveryUrl.setFileName("~" + fileName);
if (KIO::NetAccess::exists(recoveryUrl, KIO::NetAccess::SourceSide, this)) {
KFileItem bkup(KFileItem::Unknown, KFileItem::Unknown, recoveryUrl, true);
KFileItem src(KFileItem::Unknown, KFileItem::Unknown, url, true);
if (bkup.time(KFileItem::ModificationTime) > src.time(KFileItem::ModificationTime)) {
// Backup file is more recent than source file, ask user for recovery
if (KMessageBox::questionYesNo(this, i18n("A newer recovery file exists for <b>%1</b>\nOpen recovery file ?", url.fileName())) == KMessageBox::Yes) recovery = true;
}
}
//TODO: get video profile from url before opening it
MltVideoProfile prof = ProfilesDialog::getVideoProfile(KdenliveSettings::default_profile());
if (prof.width == 0) prof = ProfilesDialog::getVideoProfile("dv_pal");
KdenliveDoc *doc = new KdenliveDoc(url, KUrl(), prof, m_commandStack, this);
KdenliveDoc *doc;
if (recovery) {
doc = new KdenliveDoc(recoveryUrl, KUrl(), prof, m_commandStack, this);
doc->setUrl(url);
doc->setModified(true);
} else doc = new KdenliveDoc(url, KUrl(), prof, m_commandStack, this);
connectDocumentInfo(doc);
TrackView *trackView = new TrackView(doc, this);
m_timelineArea->setCurrentIndex(m_timelineArea->addTab(trackView, KIcon("kdenlive"), doc->description()));
......
......@@ -310,9 +310,13 @@ void ProjectList::slotUpdateClip(int id) {
void ProjectList::slotAddClip(QUrl givenUrl, QString group) {
if (!m_commandStack) kDebug() << "!!!!!!!!!!!!!!!!  NO CMD STK";
KUrl::List list;
if (givenUrl.isEmpty())
list = KFileDialog::getOpenUrls(KUrl(), "application/vnd.kde.kdenlive application/vnd.westley.scenelist application/flv application/vnd.rn-realmedia video/x-dv video/x-msvideo video/mpeg video/x-ms-wmv audio/mpeg audio/x-mp3 audio/x-wav application/ogg *.m2t *.mts *.dv video/mp4 video/quicktime image/gif image/jpeg image/png image/x-bmp image/svg+xml image/tiff image/x-xcf-gimp image/x-vnd.adobe.photoshop image/x-pcx image/x-exr");
else list.append(givenUrl);
if (givenUrl.isEmpty()) {
KFileDialog d(KUrl("kfiledialog:///clipfolder"), "application/x-kdenlive application/flv application/vnd.rn-realmedia video/x-dv video/x-msvideo video/mpeg video/x-ms-wmv audio/mpeg audio/x-mp3 audio/x-wav application/ogg video/mp4 video/quicktime image/gif image/jpeg image/png image/x-bmp image/svg+xml image/tiff image/x-xcf-gimp image/x-vnd.adobe.photoshop image/x-pcx image/x-exr", this);
d.setFilter(d.currentFilter() + "\n*.m2t *.mts|HDV video\n*.dv|DV video");
if (d.exec() == QDialog::Accepted)
list = d.selectedUrls();
/*list = KFileDialog::getOpenUrls(KUrl("kfiledialog:///clipfolder"), "application/vnd.kde.kdenlive application/vnd.westley.scenelist application/flv application/vnd.rn-realmedia video/x-dv video/x-msvideo video/mpeg video/x-ms-wmv audio/mpeg audio/x-mp3 audio/x-wav application/ogg video/mp4 video/quicktime image/gif image/jpeg image/png image/x-bmp image/svg+xml image/tiff image/x-xcf-gimp image/x-vnd.adobe.photoshop image/x-pcx image/x-exr\n*.m2t *.mts|HDV video\n*.dv|DV video");*/
} else list.append(givenUrl);
if (list.isEmpty()) return;
KUrl::List::Iterator it;
int groupId = -1;
......
......@@ -121,6 +121,7 @@ void Render::closeMlt() {
delete m_mltConsumer;
if (m_mltProducer)
delete m_mltProducer;
while (! m_producersList.isEmpty()) delete m_producersList.takeFirst();
//delete m_osdInfo;
}
......@@ -161,6 +162,7 @@ int Render::resetProfile(QString profile) {
Mlt::Producer *producer = new Mlt::Producer(*m_mltProfile , "westley-xml", tmp);
delete[] tmp;
m_mltProducer = producer;
m_mltProducer->optimise();
m_mltProducer->set_speed(0);
connectPlaylist();
......@@ -382,29 +384,35 @@ void Render::getFileProperties(const QDomElement &xml, int clipId) {
QMap < QString, QString > metadataPropertyMap;
KUrl url = KUrl(xml.attribute("resource", QString::null));
bool newProducer = false;
Mlt::Producer *producer = getProducerById(QString::number(clipId));
if (producer == NULL) {
if (url.isEmpty()) {
QDomDocument doc;
QDomElement westley = doc.createElement("westley");
QDomElement play = doc.createElement("playlist");
doc.appendChild(westley);
westley.appendChild(play);
play.appendChild(doc.importNode(xml, true));
char *tmp = decodedString(doc.toString());
producer = new Mlt::Producer(*m_mltProfile, "westley-xml", tmp);
delete[] tmp;
} else {
char *tmp = decodedString(url.path());
producer = new Mlt::Producer(*m_mltProfile, tmp);
delete[] tmp;
}
Mlt::Producer *producer;
if (url.isEmpty()) {
QDomDocument doc;
QDomElement westley = doc.createElement("westley");
QDomElement play = doc.createElement("playlist");
doc.appendChild(westley);
westley.appendChild(play);
play.appendChild(doc.importNode(xml, true));
char *tmp = decodedString(doc.toString());
producer = new Mlt::Producer(*m_mltProfile, "westley-xml", tmp);
delete[] tmp;
} else {
char *tmp = decodedString(url.path());
producer = new Mlt::Producer(*m_mltProfile, tmp);
delete[] tmp;
if (producer->is_blank()) {
kDebug() << " / / / / / / / /ERRROR / / / / // CANNOT LOAD PRODUCER: ";
return;
}
m_producersList.append(producer);
newProducer = true;
}
if (producer->is_blank()) {
kDebug() << " / / / / / / / /ERRROR / / / / // CANNOT LOAD PRODUCER: ";
return;
}
int frameNumber = xml.attribute("thumbnail", "0").toInt();
if (frameNumber != 0) producer->seek(frameNumber);
......@@ -508,7 +516,7 @@ void Render::getFileProperties(const QDomElement &xml, int clipId) {
emit replyGetFileProperties(clipId, filePropertyMap, metadataPropertyMap);
kDebug() << "REquested fuile info for: " << url.path();
if (frame) delete frame;
if (producer) delete producer;
if (!newProducer && producer) delete producer;
}
/** Create the producer from the Westley QDomDocument */
......@@ -585,7 +593,7 @@ void Render::setSceneList(QString playlist, int position) {
m_mltProducer = new Mlt::Producer(*m_mltProfile, "westley-xml", tmp);
delete[] tmp;
if (!m_mltProducer || !m_mltProducer->is_valid()) kDebug() << " WARNING - - - - -INVALID PLAYLIST: " << tmp;
//m_mltProducer->optimise();
m_mltProducer->optimise();
/*if (KdenliveSettings::osdtimecode()) {
// Attach filter for on screen display of timecode
......@@ -645,6 +653,7 @@ void Render::saveSceneList(QString path, QDomElement kdenliveData) {
char *tmppath = decodedString("westley:" + path);
Mlt::Consumer westleyConsumer(*m_mltProfile , tmppath);
m_mltProducer->optimise();
delete[] tmppath;
westleyConsumer.set("terminate_on_pause", 1);
Mlt::Producer prod(m_mltProducer->get_producer());
......@@ -682,6 +691,7 @@ void Render::connectPlaylist() {
m_mltConsumer->connect(*m_mltProducer);
m_mltProducer->set_speed(0);
m_mltConsumer->start();
parsePlaylistForClips();
emit durationChanged(m_mltProducer->get_playtime());
//refresh();
/*
......@@ -1029,23 +1039,26 @@ void Render::mltCheckLength(bool reload) {
black.setAttribute("mlt_service", "colour");
black.setAttribute("colour", "black");
black.setAttribute("id", "black");
black.setAttribute("in", "0");
black.setAttribute("out", "13999");
ItemInfo info;
info.track = 0;
while (dur > 14000) {
mltInsertClip(0, GenTime(i * 14000, m_fps), GenTime(), black);
info.startPos = GenTime(i * 14000, m_fps);
info.endPos = info.startPos + GenTime(13999, m_fps);
mltInsertClip(info, black);
dur = dur - 14000;
i++;
}
if (dur > 0) {
black.setAttribute("out", QString::number(dur));
mltInsertClip(0, GenTime(i * 14000, m_fps), GenTime(), black);
info.startPos = GenTime(i * 14000, m_fps);
info.endPos = info.startPos + GenTime(dur, m_fps);
mltInsertClip(info, black);
}
m_mltProducer->set("out", duration);
emit durationChanged((int)duration);
}
}
void Render::mltInsertClip(int track, GenTime position, GenTime crop, QDomElement element) {
void Render::mltInsertClip(ItemInfo info, QDomElement element) {
if (!m_mltProducer) {
kDebug() << "PLAYLIST NOT INITIALISED //////";
return;
......@@ -1059,24 +1072,68 @@ void Render::mltInsertClip(int track, GenTime position, GenTime crop, QDomElemen
Mlt::Service service(parentProd.get_service());
Mlt::Tractor tractor(service);
mlt_service_lock(service.get_service());
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Producer trackProducer(tractor.track(info.track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
QDomDocument doc;
doc.appendChild(doc.importNode(element, true));
QString resource = doc.toString();
char *tmp = decodedString(resource);
Mlt::Producer clip(*m_mltProfile, "westley-xml", tmp);
clip.set("in", crop.frames(m_fps));
//clip.set_in_and_out(in.frames(m_fps), out.frames(m_fps));
delete[] tmp;
trackPlaylist.insert_at((int) position.frames(m_fps), clip, 1);
Mlt::Producer *prod = getProducerById(element.attribute("id"));
if (prod == NULL) {
// clip was never used yet
QDomDocument doc;
doc.appendChild(doc.importNode(element, true));
QString resource = doc.toString();
kDebug() << "// INSERTING CLIP: " << resource;
char *tmp = decodedString(resource);
prod = new Mlt::Producer(*m_mltProfile, "westley-xml", tmp);
delete[] tmp;
m_producersList.append(prod);
}
Mlt::Producer *clip = prod->cut(info.cropStart.frames(m_fps), (info.endPos - info.startPos).frames(m_fps));
trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *clip, 1);
mlt_service_unlock(service.get_service());
if (track != 0) mltCheckLength();
if (info.track != 0) mltCheckLength();
//tractor.multitrack()->refresh();
//tractor.refresh();
}
Mlt::Producer *Render::getProducerById(const QString &id) {
for (int i = 0; i < m_producersList.count(); i++) {
if (m_producersList.at(i)->get("id") == id) return m_producersList.at(i);
}
return NULL;
}
void Render::parsePlaylistForClips() {
// clear current producers list
while (! m_producersList.isEmpty()) delete m_producersList.takeFirst();
//parse entire playlists to find all the different clips
Mlt::Producer parentProd(m_mltProducer->parent());
if (parentProd.get_producer() == NULL) {
kDebug() << "PLAYLIST BROKEN, CANNOT INSERT CLIP //////";
return;
}
Mlt::Service service(parentProd.get_service());
if (service.type() != tractor_type) return;
Mlt::Tractor tractor(service);
mlt_service_lock(service.get_service());
for (int i = 0; i < tractor.count(); i++) {
Mlt::Producer trackProducer(tractor.track(i));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
for (int j = 0; j < trackPlaylist.count(); j++) {
if (!trackPlaylist.is_blank(j)) {
Mlt::Producer *clip = trackPlaylist.get_clip(j);
if (clip) {
if (getProducerById(clip->get("id")) == NULL)
m_producersList.append(new Mlt::Producer(clip->get_parent()));
}
}
}
}
}
void Render::mltCutClip(int track, GenTime position) {
m_isBlocked = true;
......@@ -1091,10 +1148,10 @@ void Render::mltCutClip(int track, GenTime position) {
m_isBlocked = false;
}
void Render::mltUpdateClip(int track, GenTime position, GenTime crop, QDomElement element) {
void Render::mltUpdateClip(ItemInfo info, QDomElement element) {
// TODO: optimize
mltRemoveClip(track, position);
mltInsertClip(track, position, crop, element);
mltRemoveClip(info.track, info.startPos);
mltInsertClip(info, element);
}
......@@ -1575,7 +1632,7 @@ void Render::mltUpdateTransition(QString oldTag, QString tag, int a_track, int b
mltDeleteTransition(oldTag, a_track, b_track, in, out, xml, false);
mltAddTransition(tag, a_track, b_track, in, out, xml);
}
mltSavePlaylist();
//mltSavePlaylist();
}
void Render::mltUpdateTransitionParams(QString type, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml) {
......
......@@ -27,9 +27,7 @@
#include <kurl.h>
#include "gentime.h"
/*#include "docclipref.h"
#include "effectdesc.h"
#include "effectparamdescfactory.h"*/
#include "definitions.h"
/**Render encapsulates the client side of the interface to a renderer.
From Kdenlive's point of view, you treat the Render object as the
......@@ -149,8 +147,8 @@ Q_OBJECT public:
const double dar() const;
/** Playlist manipulation */
void mltInsertClip(int track, GenTime position, GenTime crop, QDomElement element);
void mltUpdateClip(int track, GenTime position, GenTime crop, QDomElement element);
void mltInsertClip(ItemInfo info, QDomElement element);
void mltUpdateClip(ItemInfo info, QDomElement element);
void mltCutClip(int track, GenTime position);
void mltResizeClipEnd(int track, GenTime pos, GenTime in, GenTime out);
void mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime moveStart, GenTime in, GenTime out);
......@@ -182,6 +180,9 @@ private: // Private attributes & methods
uint m_monitorId;
bool m_generateScenelist;
QList <Mlt::Producer *> m_producersList;
Mlt::Producer *getProducerById(const QString &id);
void parsePlaylistForClips();
/** Holds the path to on screen display profile */
QString m_osdProfile;
......
......@@ -161,7 +161,7 @@ void RenderWidget::slotEditProfile() {
ui.profile_name->setFocus();
if (d->exec() == QDialog::Accepted) {
slotDeleteProfile();
slotDeleteProfile();
QString exportFile = KStandardDirs::locateLocal("data", "kdenlive/export/customprofiles.xml");
QDomDocument doc;
QFile file(exportFile);
......@@ -319,12 +319,11 @@ void RenderWidget::refreshParams() {
}
if (item->data(EditableRole).toString().isEmpty()) {
m_view.buttonDelete->setEnabled(false);
m_view.buttonEdit->setEnabled(false);
}
else {
m_view.buttonDelete->setEnabled(true);
m_view.buttonEdit->setEnabled(true);
m_view.buttonDelete->setEnabled(false);
m_view.buttonEdit->setEnabled(false);
} else {
m_view.buttonDelete->setEnabled(true);
m_view.buttonEdit->setEnabled(true);
}
}
......
......@@ -343,7 +343,7 @@ int TrackView::slotAddProjectTrack(int ix, QDomElement xml, bool videotrack) {
ItemInfo clipinfo;
clipinfo.startPos = GenTime(position, m_doc->fps());
clipinfo.endPos = clipinfo.startPos + GenTime(out - in, m_doc->fps());
clipinfo.cropStart = GenTime(in, m_doc->fps());
clipinfo.cropStart = GenTime(in, m_doc->fps());
clipinfo.track = ix;
//kDebug() << "// INSERTING CLIP: " << in << "x" << out << ", track: " << ix << ", ID: " << id << ", SCALE: " << m_scale << ", FPS: " << m_doc->fps();
ClipItem *item = new ClipItem(clip, clipinfo, m_scale, m_doc->fps());
......
......@@ -6,11 +6,11 @@
<x>0</x>
<y>0</y>
<width>369</width>
<height>258</height>
<height>285</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_4" >
<item row="1" column="0" >
<item row="2" column="0" >
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Default Durations</string>
......@@ -50,7 +50,7 @@
</layout>
</widget>
</item>