]> git.sesse.net Git - kdenlive/blobdiff - src/clipitem.cpp
Fix crash in DVD Wizard
[kdenlive] / src / clipitem.cpp
index d16f1ad8b81fd730f22f05e40505050cc16f5013..7abb6815b735cc0871cfd0d00313a5937f1bfd39 100644 (file)
@@ -59,17 +59,22 @@ ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, i
     setZValue(2);
     setRect(0, 0, (info.endPos - info.startPos).frames(fps) - 0.02, (double)(KdenliveSettings::trackheight() - 2));
     setPos(info.startPos.frames(fps), (double)(info.track * KdenliveSettings::trackheight()) + 1);
+
+    // set speed independant info
+    m_speedIndependantInfo = m_info;
+    m_speedIndependantInfo.cropStart = GenTime((int)(m_info.cropStart.frames(m_fps) * m_speed), m_fps);
+    m_speedIndependantInfo.cropDuration = GenTime((int)(m_info.cropDuration.frames(m_fps) * m_speed), m_fps);
+
     m_videoPix = KIcon("kdenlive-show-video").pixmap(QSize(16, 16));
     m_audioPix = KIcon("kdenlive-show-audio").pixmap(QSize(16, 16));
 
     if (m_speed == 1.0) m_clipName = clip->name();
     else {
         m_clipName = clip->name() + " - " + QString::number(m_speed * 100, 'f', 0) + '%';
-        m_cropDuration = m_cropDuration * m_speed;
     }
     m_producer = clip->getId();
     m_clipType = clip->clipType();
-    m_cropStart = info.cropStart;
+    //m_cropStart = info.cropStart;
     m_maxDuration = clip->maxDuration();
     setAcceptDrops(true);
     m_audioThumbReady = clip->audioThumbCreated();
@@ -128,8 +133,8 @@ ClipItem *ClipItem::clone(ItemInfo info) const
     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);
-        if (info.cropStart + (info.endPos - info.startPos) == m_cropStart + m_cropDuration) duplicate->slotSetEndThumb(m_endPix);
+        if (info.cropStart == m_info.cropStart) duplicate->slotSetStartThumb(m_startPix);
+        if (info.cropStart + (info.endPos - info.startPos) == m_info.cropStart + (m_info.endPos - m_info.startPos)) duplicate->slotSetEndThumb(m_endPix);
     }
     //kDebug() << "// CLoning clip: " << (info.cropStart + (info.endPos - info.startPos)).frames(m_fps) << ", CURRENT end: " << (cropStart() + duration()).frames(m_fps);
     duplicate->setEffectList(m_effectList);
@@ -156,13 +161,18 @@ int ClipItem::selectedEffectIndex() const
     return m_selectedEffect;
 }
 
-void ClipItem::initEffect(QDomElement effect)
+void ClipItem::initEffect(QDomElement effect, int diff)
 {
     // the kdenlive_ix int is used to identify an effect in mlt's playlist, should
     // not be changed
     if (effect.attribute("kdenlive_ix").toInt() == 0)
         effect.setAttribute("kdenlive_ix", QString::number(effectsCounter()));
-    // init keyframes if required
+
+    if (effect.attribute("id") == "freeze" && diff > 0) {
+        EffectsList::setParameter(effect, "frame", QString::number(diff));
+    }
+
+    // Init parameter value & keyframes if required
     QDomNodeList params = effect.elementsByTagName("parameter");
     for (int i = 0; i < params.count(); i++) {
         QDomElement e = params.item(i).toElement();
@@ -256,8 +266,8 @@ bool ClipItem::checkKeyFrames()
             bool modified = false;
             int lastPos = -1;
             double lastValue = -1;
-            int start = m_cropStart.frames(m_fps);
-            int end = (m_cropStart + m_cropDuration).frames(m_fps);
+            int start = cropStart().frames(m_fps);
+            int end = (cropStart() + cropDuration()).frames(m_fps);
             foreach(const QString &str, keyframes) {
                 int pos = str.section(':', 0, 0).toInt();
                 double val = str.section(':', 1, 1).toDouble();
@@ -431,14 +441,14 @@ void ClipItem::refreshClip(bool checkDuration)
     if (checkDuration && (m_maxDuration != m_clip->maxDuration())) {
         m_maxDuration = m_clip->maxDuration();
         if (m_clipType != IMAGE && m_clipType != TEXT && m_clipType != COLOR) {
-            if (m_maxDuration != GenTime() && m_cropStart + m_cropDuration > m_maxDuration) {
+            if (m_maxDuration != GenTime() && m_info.cropStart + m_info.cropDuration > m_maxDuration) {
                 // Clip duration changed, make sure to stay in correct range
-                if (m_cropStart > m_maxDuration) {
-                    m_cropStart = GenTime();
-                    m_cropDuration = qMin(m_cropDuration, m_maxDuration);
+                if (m_info.cropStart > m_maxDuration) {
+                    m_info.cropStart = GenTime();
+                    m_info.cropDuration = qMin(m_info.cropDuration, m_maxDuration);
                     updateRectGeometry();
                 } else {
-                    m_cropDuration = m_maxDuration;
+                    m_info.cropDuration = m_maxDuration;
                     updateRectGeometry();
                 }
             }
@@ -469,7 +479,7 @@ void ClipItem::slotFetchThumbs()
     if (m_endPix.isNull() && m_startPix.isNull()) {
         m_startThumbRequested = true;
         m_endThumbRequested = true;
-        emit getThumb((int)cropStart().frames(m_fps), (int)(cropStart() + cropDuration()).frames(m_fps) - 1);
+        emit getThumb((int)m_speedIndependantInfo.cropStart.frames(m_fps), (int)(m_speedIndependantInfo.cropStart + m_speedIndependantInfo.cropDuration).frames(m_fps) - 1);
     } else {
         if (m_endPix.isNull()) {
             slotGetEndThumb();
@@ -496,7 +506,7 @@ void ClipItem::slotFetchThumbs()
 void ClipItem::slotGetStartThumb()
 {
     m_startThumbRequested = true;
-    emit getThumb((int)cropStart().frames(m_fps), -1);
+    emit getThumb((int)m_speedIndependantInfo.cropStart.frames(m_fps), -1);
     //videoThumbProducer.setThumbFrames(m_clip->producer(), (int)m_cropStart.frames(m_fps),  - 1);
     //videoThumbProducer.start(QThread::LowestPriority);
 }
@@ -504,7 +514,7 @@ void ClipItem::slotGetStartThumb()
 void ClipItem::slotGetEndThumb()
 {
     m_endThumbRequested = true;
-    emit getThumb(-1, (int)(cropStart() + cropDuration()).frames(m_fps) - 1);
+    emit getThumb(-1, (int)(m_speedIndependantInfo.cropStart + m_speedIndependantInfo.cropDuration).frames(m_fps) - 1);
     //videoThumbProducer.setThumbFrames(m_clip->producer(), -1, (int)(m_cropStart + m_cropDuration).frames(m_fps) - 1);
     //videoThumbProducer.start(QThread::LowestPriority);
 }
@@ -537,14 +547,17 @@ void ClipItem::slotThumbReady(int frame, QPixmap pix)
     if (scene() == NULL) return;
     QRectF r = boundingRect();
     double width = pix.width() / projectScene()->scale().x();
-    if (m_startThumbRequested && frame == cropStart().frames(m_fps)) {
+    if (m_startThumbRequested && frame == m_speedIndependantInfo.cropStart.frames(m_fps)) {
         m_startPix = pix;
         m_startThumbRequested = false;
         update(r.left(), r.top(), width, pix.height());
-    } else if (m_endThumbRequested && frame == (cropStart() + cropDuration()).frames(m_fps) - 1) {
+        if (m_clipType == IMAGE || m_clipType == TEXT) {
+            update(r.right() - width, r.top(), width, pix.height());
+        }
+    } else if (m_endThumbRequested && frame == (m_speedIndependantInfo.cropStart + m_speedIndependantInfo.cropDuration).frames(m_fps) - 1) {
         m_endPix = pix;
         m_endThumbRequested = false;
-        update(r.right() - width, r.y(), width, pix.height());
+        update(r.right() - width, r.top(), width, pix.height());
     }
 }
 
@@ -630,7 +643,7 @@ void ClipItem::flashClip()
     //m_timeLine->start();
 }
 
-void ClipItem::animate(qreal value)
+void ClipItem::animate(qreal /*value*/)
 {
     QRectF r = boundingRect();
     r.setHeight(20);
@@ -700,7 +713,7 @@ void ClipItem::paint(QPainter *painter,
         int channels = baseClip()->getProperty("channels").toInt();
         if (scale != m_framePixelWidth)
             m_audioThumbCachePic.clear();
-        double cropLeft = m_cropStart.frames(m_fps);
+        double cropLeft = m_info.cropStart.frames(m_fps);
         const int clipStart = mappedRect.x();
         const int mappedStartPixel =  painter->matrix().map(QPointF(startpixel + cropLeft, 0)).x() - clipStart;
         const int mappedEndPixel =  painter->matrix().map(QPointF(endpixel + cropLeft, 0)).x() - clipStart;
@@ -770,15 +783,16 @@ void ClipItem::paint(QPainter *painter,
     QPen pen = painter->pen();
     pen.setColor(QColor(255, 255, 255, 200));
     pen.setStyle(Qt::DotLine);
-    painter->setPen(pen);
+
     for (; it != markers.end(); ++it) {
-        pos = (*it).time() / m_speed - cropStart();
+        pos = GenTime((int)((*it).time().frames(m_fps) / m_speed + 0.5), m_fps) - cropStart();
         if (pos > GenTime()) {
             if (pos > cropDuration()) break;
             QLineF l(rect().x() + pos.frames(m_fps), rect().y(), rect().x() + pos.frames(m_fps), rect().bottom());
             QLineF l2 = painter->matrix().map(l);
             //framepos = scale * pos.frames(m_fps);
             //QLineF l(framepos, 5, framepos, itemHeight - 5);
+            painter->setPen(pen);
             painter->drawLine(l2);
             if (KdenliveSettings::showmarkers()) {
                 framepos = rect().x() + pos.frames(m_fps);
@@ -891,7 +905,8 @@ QList <GenTime> ClipItem::snapMarkers() const
     GenTime pos;
 
     for (int i = 0; i < markers.size(); i++) {
-        pos = markers.at(i) / m_speed - cropStart();
+
+        pos = GenTime((int)(markers.at(i).frames(m_fps) / m_speed + 0.5), m_fps) - cropStart();
         if (pos > GenTime()) {
             if (pos > cropDuration()) break;
             else snaps.append(pos + startPos());
@@ -907,7 +922,7 @@ QList <CommentedTime> ClipItem::commentedSnapMarkers() const
     GenTime pos;
 
     for (int i = 0; i < markers.size(); i++) {
-        pos = markers.at(i).time() / m_speed - cropStart();
+        pos = GenTime((int)(markers.at(i).time().frames(m_fps) / m_speed + 0.5), m_fps) - cropStart();
         if (pos > GenTime()) {
             if (pos > cropDuration()) break;
             else snaps.append(CommentedTime(pos + startPos(), markers.at(i).comment()));
@@ -1017,7 +1032,7 @@ void ClipItem::setFadeIn(int pos)
     if (pos == m_startFade) return;
     int oldIn = m_startFade;
     if (pos < 0) pos = 0;
-    if (pos > m_cropDuration.frames(m_fps)) pos = (int)(m_cropDuration.frames(m_fps));
+    if (pos > cropDuration().frames(m_fps)) pos = (int)(cropDuration().frames(m_fps));
     m_startFade = pos;
     QRectF rect = boundingRect();
     update(rect.x(), rect.y(), qMax(oldIn, pos), rect.height());
@@ -1028,7 +1043,7 @@ void ClipItem::setFadeOut(int pos)
     if (pos == m_endFade) return;
     int oldOut = m_endFade;
     if (pos < 0) pos = 0;
-    if (pos > m_cropDuration.frames(m_fps)) pos = (int)(m_cropDuration.frames(m_fps));
+    if (pos > cropDuration().frames(m_fps)) pos = (int)(cropDuration().frames(m_fps));
     m_endFade = pos;
     QRectF rect = boundingRect();
     update(rect.x() + rect.width() - qMax(oldOut, pos), rect.y(), qMax(oldOut, pos), rect.height());
@@ -1065,13 +1080,19 @@ void ClipItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
 }
 */
 
-void ClipItem::resizeStart(int posx, double /*speed*/)
+void ClipItem::resizeStart(int posx)
 {
     const int min = (startPos() - cropStart()).frames(m_fps);
     if (posx < min) posx = min;
     if (posx == startPos().frames(m_fps)) return;
     const int previous = cropStart().frames(m_fps);
-    AbstractClipItem::resizeStart(posx, m_speed);
+    AbstractClipItem::resizeStart(posx);
+
+    // set speed independant info
+    m_speedIndependantInfo = m_info;
+    m_speedIndependantInfo.cropStart = GenTime((int)(m_info.cropStart.frames(m_fps) * m_speed), m_fps);
+    m_speedIndependantInfo.cropDuration = GenTime((int)(m_info.cropDuration.frames(m_fps) * m_speed), m_fps);
+
     if ((int) cropStart().frames(m_fps) != previous) {
         if (m_hasThumbs && KdenliveSettings::videothumbnails()) {
             /*connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QPixmap)), this, SLOT(slotThumbReady(int, QPixmap)));*/
@@ -1080,16 +1101,21 @@ void ClipItem::resizeStart(int posx, double /*speed*/)
     }
 }
 
-void ClipItem::resizeEnd(int posx, double /*speed*/)
+void ClipItem::resizeEnd(int posx)
 {
     const int max = (startPos() - cropStart() + maxDuration()).frames(m_fps);
     if (posx > max && maxDuration() != GenTime()) posx = max;
     if (posx == endPos().frames(m_fps)) return;
     //kDebug() << "// NEW POS: " << posx << ", OLD END: " << endPos().frames(m_fps);
-    const int previous = (int)(cropStart() + cropDuration()).frames(m_fps) - 1;
-    AbstractClipItem::resizeEnd(posx, m_speed);
-    const int current = (int)(cropStart() + cropDuration()).frames(m_fps) - 1;
-    if (current != previous) {
+    const int previous = cropDuration().frames(m_fps);
+    AbstractClipItem::resizeEnd(posx);
+
+    // set speed independant info
+    m_speedIndependantInfo = m_info;
+    m_speedIndependantInfo.cropStart = GenTime((int)(m_info.cropStart.frames(m_fps) * m_speed), m_fps);
+    m_speedIndependantInfo.cropDuration = GenTime((int)(m_info.cropDuration.frames(m_fps) * m_speed), m_fps);
+
+    if ((int) cropDuration().frames(m_fps) != previous) {
         if (m_hasThumbs && KdenliveSettings::videothumbnails()) {
             /*connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QPixmap)), this, SLOT(slotThumbReady(int, QPixmap)));*/
             m_endThumbTimer.start(150);
@@ -1190,20 +1216,20 @@ QVariant ClipItem::itemChange(GraphicsItemChange change, const QVariant &value)
                         subitems.removeAll(this);
                         for (int j = 0; j < subitems.count(); j++) {
                             if (subitems.at(j)->type() == type()) {
-                                m_startPos = GenTime((int) pos().x(), m_fps);
+                                m_info.startPos = GenTime((int) pos().x(), m_fps);
                                 return pos();
                             }
                         }
                     }
 
-                    m_track = newTrack;
-                    m_startPos = GenTime((int) newPos.x(), m_fps);
+                    m_info.track = newTrack;
+                    m_info.startPos = GenTime((int) newPos.x(), m_fps);
                     return newPos;
                 }
             }
         }
-        m_track = newTrack;
-        m_startPos = GenTime((int) newPos.x(), m_fps);
+        m_info.track = newTrack;
+        m_info.startPos = GenTime((int) newPos.x(), m_fps);
         //kDebug()<<"// ITEM NEW POS: "<<newPos.x()<<", mapped: "<<mapToScene(newPos.x(), 0).x();
         return newPos;
     }
@@ -1248,7 +1274,7 @@ QDomElement ClipItem::getEffectAt(int ix) const
 
 void ClipItem::setEffectAt(int ix, QDomElement effect)
 {
-    if (ix < 0 || ix > (m_effectList.count() - 1)) {
+    if (ix < 0 || ix > (m_effectList.count() - 1) || effect.isNull()) {
         kDebug() << "Invalid effect index: " << ix;
         return;
     }
@@ -1266,7 +1292,7 @@ void ClipItem::setEffectAt(int ix, QDomElement effect)
     }
 }
 
-EffectsParameterList ClipItem::addEffect(const QDomElement effect, bool animate)
+EffectsParameterList ClipItem::addEffect(const QDomElement effect, bool /*animate*/)
 {
     bool needRepaint = false;
     int ix;
@@ -1485,27 +1511,30 @@ void ClipItem::setSpeed(const double speed, const int strobe)
     m_strobe = strobe;
     if (m_speed == 1.0) m_clipName = baseClip()->name();
     else m_clipName = baseClip()->name() + " - " + QString::number(speed * 100, 'f', 0) + '%';
+    m_info.cropStart = GenTime((int)(m_speedIndependantInfo.cropStart.frames(m_fps) / m_speed + 0.5), m_fps);
+    m_info.cropDuration = GenTime((int)(m_speedIndependantInfo.cropDuration.frames(m_fps) / m_speed + 0.5), m_fps);
     //update();
 }
 
 GenTime ClipItem::maxDuration() const
 {
-    return m_maxDuration / m_speed;
+    return GenTime((int)(m_maxDuration.frames(m_fps) / m_speed + 0.5), m_fps);
 }
 
-GenTime ClipItem::cropStart() const
+GenTime ClipItem::speedIndependantCropStart() const
 {
-    return m_cropStart / m_speed;
+    return m_speedIndependantInfo.cropStart;
 }
 
-GenTime ClipItem::cropDuration() const
+GenTime ClipItem::speedIndependantCropDuration() const
 {
-    return m_cropDuration / m_speed;
+    return m_speedIndependantInfo.cropDuration;
 }
 
-GenTime ClipItem::endPos() const
+
+const ItemInfo ClipItem::speedIndependantInfo() const
 {
-    return m_startPos + cropDuration();
+    return m_speedIndependantInfo;
 }
 
 //virtual
@@ -1518,7 +1547,7 @@ void ClipItem::dropEvent(QGraphicsSceneDragDropEvent * event)
     if (scene() && !scene()->views().isEmpty()) {
         event->accept();
         CustomTrackView *view = (CustomTrackView *) scene()->views()[0];
-        if (view) view->slotAddEffect(e, m_startPos, track());
+        if (view) view->slotAddEffect(e, m_info.startPos, track());
     }
 }