From 000c8e2337fe448a6e35896f3ef1a95dedbb39c7 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Tue, 28 Jul 2009 12:34:59 +0000 Subject: [PATCH] Update for new titler module, turn clip speed into an effect, mem leaks and more svn path=/trunk/kdenlive/; revision=3771 --- effects/CMakeLists.txt | 1 + effects/speed.xml | 7 +- src/changespeedcommand.cpp | 10 ++- src/changespeedcommand.h | 4 +- src/clipitem.cpp | 32 +++---- src/clipitem.h | 10 ++- src/clipmanager.cpp | 39 ++++++++- src/clipmanager.h | 2 +- src/customtrackview.cpp | 97 +++++++++++++++++---- src/customtrackview.h | 3 +- src/docclipbase.cpp | 13 ++- src/effectstackedit.cpp | 5 +- src/effectstackedit.h | 2 +- src/geometryval.cpp | 2 +- src/kdenlivedoc.cpp | 20 +++-- src/kdenliveui.rc | 1 - src/mainwindow.cpp | 34 ++++---- src/mainwindow.h | 1 - src/mimetypes/kdenlive.xml | 5 ++ src/monitor.cpp | 1 + src/projectlist.cpp | 30 ++++--- src/projectlistview.cpp | 8 +- src/renderer.cpp | 157 ++++++++++++++++++++++------------ src/renderer.h | 4 +- src/statusbarmessagelabel.cpp | 18 ++-- src/statusbarmessagelabel.h | 10 +-- src/titledocument.cpp | 16 +++- src/titledocument.h | 6 +- src/titlewidget.cpp | 35 ++++++-- src/titlewidget.h | 8 +- src/trackview.cpp | 13 ++- 31 files changed, 405 insertions(+), 189 deletions(-) diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt index 62ee2d6a..53999135 100644 --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -56,5 +56,6 @@ frei0r_saturat0r.xml gain.xml fade_from_black.xml fade_to_black.xml +speed.xml DESTINATION ${DATA_INSTALL_DIR}/kdenlive/effects) diff --git a/effects/speed.xml b/effects/speed.xml index b00b86b5..cfe7ae59 100644 --- a/effects/speed.xml +++ b/effects/speed.xml @@ -1,10 +1,9 @@ - + Speed - Make clip play faster slowly + Make clip play faster or slower Jean-Baptiste Mardelle - - + Speed diff --git a/src/changespeedcommand.cpp b/src/changespeedcommand.cpp index 394faa90..db488077 100644 --- a/src/changespeedcommand.cpp +++ b/src/changespeedcommand.cpp @@ -23,13 +23,15 @@ #include -ChangeSpeedCommand::ChangeSpeedCommand(CustomTrackView *view, ItemInfo info, double old_speed, double new_speed, const QString &clipId, QUndoCommand * parent) : +ChangeSpeedCommand::ChangeSpeedCommand(CustomTrackView *view, ItemInfo info, double old_speed, double new_speed, int old_strobe, int new_strobe, const QString &clipId, QUndoCommand * parent) : QUndoCommand(parent), m_view(view), m_clipInfo(info), m_clipId(clipId), m_old_speed(old_speed), - m_new_speed(new_speed) + m_new_speed(new_speed), + m_old_strobe(old_strobe), + m_new_strobe(new_strobe) { setText(i18n("Adjust clip length")); } @@ -38,12 +40,12 @@ ChangeSpeedCommand::ChangeSpeedCommand(CustomTrackView *view, ItemInfo info, dou // virtual void ChangeSpeedCommand::undo() { - m_view->doChangeClipSpeed(m_clipInfo, m_old_speed, m_new_speed, m_clipId); + m_view->doChangeClipSpeed(m_clipInfo, m_old_speed, m_new_speed, m_old_strobe, m_clipId); } // virtual void ChangeSpeedCommand::redo() { - m_view->doChangeClipSpeed(m_clipInfo, m_new_speed, m_old_speed, m_clipId); + m_view->doChangeClipSpeed(m_clipInfo, m_new_speed, m_old_speed, m_new_strobe, m_clipId); } diff --git a/src/changespeedcommand.h b/src/changespeedcommand.h index ab1c5b41..3f54c8fb 100644 --- a/src/changespeedcommand.h +++ b/src/changespeedcommand.h @@ -33,7 +33,7 @@ class CustomTrackView; class ChangeSpeedCommand : public QUndoCommand { public: - ChangeSpeedCommand(CustomTrackView *view, ItemInfo info, double old_speed, double new_speed, const QString &clipId, QUndoCommand * parent = 0); + ChangeSpeedCommand(CustomTrackView *view, ItemInfo info, double old_speed, double new_speed, int old_strobe, int new_strobe, const QString &clipId, QUndoCommand * parent = 0); virtual void undo(); virtual void redo(); @@ -43,6 +43,8 @@ private: QString m_clipId; double m_old_speed; double m_new_speed; + int m_old_strobe; + int m_new_strobe; }; #endif diff --git a/src/clipitem.cpp b/src/clipitem.cpp index 8d76725d..c0335645 100644 --- a/src/clipitem.cpp +++ b/src/clipitem.cpp @@ -37,7 +37,7 @@ #include #include -ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, bool generateThumbs) : +ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, int strobe, bool generateThumbs) : AbstractClipItem(info, QRectF(), fps), m_clip(clip), m_startFade(0), @@ -47,14 +47,13 @@ ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, b m_startPix(QPixmap()), m_endPix(QPixmap()), m_hasThumbs(false), - m_startThumbTimer(NULL), - m_endThumbTimer(NULL), m_selectedEffect(-1), m_timeLine(0), m_startThumbRequested(false), m_endThumbRequested(false), //m_hover(false), m_speed(speed), + m_strobe(strobe), m_framePixelWidth(0) { setZValue(2); @@ -83,12 +82,10 @@ ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, b if (m_clipType == VIDEO || m_clipType == AV || m_clipType == SLIDESHOW || m_clipType == PLAYLIST) { setBrush(QColor(141, 166, 215)); m_hasThumbs = true; - m_startThumbTimer = new QTimer(this); - m_startThumbTimer->setSingleShot(true); - connect(m_startThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetStartThumb())); - m_endThumbTimer = new QTimer(this); - m_endThumbTimer->setSingleShot(true); - connect(m_endThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetEndThumb())); + m_startThumbTimer.setSingleShot(true); + connect(&m_startThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetStartThumb())); + m_endThumbTimer.setSingleShot(true); + connect(&m_endThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetEndThumb())); connect(this, SIGNAL(getThumb(int, int)), clip->thumbProducer(), SLOT(extractImage(int, int))); //connect(this, SIGNAL(getThumb(int, int)), clip->thumbProducer(), SLOT(getVideoThumbs(int, int))); @@ -122,14 +119,12 @@ ClipItem::~ClipItem() disconnect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QPixmap)), this, SLOT(slotThumbReady(int, QPixmap))); disconnect(m_clip, SIGNAL(gotAudioData()), this, SLOT(slotGotAudioData())); } - delete m_startThumbTimer; - delete m_endThumbTimer; delete m_timeLine; } ClipItem *ClipItem::clone(ItemInfo info) const { - ClipItem *duplicate = new ClipItem(m_clip, info, m_fps, m_speed); + ClipItem *duplicate = new ClipItem(m_clip, info, m_fps, m_speed, m_strobe); if (m_clipType == IMAGE || m_clipType == TEXT) duplicate->slotSetStartThumb(m_startPix); else { if (info.cropStart == m_cropStart) duplicate->slotSetStartThumb(m_startPix); @@ -591,6 +586,7 @@ QDomElement ClipItem::xml() const { QDomElement xml = m_clip->toXML(); if (m_speed != 1.0) xml.setAttribute("speed", m_speed); + if (m_strobe > 1) xml.setAttribute("strobe", m_strobe); if (m_audioOnly) xml.setAttribute("audio_only", 1); else if (m_videoOnly) xml.setAttribute("video_only", 1); return xml; @@ -1123,7 +1119,7 @@ void ClipItem::resizeStart(int posx, double /*speed*/) checkEffectsKeyframesPos(previous, cropStart().frames(m_fps), true); if (m_hasThumbs && KdenliveSettings::videothumbnails()) { /*connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QPixmap)), this, SLOT(slotThumbReady(int, QPixmap)));*/ - m_startThumbTimer->start(150); + m_startThumbTimer.start(150); } } } @@ -1140,7 +1136,7 @@ void ClipItem::resizeEnd(int posx, double /*speed*/, bool updateKeyFrames) if (updateKeyFrames) checkEffectsKeyframesPos(previous, (cropStart() + cropDuration()).frames(m_fps), false); if (m_hasThumbs && KdenliveSettings::videothumbnails()) { /*connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QPixmap)), this, SLOT(slotThumbReady(int, QPixmap)));*/ - m_endThumbTimer->start(150); + m_endThumbTimer.start(150); } } } @@ -1501,9 +1497,15 @@ double ClipItem::speed() const return m_speed; } -void ClipItem::setSpeed(const double speed) +int ClipItem::strobe() const +{ + return m_strobe; +} + +void ClipItem::setSpeed(const double speed, const int strobe) { m_speed = speed; + m_strobe = strobe; if (m_speed == 1.0) m_clipName = baseClip()->name(); else m_clipName = baseClip()->name() + " - " + QString::number(speed * 100, 'f', 0) + '%'; //update(); diff --git a/src/clipitem.h b/src/clipitem.h index 31efc3ae..8d0feafd 100644 --- a/src/clipitem.h +++ b/src/clipitem.h @@ -41,7 +41,7 @@ class ClipItem : public AbstractClipItem Q_OBJECT public: - ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, bool generateThumbs = true); + ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, int strobe, bool generateThumbs = true); virtual ~ ClipItem(); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, @@ -95,8 +95,9 @@ public: QString keyframes(const int index); void setKeyframes(const int ix, const QString keyframes); void setEffectList(const EffectsList effectList); - void setSpeed(const double speed); + void setSpeed(const double speed, int strobe); double speed() const; + int strobe() const; GenTime maxDuration() const; GenTime cropStart() const; GenTime endPos() const; @@ -133,8 +134,8 @@ private: QPixmap m_startPix; QPixmap m_endPix; bool m_hasThumbs; - QTimer *m_startThumbTimer; - QTimer *m_endThumbTimer; + QTimer m_startThumbTimer; + QTimer m_endThumbTimer; int m_selectedEffect; QTimeLine *m_timeLine; @@ -142,6 +143,7 @@ private: bool m_endThumbRequested; //bool m_hover; double m_speed; + int m_strobe; EffectsList m_effectList; QList m_transitionsList; diff --git a/src/clipmanager.cpp b/src/clipmanager.cpp index 4764a650..fc33da1d 100644 --- a/src/clipmanager.cpp +++ b/src/clipmanager.cpp @@ -48,6 +48,7 @@ ClipManager::ClipManager(KdenliveDoc *doc) : ClipManager::~ClipManager() { + kDebug() << "\n\n 2222222222222222222222222 CLOSE CM 22222222222"; qDeleteAll(m_clipList); } @@ -257,8 +258,23 @@ void ClipManager::slotAddClipList(const KUrl::List urls, const QString group, co KMimeType::Ptr type = KMimeType::findByUrl(file); if (type->name().startsWith("image/")) { prod.setAttribute("type", (int) IMAGE); - prod.setAttribute("in", "0"); + prod.setAttribute("in", 0); prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::image_duration()) - 1); + } else if (type->name() == "application/x-kdenlivetitle") { + // opening a title file + QDomDocument txtdoc("titledocument"); + QFile txtfile(file.path()); + if (txtfile.open(QIODevice::ReadOnly) && txtdoc.setContent(&txtfile)) { + txtfile.close(); + prod.setAttribute("type", (int) TEXT); + prod.setAttribute("resource", QString()); + prod.setAttribute("xmldata", txtdoc.toString()); + GenTime outPos(txtdoc.documentElement().attribute("out").toDouble() / 1000.0); + prod.setAttribute("transparency", 1); + prod.setAttribute("in", 0); + int out = (int) outPos.frames(m_doc->fps()); + if (out > 0) prod.setAttribute("out", out); + } else txtfile.close(); } new AddClipCommand(m_doc, doc.documentElement(), QString::number(id), true, addClips); } @@ -284,6 +300,21 @@ void ClipManager::slotAddClipFile(const KUrl url, const QString group, const QSt prod.setAttribute("type", (int) IMAGE); prod.setAttribute("in", "0"); prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::image_duration()) - 1); + } else if (type->name() == "application/x-kdenlivetitle") { + // opening a title file + QDomDocument txtdoc("titledocument"); + QFile txtfile(url.path()); + if (txtfile.open(QIODevice::ReadOnly) && txtdoc.setContent(&txtfile)) { + txtfile.close(); + prod.setAttribute("type", (int) TEXT); + prod.setAttribute("resource", QString()); + prod.setAttribute("xmldata", txtdoc.toString()); + GenTime outPos(txtdoc.documentElement().attribute("out").toDouble() / 1000.0); + prod.setAttribute("transparency", 1); + prod.setAttribute("in", 0); + int out = (int) outPos.frames(m_doc->fps()); + if (out > 0) prod.setAttribute("out", out); + } else txtfile.close(); } AddClipCommand *command = new AddClipCommand(m_doc, doc.documentElement(), QString::number(id), true); m_doc->commandStack()->push(command); @@ -338,12 +369,12 @@ void ClipManager::slotAddSlideshowClipFile(const QString name, const QString pat -void ClipManager::slotAddTextClipFile(const QString titleName, const QString imagePath, const QString xml, const QString group, const QString &groupId) +void ClipManager::slotAddTextClipFile(const QString titleName, int out, const QString xml, const QString group, const QString &groupId) { QDomDocument doc; QDomElement prod = doc.createElement("producer"); doc.appendChild(prod); - prod.setAttribute("resource", imagePath); + //prod.setAttribute("resource", imagePath); prod.setAttribute("name", titleName); prod.setAttribute("xmldata", xml); uint id = m_clipIdCounter++; @@ -355,7 +386,7 @@ void ClipManager::slotAddTextClipFile(const QString titleName, const QString ima prod.setAttribute("type", (int) TEXT); prod.setAttribute("transparency", "1"); prod.setAttribute("in", "0"); - prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::image_duration()) - 1); + prod.setAttribute("out", out); AddClipCommand *command = new AddClipCommand(m_doc, doc.documentElement(), QString::number(id), true); m_doc->commandStack()->push(command); } diff --git a/src/clipmanager.h b/src/clipmanager.h index 4a7850f7..6eca717a 100644 --- a/src/clipmanager.h +++ b/src/clipmanager.h @@ -57,7 +57,7 @@ Q_OBJECT public: void deleteClip(const QString &clipId); void slotAddClipFile(const KUrl url, const QString group, const QString &groupId); void slotAddClipList(const KUrl::List urls, const QString group, const QString &groupId); - void slotAddTextClipFile(const QString titleName, const QString imagePath, const QString xml, const QString group, const QString &groupId); + void slotAddTextClipFile(const QString titleName, int out, const QString xml, const QString group, const QString &groupId); void slotAddTextTemplateClip(QString titleName, const QString imagePath, const KUrl path, const QString group, const QString &groupId); void slotAddColorClipFile(const QString name, const QString color, QString duration, const QString group, const QString &groupId); void slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, const QString group, const QString &groupId); diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 25bdd97e..f72109df 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -98,7 +98,6 @@ CustomTrackView::CustomTrackView(KdenliveDoc *doc, CustomTrackScene* projectscen m_animation(NULL), m_clickPoint(), m_autoScroll(KdenliveSettings::autoscroll()), - m_changeSpeedAction(NULL), m_pasteEffectsAction(NULL), m_ungroupAction(NULL), m_scrollOffset(0), @@ -165,8 +164,7 @@ void CustomTrackView::setContextMenu(QMenu *timeline, QMenu *clip, QMenu *transi m_clipTypeGroup = clipTypeGroup; QList list = m_timelineContextClipMenu->actions(); for (int i = 0; i < list.count(); i++) { - if (list.at(i)->data().toString() == "change_speed") m_changeSpeedAction = list.at(i); - else if (list.at(i)->data().toString() == "paste_effects") m_pasteEffectsAction = list.at(i); + if (list.at(i)->data().toString() == "paste_effects") m_pasteEffectsAction = list.at(i); else if (list.at(i)->data().toString() == "ungroup_clip") m_ungroupAction = list.at(i); } @@ -411,9 +409,9 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) return; } else { if (m_visualTip) { + m_animationTimer->stop(); delete m_animation; m_animation = NULL; - m_animationTimer->stop(); delete m_visualTip; m_visualTip = NULL; } @@ -567,8 +565,8 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) setCursor(Qt::SplitHCursor); } else { if (m_visualTip) { - delete m_animation; m_animationTimer->stop(); + delete m_animation; m_animation = NULL; delete m_visualTip; m_visualTip = NULL; @@ -817,7 +815,6 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) groupSelectedItems(); ClipItem *clip = static_cast (m_dragItem); updateClipTypeActions(dragGroup == NULL ? clip : NULL); - m_changeSpeedAction->setEnabled(clip->clipType() == AV || clip->clipType() == VIDEO); m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1); } @@ -1111,7 +1108,6 @@ void CustomTrackView::displayContextMenu(QPoint pos, AbstractClipItem *clip, Abs m_editGuide->setEnabled(m_dragGuide != NULL); if (clip == NULL) m_timelineContextMenu->popup(pos); else if (group != NULL) { - m_changeSpeedAction->setEnabled(false); m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1); m_ungroupAction->setEnabled(true); updateClipTypeActions(NULL); @@ -1121,7 +1117,6 @@ void CustomTrackView::displayContextMenu(QPoint pos, AbstractClipItem *clip, Abs if (clip->type() == AVWIDGET) { ClipItem *item = static_cast (clip); updateClipTypeActions(item); - m_changeSpeedAction->setEnabled(item->clipType() == AV || item->clipType() == VIDEO); m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1); m_timelineContextClipMenu->popup(pos); } else if (clip->type() == TRANSITIONWIDGET) m_timelineContextTransitionMenu->popup(pos); @@ -1148,7 +1143,7 @@ void CustomTrackView::dragEnterEvent(QDragEnterEvent * event) info.cropStart = GenTime(list.at(1).toInt(), m_document->fps()); info.endPos = GenTime(list.at(2).toInt() - list.at(1).toInt(), m_document->fps()); info.track = (int)(1 / m_tracksHeight); - ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0); + ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1); m_selectionGroup->addToGroup(item); item->setFlags(QGraphicsItem::ItemIsSelectable); //TODO: check if we do not overlap another clip when first dropping in timeline @@ -1175,7 +1170,7 @@ void CustomTrackView::dragEnterEvent(QDragEnterEvent * event) info.startPos = start; info.endPos = info.startPos + clip->duration(); info.track = (int)(1 / m_tracksHeight); - ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, false); + ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1, false); start += clip->duration(); offsetList.append(start); m_selectionGroup->addToGroup(item); @@ -1268,6 +1263,22 @@ void CustomTrackView::addEffect(int track, GenTime pos, QDomElement effect) { ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_document->tracksCount() - track); if (clip) { + // Special case: speed effect + if (effect.attribute("id") == "speed") { + if (clip->clipType() != VIDEO && clip->clipType() != AV && clip->clipType() != PLAYLIST) { + emit displayMessage(i18n("Problem adding effect to clip"), ErrorMessage); + return; + } + ItemInfo info = clip->info(); + double speed = EffectsList::parameter(effect, "speed").toDouble() / 100.0; + int strobe = EffectsList::parameter(effect, "strobe").toInt(); + if (strobe == 0) strobe = 1; + doChangeClipSpeed(info, speed, 1.0, strobe, clip->baseClip()->getId()); + clip->addEffect(effect); + emit clipItemSelected(clip); + return; + } + if (!m_document->renderer()->mltAddEffect(track, pos, clip->addEffect(effect))) emit displayMessage(i18n("Problem adding effect to clip"), ErrorMessage); emit clipItemSelected(clip); @@ -1277,6 +1288,17 @@ void CustomTrackView::addEffect(int track, GenTime pos, QDomElement effect) void CustomTrackView::deleteEffect(int track, GenTime pos, QDomElement effect) { QString index = effect.attribute("kdenlive_ix"); + // Special case: speed effect + if (effect.attribute("id") == "speed") { + ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_document->tracksCount() - track); + if (clip) { + ItemInfo info = clip->info(); + doChangeClipSpeed(info, 1.0, clip->speed(), 1, clip->baseClip()->getId()); + clip->deleteEffect(index); + emit clipItemSelected(clip); + return; + } + } if (!m_document->renderer()->mltRemoveEffect(track, pos, index, true) && effect.attribute("disabled") != "1") { kDebug() << "// ERROR REMOV EFFECT: " << index << ", DISABLE: " << effect.attribute("disabled"); emit displayMessage(i18n("Problem deleting effect"), ErrorMessage); @@ -1400,6 +1422,25 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement effect, i { ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_document->tracksCount() - track); if (clip) { + + + // Special case: speed effect + if (effect.attribute("id") == "speed") { + ItemInfo info = clip->info(); + double speed = EffectsList::parameter(effect, "speed").toDouble() / 100.0; + int strobe = EffectsList::parameter(effect, "strobe").toInt(); + if (strobe == 0) strobe = 1; + doChangeClipSpeed(info, speed, clip->speed(), strobe, clip->baseClip()->getId()); + clip->setEffectAt(ix, effect); + if (ix == clip->selectedEffectIndex()) { + clip->setSelectedEffect(ix); + } + return; + } + + + + EffectsParameterList effectParams = clip->getEffectArgs(effect); if (effect.attribute("tag") == "ladspa") { // Update the ladspa affect file @@ -1455,6 +1496,21 @@ void CustomTrackView::slotChangeEffectState(ClipItem *clip, int effectPos, bool { QDomElement effect = clip->effectAt(effectPos); QDomElement oldEffect = effect.cloneNode().toElement(); + + if (effect.attribute("id") == "speed") { + if (clip) { + ItemInfo info = clip->info(); + effect.setAttribute("disabled", disable); + if (disable) doChangeClipSpeed(info, 1.0, clip->speed(), 1, clip->baseClip()->getId()); + else { + double speed = EffectsList::parameter(effect, "speed").toDouble() / 100.0; + int strobe = EffectsList::parameter(effect, "strobe").toInt(); + if (strobe == 0) strobe = 1; + doChangeClipSpeed(info, speed, 1.0, strobe, clip->baseClip()->getId()); + } + return; + } + } effect.setAttribute("disabled", disable); EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldEffect, effect, effectPos, true); m_commandStack->push(command); @@ -1779,19 +1835,21 @@ void CustomTrackView::dropEvent(QDropEvent * event) bool isLocked = m_document->trackInfoAt(tracknumber).isLocked; if (isLocked) item->setItemLocked(true); - if (item->baseClip()->isTransparent() && getTransitionItemAtStart(info.startPos, info.track) == NULL) { + /*if (item->baseClip()->isTransparent() && getTransitionItemAtStart(info.startPos, info.track) == NULL) { // add transparency transition - new AddTransitionCommand(this, info, getPreviousVideoTrack(info.track), MainWindow::transitions.getEffectByTag("composite", "composite"), false, true, addCommand); - } + QDomElement trans = MainWindow::transitions.getEffectByTag("composite", "composite").cloneNode().toElement(); + new AddTransitionCommand(this, info, getPreviousVideoTrack(info.track), trans, false, true, addCommand); + }*/ info.track = m_document->tracksCount() - item->track(); m_document->renderer()->mltInsertClip(info, item->xml(), item->baseClip()->producer(item->track())); item->setSelected(true); } m_commandStack->push(addCommand); setDocumentModified(); - m_changeSpeedAction->setEnabled(hasVideoClip); m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1); if (items.count() > 1) groupSelectedItems(true); + event->setDropAction(Qt::MoveAction); + event->accept(); } else QGraphicsView::dropEvent(event); setFocus(); } @@ -2349,6 +2407,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) else if (item->isVideoOnly()) prod = item->baseClip()->videoProducer(); else prod = item->baseClip()->producer(m_dragItemInfo.track); bool success = m_document->renderer()->mltMoveClip((int)(m_document->tracksCount() - m_dragItemInfo.track), (int)(m_document->tracksCount() - m_dragItem->track()), (int) m_dragItemInfo.startPos.frames(m_document->fps()), (int)(m_dragItem->startPos().frames(m_document->fps())), prod); + if (success) { kDebug() << "// get trans info"; int tracknumber = m_document->tracksCount() - item->track() - 1; @@ -2874,7 +2933,7 @@ void CustomTrackView::changeClipSpeed() double speed = (double) percent / 100.0; if (item->speed() != speed && (item->clipType() == VIDEO || item->clipType() == AV)) { count++; - new ChangeSpeedCommand(this, info, item->speed(), speed, item->clipProducer(), changeSelected); + //new ChangeSpeedCommand(this, info, item->speed(), speed, item->clipProducer(), changeSelected); } } } @@ -2882,7 +2941,7 @@ void CustomTrackView::changeClipSpeed() else delete changeSelected; } -void CustomTrackView::doChangeClipSpeed(ItemInfo info, const double speed, const double oldspeed, const QString &id) +void CustomTrackView::doChangeClipSpeed(ItemInfo info, const double speed, const double oldspeed, int strobe, const QString &id) { DocClipBase *baseclip = m_document->clipManager()->getClipById(id); ClipItem *item = getClipItemAt((int) info.startPos.frames(m_document->fps()), info.track); @@ -2892,9 +2951,9 @@ void CustomTrackView::doChangeClipSpeed(ItemInfo info, const double speed, const return; } info.track = m_document->tracksCount() - item->track(); - int endPos = m_document->renderer()->mltChangeClipSpeed(info, speed, oldspeed, baseclip->producer()); + int endPos = m_document->renderer()->mltChangeClipSpeed(info, speed, oldspeed, strobe, baseclip->producer()); if (endPos >= 0) { - item->setSpeed(speed); + item->setSpeed(speed, strobe); item->updateRectGeometry(); if (item->cropDuration().frames(m_document->fps()) > endPos) item->AbstractClipItem::resizeEnd(info.startPos.frames(m_document->fps()) + endPos, speed); @@ -3003,7 +3062,7 @@ void CustomTrackView::addClip(QDomElement xml, const QString &clipId, ItemInfo i emit displayMessage(i18n("No clip copied"), ErrorMessage); return; } - ClipItem *item = new ClipItem(baseclip, info, m_document->fps(), xml.attribute("speed", "1").toDouble()); + ClipItem *item = new ClipItem(baseclip, info, m_document->fps(), xml.attribute("speed", "1").toDouble(), xml.attribute("strobe", "1").toInt()); item->setEffectList(effects); if (xml.hasAttribute("audio_only")) item->setAudioOnly(true); else if (xml.hasAttribute("video_only")) item->setVideoOnly(true); diff --git a/src/customtrackview.h b/src/customtrackview.h index 86c1b8b1..4f23d5b7 100644 --- a/src/customtrackview.h +++ b/src/customtrackview.h @@ -96,7 +96,7 @@ public: void clipStart(); void clipEnd(); void changeClipSpeed(); - void doChangeClipSpeed(ItemInfo info, const double speed, const double oldspeed, const QString &id); + void doChangeClipSpeed(ItemInfo info, const double speed, const double oldspeed, int strobe, const QString &id); void setDocumentModified(); void setInPoint(); void setOutPoint(); @@ -209,7 +209,6 @@ private: QMenu *m_timelineContextClipMenu; QMenu *m_timelineContextTransitionMenu; QAction *m_autoTransition; - QAction *m_changeSpeedAction; QAction *m_pasteEffectsAction; QAction *m_ungroupAction; QAction *m_editGuide; diff --git a/src/docclipbase.cpp b/src/docclipbase.cpp index 10d5df4a..02008ccb 100644 --- a/src/docclipbase.cpp +++ b/src/docclipbase.cpp @@ -92,11 +92,14 @@ DocClipBase::DocClipBase(ClipManager *clipManager, QDomElement xml, const QStrin DocClipBase::~DocClipBase() { + kDebug() << "CLIP " << m_id << " DELETED******************************"; delete m_thumbProd; if (m_audioTimer) { m_audioTimer->stop(); delete m_audioTimer; } + /*kDebug() <<" * * *CNT "< 0) kDebug()<<"YOYO: "<get_out()<<", CUT: "<is_cut();*/ qDeleteAll(m_baseTrackProducers); m_baseTrackProducers.clear(); qDeleteAll(m_audioTrackProducers); @@ -752,8 +755,16 @@ void DocClipBase::setProperty(const QString &key, const QString &value) char *tmp = (char *) qstrdup(value.toUtf8().data()); setProducerProperty("colour", tmp); delete[] tmp; - } else if (key == "xmldata") { + } else if (key == "templatetext") { + char *tmp = (char *) qstrdup(value.toUtf8().data()); + setProducerProperty("templatetext", tmp); + delete[] tmp; setProducerProperty("force_reload", 1); + } else if (key == "xmldata") { + char *tmp = (char *) qstrdup(value.toUtf8().data()); + setProducerProperty("xmldata", tmp); + delete[] tmp; + //setProducerProperty("force_reload", 1); } else if (key == "force_aspect_ratio") { if (value.isEmpty()) { m_properties.remove("force_aspect_ratio"); diff --git a/src/effectstackedit.cpp b/src/effectstackedit.cpp index aa9d9ffa..30b32772 100644 --- a/src/effectstackedit.cpp +++ b/src/effectstackedit.cpp @@ -177,7 +177,7 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int in, int out) if (pa.attribute("max").startsWith('%')) { max = (int) ProfilesDialog::getStringEval(m_profile, pa.attribute("max")); } else max = pa.attribute("max").toInt(); - createSliderItem(paramName, (int)(value.toDouble() + 0.5) , min, max); + createSliderItem(paramName, (int)(value.toDouble() + 0.5) , min, max, pa.attribute("suffix", QString())); delete toFillin; toFillin = NULL; } else if (type == "list") { @@ -505,13 +505,14 @@ void EffectStackEdit::collectAllParameters() emit parameterChanged(oldparam, m_params); } -void EffectStackEdit::createSliderItem(const QString& name, int val , int min, int max) +void EffectStackEdit::createSliderItem(const QString& name, int val , int min, int max, const QString suffix) { QWidget* toFillin = new QWidget; Constval *ctval = new Constval; ctval->setupUi(toFillin); ctval->horizontalSlider->setMinimum(min); ctval->horizontalSlider->setMaximum(max); + if (!suffix.isEmpty()) ctval->spinBox->setSuffix(suffix); ctval->spinBox->setMinimum(min); ctval->spinBox->setMaximum(max); ctval->horizontalSlider->setPageStep((int)(max - min) / 10); diff --git a/src/effectstackedit.h b/src/effectstackedit.h index 2e6d16e6..2a595dfe 100644 --- a/src/effectstackedit.h +++ b/src/effectstackedit.h @@ -63,7 +63,7 @@ private: QList m_uiItems; QDomElement m_params; QMap m_valueItems; - void createSliderItem(const QString& name, int val , int min, int max); + void createSliderItem(const QString& name, int val , int min, int max, const QString); wipeInfo getWipeInfo(QString value); QString getWipeString(wipeInfo info); MltVideoProfile m_profile; diff --git a/src/geometryval.cpp b/src/geometryval.cpp index 6b3323dd..d6e27782 100644 --- a/src/geometryval.cpp +++ b/src/geometryval.cpp @@ -375,7 +375,7 @@ void Geometryval::slotDeleteFrame(int pos) void Geometryval::slotAddFrame(int pos) { - if (pos == -1) pos = m_ui.spinPos->value(); + if (pos = -1) pos = m_ui.spinPos->value(); Mlt::GeometryItem item; item.frame(pos); item.x(m_paramRect->pos().x()); diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index ab33a5fb..0b56aa94 100644 --- a/src/kdenlivedoc.cpp +++ b/src/kdenlivedoc.cpp @@ -231,8 +231,11 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup KdenliveDoc::~KdenliveDoc() { + m_autoSaveTimer->stop(); delete m_commandStack; + kDebug() << "// DEL CLP MAN"; delete m_clipManager; + kDebug() << "// DEL CLP MAN done"; delete m_autoSaveTimer; if (m_autosave) { if (!m_autosave->fileName().isEmpty()) m_autosave->remove(); @@ -803,7 +806,7 @@ void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem) if (elem.attribute("type").toInt() == SLIDESHOW) { extension = KUrl(path).fileName(); path = KUrl(path).directory(); - } else if (elem.attribute("type").toInt() == TEXT && QFile::exists(path) == false) { + } /*else if (elem.attribute("type").toInt() == TEXT && QFile::exists(path) == false) { kDebug() << "// TITLE: " << elem.attribute("name") << " Preview file: " << elem.attribute("resource") << " DOES NOT EXIST"; QString titlename = elem.attribute("name"); QString titleresource; @@ -826,7 +829,7 @@ void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem) elem.setAttribute("resource", titleresource); setNewClipResource(clipId, titleresource); delete dia_ui; - } + }*/ if (path.isEmpty() == false && QFile::exists(path) == false && elem.attribute("type").toInt() != TEXT && !elem.hasAttribute("placeholder")) { kDebug() << "// FOUND MISSING CLIP: " << path << ", TYPE: " << elem.attribute("type").toInt(); @@ -1037,13 +1040,13 @@ void KdenliveDoc::slotCreateTextClip(QString group, const QString &groupId, cons { QString titlesFolder = projectFolder().path(KUrl::AddTrailingSlash) + "titles/"; KStandardDirs::makeDir(titlesFolder); - TitleWidget *dia_ui = new TitleWidget(templatePath, titlesFolder, m_render, kapp->activeWindow()); + TitleWidget *dia_ui = new TitleWidget(templatePath, m_timecode, titlesFolder, m_render, kapp->activeWindow()); if (dia_ui->exec() == QDialog::Accepted) { - QStringList titleInfo = TitleWidget::getFreeTitleInfo(projectFolder()); + /*QStringList titleInfo = TitleWidget::getFreeTitleInfo(projectFolder()); QImage pix = dia_ui->renderedPixmap(); - pix.save(titleInfo.at(1)); + pix.save(titleInfo.at(1));*/ //dia_ui->saveTitle(path + ".kdenlivetitle"); - m_clipManager->slotAddTextClipFile(titleInfo.at(0), titleInfo.at(1), dia_ui->xml().toString(), group, groupId); + m_clipManager->slotAddTextClipFile(i18n("Title clip"), dia_ui->duration(), dia_ui->xml().toString(), group, groupId); setModified(true); emit selectLastAddedClip(QString::number(m_clipManager->lastClipId())); } @@ -1061,12 +1064,13 @@ void KdenliveDoc::slotCreateTextTemplateClip(QString group, const QString &group QStringList titleInfo = TitleWidget::getFreeTitleInfo(projectFolder(), true); - TitleWidget *dia_ui = new TitleWidget(path, titlesFolder, m_render, kapp->activeWindow()); + //TODO: rewrite with new title system (just set resource) + /*TitleWidget *dia_ui = new TitleWidget(path, titlesFolder, m_render, kapp->activeWindow()); QImage pix = dia_ui->renderedPixmap(); pix.save(titleInfo.at(1)); delete dia_ui; m_clipManager->slotAddTextTemplateClip(titleInfo.at(0), titleInfo.at(1), path, group, groupId); - setModified(true); + setModified(true);*/ emit selectLastAddedClip(QString::number(m_clipManager->lastClipId())); } diff --git a/src/kdenliveui.rc b/src/kdenliveui.rc index e36ca100..b099be38 100644 --- a/src/kdenliveui.rc +++ b/src/kdenliveui.rc @@ -68,7 +68,6 @@ Timeline - Guides diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 43d32f02..488975e9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -328,7 +328,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent m_timelineContextMenu->addAction(actionCollection()->action(KStandardAction::name(KStandardAction::Paste))); m_timelineContextClipMenu->addAction(actionCollection()->action("delete_timeline_clip")); - m_timelineContextClipMenu->addAction(actionCollection()->action("change_clip_speed")); m_timelineContextClipMenu->addAction(actionCollection()->action("group_clip")); m_timelineContextClipMenu->addAction(actionCollection()->action("ungroup_clip")); m_timelineContextClipMenu->addAction(actionCollection()->action("cut_timeline_clip")); @@ -381,11 +380,20 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent void MainWindow::queryQuit() { - kDebug() << "----- SAVING CONFUIG"; - if (queryClose()) { - Mlt::Factory::close(); - kapp->quit(); - } + delete m_effectStack; + delete m_activeTimeline; + delete m_projectMonitor; + kDebug() << "// DEL MON 1 done"; + delete m_clipMonitor; + kDebug() << "// DEL MON 2 done"; + delete m_activeDocument; + Mlt::Factory::close(); + qApp->quit(); + /* + if (queryClose()) { + Mlt::Factory::close(); + kapp->quit(); + }*/ } //virtual @@ -946,10 +954,10 @@ void MainWindow::setupActions() collection->addAction("delete_timeline_clip", deleteTimelineClip); connect(deleteTimelineClip, SIGNAL(triggered(bool)), this, SLOT(slotDeleteTimelineClip())); - KAction* editTimelineClipSpeed = new KAction(i18n("Change Clip Speed"), this); + /*KAction* editTimelineClipSpeed = new KAction(i18n("Change Clip Speed"), this); collection->addAction("change_clip_speed", editTimelineClipSpeed); editTimelineClipSpeed->setData("change_speed"); - connect(editTimelineClipSpeed, SIGNAL(triggered(bool)), this, SLOT(slotChangeClipSpeed())); + connect(editTimelineClipSpeed, SIGNAL(triggered(bool)), this, SLOT(slotChangeClipSpeed()));*/ KAction *stickTransition = collection->addAction("auto_transition"); stickTransition->setData(QString("auto")); @@ -1950,13 +1958,6 @@ void MainWindow::slotDeleteTimelineClip() } } -void MainWindow::slotChangeClipSpeed() -{ - if (m_activeTimeline) { - m_activeTimeline->projectView()->changeClipSpeed(); - } -} - void MainWindow::slotAddClipMarker() { DocClipBase *clip = NULL; @@ -2291,7 +2292,7 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) return; } QString path = clip->getProperty("resource"); - TitleWidget *dia_ui = new TitleWidget(KUrl(), titlepath, m_projectMonitor->render, this); + TitleWidget *dia_ui = new TitleWidget(KUrl(), m_activeDocument->timecode(), titlepath, m_projectMonitor->render, this); QDomDocument doc; doc.setContent(clip->getProperty("xmldata")); dia_ui->setXml(doc); @@ -2299,6 +2300,7 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) QRect rect = dia_ui->renderedRect(); QMap newprops; newprops.insert("xmldata", dia_ui->xml().toString()); + newprops.insert("out", QString::number(dia_ui->duration())); newprops.insert("frame_size", QString::number(rect.width()) + 'x' + QString::number(rect.height())); EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newprops, true); m_activeDocument->commandStack()->push(command); diff --git a/src/mainwindow.h b/src/mainwindow.h index d031f0b2..9133655f 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -272,7 +272,6 @@ private slots: void slotPaste(); void slotPasteEffects(); void slotReloadEffects(); - void slotChangeClipSpeed(); void slotAdjustClipMonitor(); void slotAdjustProjectMonitor(); diff --git a/src/mimetypes/kdenlive.xml b/src/mimetypes/kdenlive.xml index 7e3b6803..e4445c59 100644 --- a/src/mimetypes/kdenlive.xml +++ b/src/mimetypes/kdenlive.xml @@ -5,4 +5,9 @@ + + Kdenlive video title + + + diff --git a/src/monitor.cpp b/src/monitor.cpp index b0f7991e..0c12a74d 100644 --- a/src/monitor.cpp +++ b/src/monitor.cpp @@ -150,6 +150,7 @@ Monitor::~Monitor() delete m_timePos; delete m_overlay; delete m_monitorRefresh; + delete render; } QString Monitor::name() const diff --git a/src/projectlist.cpp b/src/projectlist.cpp index bb5f18f0..2fc16122 100644 --- a/src/projectlist.cpp +++ b/src/projectlist.cpp @@ -275,7 +275,7 @@ void ProjectList::slotUpdateClipProperties(const QString &id, QMap isGroup()) clip->setProperties(properties); - if (properties.contains("xmldata")) regenerateTemplateImage(clip); + //if (properties.contains("xmldata")) regenerateTemplateImage(clip); if (properties.contains("name")) { m_listView->blockSignals(true); clip->setText(1, properties.value("name")); @@ -318,10 +318,12 @@ void ProjectList::slotItemEdited(QTreeWidgetItem *item, int column) oldprops["description"] = clip->referencedClip()->getProperty("description"); newprops["description"] = item->text(2); - if (clip->clipType() == TEXT && !clip->referencedClip()->getProperty("xmltemplate").isEmpty()) { + if (clip->clipType() == TEXT && !clip->referencedClip()->getProperty("xmldata").isEmpty()) { // This is a text template clip, update the image - oldprops.insert("xmldata", clip->referencedClip()->getProperty("xmldata")); - newprops.insert("xmldata", generateTemplateXml(clip->referencedClip()->getProperty("xmltemplate"), item->text(2)).toString()); + /*oldprops.insert("xmldata", clip->referencedClip()->getProperty("xmldata")); + newprops.insert("xmldata", generateTemplateXml(clip->referencedClip()->getProperty("xmltemplate"), item->text(2)).toString());*/ + oldprops.insert("templatetext", clip->referencedClip()->getProperty("templatetext")); + newprops.insert("templatetext", item->text(2)); } slotUpdateClipProperties(clip->clipId(), newprops); @@ -583,7 +585,7 @@ void ProjectList::updateAllClips() ProjectItem *item = static_cast (*it); if (!item->isGroup()) { DocClipBase *clip = item->referencedClip(); - if (clip->clipType() == TEXT && !QFile::exists(clip->fileURL().path())) { + /*if (clip->clipType() == TEXT && !QFile::exists(clip->fileURL().path())) { // regenerate text clip image if required TitleWidget *dia_ui = new TitleWidget(KUrl(), QString(), m_render, this); QDomDocument doc; @@ -592,7 +594,7 @@ void ProjectList::updateAllClips() QImage pix = dia_ui->renderedPixmap(); pix.save(clip->fileURL().path()); delete dia_ui; - } + }*/ if (item->referencedClip()->producer() == NULL) { if (clip->isPlaceHolder() == false) requestClipInfo(clip->toXML(), clip->getId()); @@ -623,7 +625,7 @@ void ProjectList::slotAddClip(const QList givenList, const QString &group KUrl::List list; if (givenList.isEmpty()) { // Build list of mime types - QStringList mimeTypes = QStringList() << "application/x-kdenlive" << "video/x-flv" << "application/vnd.rn-realmedia" << "video/x-dv" << "video/dv" << "video/x-msvideo" << "video/x-matroska" << "video/mlt-playlist" << "video/mpeg" << "video/ogg" << "video/x-ms-wmv" << "audio/x-flac" << "audio/x-matroska" << "audio/mp4" << "audio/mpeg" << "audio/x-mp3" << "audio/ogg" << "audio/x-wav" << "application/ogg" << "video/mp4" << "video/quicktime" << "image/gif" << "image/jpeg" << "image/png" << "image/x-tga" << "image/x-bmp" << "image/svg+xml" << "image/tiff" << "image/x-xcf-gimp" << "image/x-vnd.adobe.photoshop" << "image/x-pcx" << "image/x-exr"; + QStringList mimeTypes = QStringList() << "application/x-kdenlive" << "application/x-kdenlivetitle" << "video/x-flv" << "application/vnd.rn-realmedia" << "video/x-dv" << "video/dv" << "video/x-msvideo" << "video/x-matroska" << "video/mlt-playlist" << "video/mpeg" << "video/ogg" << "video/x-ms-wmv" << "audio/x-flac" << "audio/x-matroska" << "audio/mp4" << "audio/mpeg" << "audio/x-mp3" << "audio/ogg" << "audio/x-wav" << "application/ogg" << "video/mp4" << "video/quicktime" << "image/gif" << "image/jpeg" << "image/png" << "image/x-tga" << "image/x-bmp" << "image/svg+xml" << "image/tiff" << "image/x-xcf-gimp" << "image/x-vnd.adobe.photoshop" << "image/x-pcx" << "image/x-exr"; QString allExtensions; foreach(const QString& mimeType, mimeTypes) { @@ -970,28 +972,30 @@ void ProjectList::regenerateTemplate(const QString &id) void ProjectList::regenerateTemplate(ProjectItem *clip) { + //TODO: remove this unused method, only force_reload is necessary // Generate image for template clip - const QString comment = clip->referencedClip()->getProperty("description"); - const QString path = clip->referencedClip()->getProperty("xmltemplate"); + /*const QString comment = clip->referencedClip()->getProperty("description"); + const QString path = clip->referencedClip()->getProperty("resource"); QDomDocument doc = generateTemplateXml(path, comment); TitleWidget *dia_ui = new TitleWidget(KUrl(), QString(), m_render, this); dia_ui->setXml(doc); QImage pix = dia_ui->renderedPixmap(); pix.save(clip->clipUrl().path()); - delete dia_ui; + delete dia_ui;*/ clip->referencedClip()->producer()->set("force_reload", 1); } void ProjectList::regenerateTemplateImage(ProjectItem *clip) { + //TODO: remove this unused method // Generate image for template clip - TitleWidget *dia_ui = new TitleWidget(KUrl(), QString(), m_render, this); + /*TitleWidget *dia_ui = new TitleWidget(KUrl(), QString(), m_render, this); QDomDocument doc; doc.setContent(clip->referencedClip()->getProperty("xmldata")); dia_ui->setXml(doc); QImage pix = dia_ui->renderedPixmap(); pix.save(clip->clipUrl().path()); - delete dia_ui; + delete dia_ui;*/ } QDomDocument ProjectList::generateTemplateXml(QString path, const QString &replaceString) diff --git a/src/projectlistview.cpp b/src/projectlistview.cpp index fabe6a23..d96f6a7b 100644 --- a/src/projectlistview.cpp +++ b/src/projectlistview.cpp @@ -154,6 +154,9 @@ void ProjectListView::dropEvent(QDropEvent *event) } } emit addClip(event->mimeData()->urls(), groupName, groupId); + event->setDropAction(Qt::CopyAction); + event->accept(); + return; } else if (event->mimeData()->hasFormat("kdenlive/producerslist")) { ProjectItem *item = static_cast (itemAt(event->pos())); if (item) { @@ -258,7 +261,7 @@ void ProjectListView::mouseMoveEvent(QMouseEvent *event) drag->setMimeData(mimeData); drag->setPixmap(clickItem->icon(0).pixmap(iconSize())); drag->setHotSpot(QPoint(0, 50)); - drag->exec(Qt::MoveAction); + drag->exec(); } //event->accept(); } @@ -267,8 +270,7 @@ void ProjectListView::mouseMoveEvent(QMouseEvent *event) // virtual void ProjectListView::dragMoveEvent(QDragMoveEvent * event) { - event->setDropAction(Qt::IgnoreAction); - event->setDropAction(Qt::MoveAction); + //event->setDropAction(Qt::MoveAction); if (event->mimeData()->hasText()) { event->acceptProposedAction(); } diff --git a/src/renderer.cpp b/src/renderer.cpp index 05fc9c62..cb5c8e25 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -77,13 +77,11 @@ Render::Render(const QString & rendererName, int winid, int /* extid */, QWidget m_winid(winid) { kDebug() << "////////// USING PROFILE: " << (char*)KdenliveSettings::current_profile().toUtf8().data(); - m_refreshTimer = new QTimer(this); - connect(m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh())); /*if (rendererName == "project") m_monitorId = 10000; else m_monitorId = 10001;*/ - m_osdTimer = new QTimer(this); - connect(m_osdTimer, SIGNAL(timeout()), this, SLOT(slotOsdTimeout())); + /*m_osdTimer = new QTimer(this); + connect(m_osdTimer, SIGNAL(timeout()), this, SLOT(slotOsdTimeout()));*/ buildConsumer(); @@ -101,8 +99,22 @@ Render::~Render() void Render::closeMlt() { - delete m_osdTimer; - delete m_refreshTimer; + //delete m_osdTimer; + + Mlt::Service service(m_mltProducer->get_service()); + if (service.type() == tractor_type) { + Mlt::Tractor tractor(service); + int trackNb = tractor.count(); + + while (trackNb > 1) { + Mlt::Producer trackProducer(tractor.track(trackNb - 1)); + Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service()); + trackPlaylist.clear(); + trackNb--; + } + } + + kDebug() << "// // // CLOSE RENDERER"; delete m_mltConsumer; delete m_mltProducer; delete m_blackClip; @@ -512,14 +524,23 @@ void Render::getFileProperties(const QDomElement &xml, const QString &clipId, bo { KUrl url = KUrl(xml.attribute("resource", QString())); Mlt::Producer *producer = NULL; - if (xml.attribute("type").toInt() == TEXT && !QFile::exists(url.path())) { + /*if (xml.attribute("type").toInt() == TEXT && !QFile::exists(url.path())) { emit replyGetFileProperties(clipId, producer, QMap < QString, QString >(), QMap < QString, QString >(), replaceProducer); return; - } + }*/ if (xml.attribute("type").toInt() == COLOR) { char *tmp = decodedString("colour:" + xml.attribute("colour")); producer = new Mlt::Producer(*m_mltProfile, 0, tmp); delete[] tmp; + } else if (xml.attribute("type").toInt() == TEXT) { + char *tmp = decodedString("kdenlivetitle:" + xml.attribute("resource")); + producer = new Mlt::Producer(*m_mltProfile, 0, tmp); + delete[] tmp; + if (xml.hasAttribute("xmldata")) { + char *tmp = decodedString(xml.attribute("xmldata")); + producer->set("xmldata", tmp); + delete[] tmp; + } } else if (url.isEmpty()) { QDomDocument doc; QDomElement mlt = doc.createElement("mlt"); @@ -956,6 +977,7 @@ void Render::saveZone(KUrl url, QString desc, QPoint zone) tmppath = decodedString(desc); Mlt::Playlist list; list.insert_at(0, prod, 0); + delete prod; list.set("title", tmppath); delete[] tmppath; xmlConsumer.connect(list); @@ -1037,7 +1059,7 @@ void Render::setVolume(double /*volume*/) if (m_mltProducer->attach(*m_osdInfo) == 1) kDebug()<<"////// error attaching filter"; }*/ refresh(); - m_osdTimer->setSingleShot(2500); + //m_osdTimer->setSingleShot(2500); } void Render::slotOsdTimeout() @@ -1247,12 +1269,6 @@ void Render::seekToFrameDiff(int diff) refresh(); } -void Render::askForRefresh() -{ - // Use a Timer so that we don't refresh too much - m_refreshTimer->start(300); -} - void Render::doRefresh() { // Use a Timer so that we don't refresh too much @@ -1263,7 +1279,6 @@ void Render::refresh() { if (!m_mltProducer || m_isBlocked) return; - m_refreshTimer->stop(); if (m_mltConsumer) { m_mltConsumer->set("refresh", 1); } @@ -1434,19 +1449,23 @@ void Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *pr Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service()); //kDebug()<<"/// INSERT cLIP: "< 1) { // We want a slowmotion producer double speed = element.attribute("speed", "1.0").toDouble(); + int strobe = element.attribute("strobe", "1").toInt(); QString url = QString::fromUtf8(prod->get("resource")); url.append('?' + QString::number(speed)); + if (strobe > 1) url.append("&strobe=" + QString::number(strobe)); Mlt::Producer *slowprod = m_slowmotionProducers.value(url); if (!slowprod || slowprod->get_producer() == NULL) { char *tmp = decodedString(url); slowprod = new Mlt::Producer(*m_mltProfile, "framebuffer", tmp); + if (strobe > 1) slowprod->set("strobe", strobe); delete[] tmp; QString id = prod->get("id"); if (id.contains('_')) id = id.section('_', 0, 0); QString producerid = "slowmotion:" + id + ':' + QString::number(speed); + if (strobe > 1) producerid.append(':' + QString::number(strobe)); tmp = decodedString(producerid); slowprod->set("id", tmp); delete[] tmp; @@ -1456,8 +1475,8 @@ void Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *pr } Mlt::Producer *clip = prod->cut((int) info.cropStart.frames(m_fps), (int)(info.endPos - info.startPos + info.cropStart).frames(m_fps) - 1); - int newIndex = trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *clip, 1); - + int newIndex = trackPlaylist.insert_at((int) info.startPos.frames(m_fps), clip, 1); + delete clip; /*if (QString(prod->get("transparency")).toInt() == 1) mltAddClipTransparency(info, info.track - 1, QString(prod->get("id")).toInt());*/ @@ -1514,6 +1533,8 @@ void Render::mltCutClip(int track, GenTime position) } Mlt::Service clipService(original->get_service()); Mlt::Service dupService(clip->get_service()); + delete original; + delete clip; int ct = 0; Mlt::Filter *filter = clipService.filter(ct); while (filter) { @@ -1582,7 +1603,8 @@ bool Render::mltRemoveClip(int track, GenTime position) } //kDebug()<<"//// Deleting at: "<< (int) position.frames(m_fps) <<" --------------------------------------"; m_isBlocked = true; - trackPlaylist.replace_with_blank(clipIndex); + Mlt::Producer *clip = trackPlaylist.replace_with_blank(clipIndex); + delete clip; trackPlaylist.consolidate_blanks(0); /*if (QString(clip.parent().get("transparency")).toInt() == 1) mltDeleteTransparency((int) position.frames(m_fps), track, QString(clip.parent().get("id")).toInt());*/ @@ -1679,11 +1701,11 @@ void Render::mltInsertSpace(QMap trackClipStartList, QMap if (!trackPlaylist.is_blank(clipIndex)) clipIndex --; if (!trackPlaylist.is_blank(clipIndex)) kDebug() << "//// ERROR TRYING TO DELETE SPACE FROM " << insertPos; int position = trackPlaylist.clip_start(clipIndex); - int blankDuration = trackPlaylist.clip_length(clipIndex) - 1; + int blankDuration = trackPlaylist.clip_length(clipIndex); diff = -diff; - if (blankDuration - diff == 1) + if (blankDuration - diff == 0) trackPlaylist.remove(clipIndex); - else trackPlaylist.remove_region(position, diff - 1); + else trackPlaylist.remove_region(position, diff); } trackPlaylist.consolidate_blanks(0); } @@ -1740,10 +1762,10 @@ void Render::mltInsertSpace(QMap trackClipStartList, QMap if (!trackPlaylist.is_blank(clipIndex)) clipIndex --; if (!trackPlaylist.is_blank(clipIndex)) kDebug() << "//// ERROR TRYING TO DELETE SPACE FROM " << insertPos; int position = trackPlaylist.clip_start(clipIndex); - int blankDuration = trackPlaylist.clip_length(clipIndex) - 1; - if (diff + blankDuration == 1) + int blankDuration = trackPlaylist.clip_length(clipIndex); + if (diff + blankDuration == 0) trackPlaylist.remove(clipIndex); - else trackPlaylist.remove_region(position, - diff - 1); + else trackPlaylist.remove_region(position, - diff); } trackPlaylist.consolidate_blanks(0); } @@ -1798,7 +1820,7 @@ void Render::mltPasteEffects(Mlt::Producer *source, Mlt::Producer *dest) } } -int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt::Producer *prod) +int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, int strobe, Mlt::Producer *prod) { m_isBlocked = true; int newLength = 0; @@ -1831,22 +1853,26 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt QString serv = clipparent.get("mlt_service"); QString id = clipparent.get("id"); //kDebug() << "CLIP SERVICE: " << serv; - if (serv == "avformat" && speed != 1.0) { + if (serv == "avformat" && (speed != 1.0 || strobe > 1)) { mlt_service_lock(service.get_service()); QString url = QString::fromUtf8(clipparent.get("resource")); url.append('?' + QString::number(speed)); + if (strobe > 1) url.append("&strobe=" + QString::number(strobe)); Mlt::Producer *slowprod = m_slowmotionProducers.value(url); if (!slowprod || slowprod->get_producer() == NULL) { char *tmp = decodedString(url); slowprod = new Mlt::Producer(*m_mltProfile, "framebuffer", tmp); + if (strobe > 1) slowprod->set("strobe", strobe); delete[] tmp; QString producerid = "slowmotion:" + id + ':' + QString::number(speed); + if (strobe > 1) producerid.append(':' + QString::number(strobe)); tmp = decodedString(producerid); slowprod->set("id", tmp); delete[] tmp; m_slowmotionProducers.insert(url, slowprod); } - trackPlaylist.replace_with_blank(clipIndex); + Mlt::Producer *clip = trackPlaylist.replace_with_blank(clipIndex); + delete clip; trackPlaylist.consolidate_blanks(0); // Check that the blank space is long enough for our new duration clipIndex = trackPlaylist.get_clip_index_at(startPos); @@ -1860,14 +1886,16 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt // move all effects to the correct producer mltPasteEffects(clip, cut); - trackPlaylist.insert_at(startPos, *cut, 1); + trackPlaylist.insert_at(startPos, cut, 1); + delete cut; clipIndex = trackPlaylist.get_clip_index_at(startPos); newLength = trackPlaylist.clip_length(clipIndex); mlt_service_unlock(service.get_service()); - } else if (speed == 1.0) { + } else if (speed == 1.0 && strobe < 2) { mlt_service_lock(service.get_service()); - trackPlaylist.replace_with_blank(clipIndex); + Mlt::Producer *clip = trackPlaylist.replace_with_blank(clipIndex); + delete clip; trackPlaylist.consolidate_blanks(0); // Check that the blank space is long enough for our new duration @@ -1885,7 +1913,8 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt // move all effects to the correct producer mltPasteEffects(clip, cut); - trackPlaylist.insert_at(startPos, *cut, 1); + trackPlaylist.insert_at(startPos, cut, 1); + delete cut; clipIndex = trackPlaylist.get_clip_index_at(startPos); newLength = trackPlaylist.clip_length(clipIndex); mlt_service_unlock(service.get_service()); @@ -1895,22 +1924,26 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt QString url = QString::fromUtf8(clipparent.get("resource")); url = url.section('?', 0, 0); url.append('?' + QString::number(speed)); + if (strobe > 1) url.append("&strobe=" + QString::number(strobe)); Mlt::Producer *slowprod = m_slowmotionProducers.value(url); if (!slowprod || slowprod->get_producer() == NULL) { char *tmp = decodedString(url); slowprod = new Mlt::Producer(*m_mltProfile, "framebuffer", tmp); delete[] tmp; + slowprod->set("strobe", strobe); QString producerid = "slowmotion:" + id.section(':', 1, 1) + ':' + QString::number(speed); + if (strobe > 1) producerid.append(':' + QString::number(strobe)); tmp = decodedString(producerid); slowprod->set("id", tmp); delete[] tmp; m_slowmotionProducers.insert(url, slowprod); } - trackPlaylist.replace_with_blank(clipIndex); + Mlt::Producer *clip = trackPlaylist.replace_with_blank(clipIndex); + delete clip; trackPlaylist.consolidate_blanks(0); GenTime oldDuration = GenTime(clipLength, m_fps); - GenTime newDuration = oldDuration * oldspeed / speed; + GenTime newDuration = oldDuration * (oldspeed / speed); // Check that the blank space is long enough for our new duration clipIndex = trackPlaylist.get_clip_index_at(startPos); @@ -1925,7 +1958,8 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt // move all effects to the correct producer mltPasteEffects(clip, cut); - trackPlaylist.insert_at(startPos, *cut, 1); + trackPlaylist.insert_at(startPos, cut, 1); + delete cut; clipIndex = trackPlaylist.get_clip_index_at(startPos); newLength = trackPlaylist.clip_length(clipIndex); @@ -1952,6 +1986,7 @@ bool Render::mltRemoveEffect(int track, GenTime position, QString index, bool up return success; } Mlt::Service clipService(clip->get_service()); + delete clip; // if (tag.startsWith("ladspa")) tag = "ladspa"; m_isBlocked = true; int ct = 0; @@ -1988,7 +2023,7 @@ bool Render::mltAddEffect(int track, GenTime position, EffectsParameterList para } Mlt::Service clipService(clip->get_service()); m_isBlocked = true; - + delete clip; // temporarily remove all effects after insert point QList filtersList; const int filter_ix = params.paramValue("kdenlive_ix").toInt(); @@ -2136,6 +2171,7 @@ bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList par return false; } Mlt::Service clipService(clip->get_service()); + delete clip; m_isBlocked = true; int ct = 0; Mlt::Filter *filter = clipService.filter(ct); @@ -2200,6 +2236,7 @@ void Render::mltMoveEffect(int track, GenTime position, int oldPos, int newPos) return; } Mlt::Service clipService(clip->get_service()); + delete clip; m_isBlocked = true; int ct = 0; QList filtersList; @@ -2306,11 +2343,11 @@ bool Render::mltResizeClipEnd(ItemInfo info, GenTime clipDuration) // If this is not the last clip in playlist if (trackPlaylist.is_blank(clipIndex)) { int blankStart = trackPlaylist.clip_start(clipIndex); - int blankDuration = trackPlaylist.clip_length(clipIndex) - 1; + int blankDuration = trackPlaylist.clip_length(clipIndex); if (diff > blankDuration) kDebug() << "// ERROR blank clip is not large enough to get back required space!!!"; - if (diff - blankDuration == 1) { + if (diff - blankDuration == 0) { trackPlaylist.remove(clipIndex); - } else trackPlaylist.remove_region(blankStart, diff - 1); + } else trackPlaylist.remove_region(blankStart, diff); } else { kDebug() << "/// RESIZE ERROR, NXT CLIP IS NOT BLK: " << clipIndex; } @@ -2462,19 +2499,21 @@ void Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod) 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()) { + Mlt::Producer *clipProducer = trackPlaylist.replace_with_blank(clipIndex); + if (clipProducer->is_blank()) { kDebug() << "// ERROR UPDATING CLIP PROD"; + delete clipProducer; mlt_service_unlock(m_mltConsumer->get_service()); m_isBlocked--; return; } - Mlt::Producer *clip = prod->cut(clipProducer.get_in(), clipProducer.get_out()); + Mlt::Producer *clip = prod->cut(clipProducer->get_in(), clipProducer->get_out()); // move all effects to the correct producer - mltPasteEffects(&clipProducer, clip); - + mltPasteEffects(clipProducer, clip); trackPlaylist.insert_at(pos, clip, 1); + delete clip; + delete clipProducer; mlt_service_unlock(m_mltConsumer->get_service()); m_isBlocked--; } @@ -2494,10 +2533,11 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn kDebug() << "////// LOOKING FOR CLIP TO MOVE, INDEX: " << clipIndex; bool checkLength = false; if (endTrack == startTrack) { - Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex)); - if (!trackPlaylist.is_blank_at(moveEnd) || clipProducer.is_blank()) { + Mlt::Producer *clipProducer = trackPlaylist.replace_with_blank(clipIndex); + if (!trackPlaylist.is_blank_at(moveEnd) || clipProducer->is_blank()) { // error, destination is not empty if (!trackPlaylist.is_blank_at(moveEnd)) trackPlaylist.insert_at(moveStart, clipProducer, 1); + delete clipProducer; //int ix = trackPlaylist.get_clip_index_at(moveEnd); kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd; mlt_service_unlock(service.get_service()); @@ -2506,6 +2546,7 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn } else { trackPlaylist.consolidate_blanks(0); int newIndex = trackPlaylist.insert_at(moveEnd, clipProducer, 1); + delete clipProducer; /*if (QString(clipProducer.parent().get("transparency")).toInt() == 1) { mltMoveTransparency(moveStart, moveEnd, startTrack, endTrack, QString(clipProducer.parent().get("id")).toInt()); }*/ @@ -2521,10 +2562,11 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn m_isBlocked--; return false; } else { - Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex)); - if (clipProducer.is_blank()) { + Mlt::Producer *clipProducer = trackPlaylist.replace_with_blank(clipIndex); + if (clipProducer->is_blank()) { // error, destination is not empty //int ix = trackPlaylist.get_clip_index_at(moveEnd); + delete clipProducer; kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd; mlt_service_unlock(service.get_service()); m_isBlocked--; @@ -2534,24 +2576,27 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn destTrackPlaylist.consolidate_blanks(1); Mlt::Producer *clip; // check if we are moving a slowmotion producer - QString serv = clipProducer.parent().get("mlt_service"); - QString currentid = clipProducer.parent().get("id"); + QString serv = clipProducer->parent().get("mlt_service"); + QString currentid = clipProducer->parent().get("id"); if (serv == "framebuffer" || currentid.endsWith("_video")) { - clip = &clipProducer; + clip = clipProducer; } else { if (prod == NULL) { // Special case: prod is null when using placeholder clips. // in that case, use the producer existing in playlist. Note that // it will bypass the one producer per track logic and might cause // Sound cracks if clip is moved so that it overlaps another copy of itself - clip = clipProducer.cut(clipProducer.get_in(), clipProducer.get_out()); - } else clip = prod->cut(clipProducer.get_in(), clipProducer.get_out()); + clip = clipProducer->cut(clipProducer->get_in(), clipProducer->get_out()); + } else clip = prod->cut(clipProducer->get_in(), clipProducer->get_out()); } // move all effects to the correct producer - mltPasteEffects(&clipProducer, clip); + mltPasteEffects(clipProducer, clip); int newIndex = destTrackPlaylist.insert_at(moveEnd, clip, 1); + delete clip; + clip = NULL; + if (clipProducer) delete clipProducer; destTrackPlaylist.consolidate_blanks(0); /*if (QString(clipProducer.parent().get("transparency")).toInt() == 1) { kDebug() << "//////// moving clip transparency"; @@ -3010,6 +3055,8 @@ void Render::fillSlowMotionProducers() if (id.startsWith("slowmotion:") && !nprod->is_blank()) { // this is a slowmotion producer, add it to the list QString url = QString::fromUtf8(nprod->get("resource")); + int strobe = nprod->get_int("strobe"); + if (strobe > 1) url.append("&strobe=" + QString::number(strobe)); if (!m_slowmotionProducers.contains(url)) { m_slowmotionProducers.insert(url, nprod); } diff --git a/src/renderer.h b/src/renderer.h index b0990d88..b36efdb4 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -150,7 +150,6 @@ Q_OBJECT public: /** Gives the aspect ratio of the consumer */ double consumerRatio() const; - void askForRefresh(); void doRefresh(); /** Save current producer frame as image */ @@ -201,7 +200,7 @@ Q_OBJECT public: to the clip and 0.6 is the speed in percents. The newly created producer will have it's "id" parameter set to: "slowmotion:parentid:speed", where parentid is the id of the original clip in the ClipManager list and speed is the current speed */ - int mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt::Producer *prod); + int mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, int strobe, Mlt::Producer *prod); QList producersList(); void updatePreviewSettings(); @@ -228,7 +227,6 @@ private: // Private attributes & methods Mlt::Producer *m_blackClip; QString m_activeProfile; - QTimer *m_refreshTimer; QTimer *m_osdTimer; /** A human-readable description of this renderer. */ diff --git a/src/statusbarmessagelabel.cpp b/src/statusbarmessagelabel.cpp index 3fcf28fc..b7a55812 100644 --- a/src/statusbarmessagelabel.cpp +++ b/src/statusbarmessagelabel.cpp @@ -32,7 +32,7 @@ #include #include #include -#include + StatusBarMessageLabel::StatusBarMessageLabel(QWidget* parent) : QWidget(parent), @@ -40,7 +40,6 @@ StatusBarMessageLabel::StatusBarMessageLabel(QWidget* parent) : m_state(Default), m_illumination(-64), m_minTextHeight(-1), - m_timer(0), m_closeButton(0) { setMinimumHeight(KIconLoader::SizeSmall); @@ -49,8 +48,7 @@ StatusBarMessageLabel::StatusBarMessageLabel(QWidget* parent) : palette.setColor(QPalette::Background, Qt::transparent); setPalette(palette); - m_timer = new QTimer(this); - connect(m_timer, SIGNAL(timeout()), this, SLOT(timerDone())); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(timerDone())); m_closeButton = new QPushButton(i18nc("@action:button", "Close"), this); m_closeButton->hide(); @@ -83,7 +81,7 @@ void StatusBarMessageLabel::setMessage(const QString& text, m_illumination = -64; m_state = Default; - m_timer->stop(); + m_timer.stop(); const char* iconName = 0; QPixmap pixmap; @@ -101,14 +99,14 @@ void StatusBarMessageLabel::setMessage(const QString& text, case ErrorMessage: iconName = "dialog-warning"; - m_timer->start(100); + m_timer.start(100); m_state = Illuminate; m_closeButton->hide(); break; case MltError: iconName = "dialog-close"; - m_timer->start(100); + m_timer.start(100); m_state = Illuminate; updateCloseButtonPosition(); m_closeButton->show(); @@ -192,7 +190,7 @@ void StatusBarMessageLabel::timerDone() update(); } else { m_state = Illuminated; - m_timer->start(1500); + m_timer.start(1500); } break; } @@ -201,7 +199,7 @@ void StatusBarMessageLabel::timerDone() // start desaturation if (m_type != MltError) { m_state = Desaturate; - m_timer->start(80); + m_timer.start(80); } break; } @@ -211,7 +209,7 @@ void StatusBarMessageLabel::timerDone() if (m_illumination < -128) { m_illumination = 0; m_state = Default; - m_timer->stop(); + m_timer.stop(); setMessage(QString(), DefaultMessage); } else { m_illumination -= 5; diff --git a/src/statusbarmessagelabel.h b/src/statusbarmessagelabel.h index ce4b3fe1..5f3cc8a4 100644 --- a/src/statusbarmessagelabel.h +++ b/src/statusbarmessagelabel.h @@ -24,16 +24,16 @@ #define STATUSBARMESSAGELABEL_H -#include -#include +#include +#include +#include +#include -#include #include class QPaintEvent; class QResizeEvent; class QPushButton; -class QTimer; /** * @brief Represents a message text label as part of the status bar. @@ -124,7 +124,7 @@ private: State m_state; int m_illumination; int m_minTextHeight; - QTimer* m_timer; + QTimer m_timer; QString m_text; QList m_pendingMessages; QPixmap m_pixmap; diff --git a/src/titledocument.cpp b/src/titledocument.cpp index 959aac69..1f78d5d8 100644 --- a/src/titledocument.cpp +++ b/src/titledocument.cpp @@ -165,12 +165,13 @@ QColor TitleDocument::getBackgroundColor() } -bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv) +bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv, double out) { if (!m_scene) return false; QDomDocument doc = xml(startv, endv); + doc.documentElement().setAttribute("out", out); KTemporaryFile tmpfile; if (!tmpfile.open()) { kWarning() << "///// CANNOT CREATE TMP FILE in: " << tmpfile.fileName(); @@ -187,7 +188,7 @@ bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, return KIO::NetAccess::upload(tmpfile.fileName(), url, 0); } -int TitleDocument::loadDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv) +int TitleDocument::loadDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv, double *out) { QString tmpfile; QDomDocument doc; @@ -202,14 +203,21 @@ int TitleDocument::loadDocument(const KUrl& url, QGraphicsPolygonItem* startv, Q } else return -1; KIO::NetAccess::removeTempFile(tmpfile); - return loadFromXml(doc, startv, endv); + return loadFromXml(doc, startv, endv, out); } return -1; } -int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv) +int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv, double *out) { QDomNodeList titles = doc.elementsByTagName("kdenlivetitle"); + + //TODO: get default title duration instead of hardcoded one + if (doc.documentElement().hasAttribute("out")) + *out = doc.documentElement().attribute("out").toDouble(); + else + *out = 5000; + int maxZValue = 0; if (titles.size()) { diff --git a/src/titledocument.h b/src/titledocument.h index 263d79e6..637cdfa2 100644 --- a/src/titledocument.h +++ b/src/titledocument.h @@ -30,10 +30,10 @@ class TitleDocument public: TitleDocument(); void setScene(QGraphicsScene* scene); - bool saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv); - int loadDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv); + bool saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv, double out); + int loadDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv, double *out); QDomDocument xml(QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv); - int loadFromXml(QDomDocument doc, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv); + int loadFromXml(QDomDocument doc, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv, double *out); /** \brief Get the background color (incl. alpha) from the document, if possibly * \returns The background color of the document, inclusive alpha. If none found, returns (0,0,0,0) */ QColor getBackgroundColor(); diff --git a/src/titlewidget.cpp b/src/titlewidget.cpp index 04209c09..1cf5cc1c 100644 --- a/src/titlewidget.cpp +++ b/src/titlewidget.cpp @@ -43,7 +43,7 @@ const int RECTITEM = 3; const int TEXTITEM = 8; static bool insertingValues = false; -TitleWidget::TitleWidget(KUrl url, QString projectTitlePath, Render *render, QWidget *parent) : +TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render *render, QWidget *parent) : QDialog(parent), Ui::TitleWidget_UI(), m_startViewport(NULL), @@ -51,7 +51,8 @@ TitleWidget::TitleWidget(KUrl url, QString projectTitlePath, Render *render, QWi m_render(render), m_count(0), m_unicodeDialog(new UnicodeDialog(UnicodeDialog::InputHex)), - m_projectTitlePath(projectTitlePath) + m_projectTitlePath(projectTitlePath), + m_tc(tc) { setupUi(this); setFont(KGlobalSettings::toolBarFont()); @@ -66,6 +67,9 @@ TitleWidget::TitleWidget(KUrl url, QString projectTitlePath, Render *render, QWi m_frameHeight = render->renderHeight(); showToolbars(TITLE_NONE); + //TODO: get default title duration instead of hardcoded one + title_duration->setText(m_tc.getTimecode(GenTime(5000 / 1000.0), m_render->fps())); + connect(kcolorbutton, SIGNAL(clicked()), this, SLOT(slotChangeBackground())) ; connect(horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(slotChangeBackground())) ; @@ -265,7 +269,9 @@ TitleWidget::TitleWidget(KUrl url, QString projectTitlePath, Render *render, QWi kDebug() << "// TITLE WIDGWT: " << graphicsView->viewport()->width() << "x" << graphicsView->viewport()->height(); //toolBox->setItemEnabled(2, false); if (!url.isEmpty()) { - m_count = m_titledocument.loadDocument(url, m_startViewport, m_endViewport) + 1; + double out; + m_count = m_titledocument.loadDocument(url, m_startViewport, m_endViewport, &out) + 1; + title_duration->setText(m_tc.getTimecode(GenTime(out), m_render->fps())); slotSelectTool(); } else { slotTextTool(); @@ -1306,7 +1312,9 @@ void TitleWidget::loadTitle() if (items.at(i)->zValue() > -1000) delete items.at(i); } m_scene->clearTextSelection(); - m_count = m_titledocument.loadDocument(url, m_startViewport, m_endViewport) + 1; + double out; + m_count = m_titledocument.loadDocument(url, m_startViewport, m_endViewport, &out) + 1; + title_duration->setText(m_tc.getTimecode(GenTime(out / 1000.0), m_render->fps())); insertingValues = true; startViewportX->setValue(m_startViewport->data(0).toInt()); startViewportY->setValue(m_startViewport->data(1).toInt()); @@ -1323,7 +1331,7 @@ void TitleWidget::saveTitle(KUrl url) { if (url.isEmpty()) url = KFileDialog::getSaveUrl(KUrl(m_projectTitlePath), "*.kdenlivetitle", this, i18n("Save Title")); if (!url.isEmpty()) { - if (m_titledocument.saveDocument(url, m_startViewport, m_endViewport) == false) + if (m_titledocument.saveDocument(url, m_startViewport, m_endViewport, GenTime(m_tc.getFrameCount(title_duration->text(), m_render->fps()), m_render->fps()).ms()) == false) KMessageBox::error(this, i18n("Cannot write to file %1", url.path())); } } @@ -1331,15 +1339,30 @@ void TitleWidget::saveTitle(KUrl url) QDomDocument TitleWidget::xml() { QDomDocument doc = m_titledocument.xml(m_startViewport, m_endViewport); + doc.documentElement().setAttribute("out", GenTime(m_tc.getFrameCount(title_duration->text(), m_render->fps()), m_render->fps()).ms()); if (cropImage->isChecked()) { doc.documentElement().setAttribute("crop", 1); } return doc; } +int TitleWidget::duration() const +{ + return GenTime(m_tc.getFrameCount(title_duration->text(), m_render->fps()), m_render->fps()).frames(m_render->fps()); +} + void TitleWidget::setXml(QDomDocument doc) { - m_count = m_titledocument.loadFromXml(doc, m_startViewport, m_endViewport); + double out; + m_count = m_titledocument.loadFromXml(doc, m_startViewport, m_endViewport, &out); + kDebug() << "\n\n// TITLE OUT: " << out; + title_duration->setText(m_tc.getTimecode(GenTime(out / 1000.0), m_render->fps())); + /*if (doc.documentElement().hasAttribute("out")) { + GenTime duration = GenTime(doc.documentElement().attribute("out").toDouble() / 1000.0); + title_duration->setText(m_tc.getTimecode(duration, m_render->fps())); + } + else title_duration->setText(m_tc.getTimecode(GenTime(5000), m_render->fps()));*/ + QDomElement e = doc.documentElement(); cropImage->setChecked(e.hasAttribute("crop")); m_transformations.clear(); diff --git a/src/titlewidget.h b/src/titlewidget.h index d4a5fa82..26e7e84a 100644 --- a/src/titlewidget.h +++ b/src/titlewidget.h @@ -24,6 +24,7 @@ #include "renderer.h" #include "graphicsscenerectmove.h" #include "unicodedialog.h" +#include "timecode.h" #include #include @@ -48,7 +49,7 @@ class TitleWidget : public QDialog , public Ui::TitleWidget_UI public: /** \brief Constructor * \param projectPath Path to use when user requests loading or saving of titles as .kdenlivetitle documents */ - TitleWidget(KUrl url, QString projectTitlePath, Render *render, QWidget *parent = 0); + TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render *render, QWidget *parent = 0); virtual ~TitleWidget(); QDomDocument xml(); void setXml(QDomDocument doc); @@ -75,6 +76,9 @@ public: */ const QRect renderedRect(); + /** \brief Get clip duration. */ + int duration() const; + protected: virtual void resizeEvent(QResizeEvent * event); @@ -98,10 +102,12 @@ private: QAction *m_buttonLoad; QAction *m_unicodeAction; + /** \brief Dialog for entering unicode in text fields */ UnicodeDialog *m_unicodeDialog; /** project path for storing title clips */ QString m_projectTitlePath; + Timecode m_tc; /** See http://doc.trolltech.com/4.5/signalsandslots.html#advanced-signals-and-slots-usage */ QSignalMapper *m_signalMapper; diff --git a/src/trackview.cpp b/src/trackview.cpp index 10ba42cb..0ed52e09 100644 --- a/src/trackview.cpp +++ b/src/trackview.cpp @@ -502,9 +502,12 @@ int TrackView::slotAddProjectTrack(int ix, QDomElement xml, bool locked) QString idString = elem.attribute("producer"); QString id = idString; double speed = 1.0; + int strobe = 1; if (idString.startsWith("slowmotion")) { id = idString.section(':', 1, 1); speed = idString.section(':', 2, 2).toDouble(); + strobe = idString.section(':', 3, 3).toInt(); + if (strobe == 0) strobe = 1; } else id = id.section('_', 0, 0); DocClipBase *clip = m_doc->clipManager()->getClipById(id); if (clip == NULL) { @@ -545,13 +548,21 @@ int TrackView::slotAddProjectTrack(int ix, QDomElement xml, bool locked) 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_doc->fps(), speed, false); + ClipItem *item = new ClipItem(clip, clipinfo, m_doc->fps(), speed, strobe, false); if (idString.endsWith("_video")) item->setVideoOnly(true); else if (idString.endsWith("_audio")) item->setAudioOnly(true); m_scene->addItem(item); if (locked) item->setItemLocked(true); clip->addReference(); position += (out - in + 1); + kDebug() << "/////////\n\n\n" << "CLIP SPEED: " << speed << ", " << strobe << "\n\n\n/////////////////////"; + if (speed != 1.0 || strobe > 1) { + QDomElement speedeffect = MainWindow::videoEffects.getEffectByTag(QString(), "speed").cloneNode().toElement(); + EffectsList::setParameter(speedeffect, "speed", QString::number((int)(100 * speed + 0.5))); + EffectsList::setParameter(speedeffect, "strobe", QString::number(strobe)); + item->addEffect(speedeffect, false); + item->effectsCounter(); + } // parse clip effects QDomNodeList effects = elem.childNodes(); -- 2.39.2