summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Mardelle <jb@kdenlive.org>2016-11-30 23:05:45 (GMT)
committerJean-Baptiste Mardelle <jb@kdenlive.org>2016-11-30 23:05:57 (GMT)
commitb348355e43285c37456bfc2625a055811b790b8f (patch)
treebfc11d5ac543db11e2bb9efe394798df34a794d7
parent2087c0236360e0bf3387f0117c7a9c273ba199e8 (diff)
Fix many issues with volume keyframes
-rw-r--r--src/doc/documentvalidator.cpp2
-rw-r--r--src/effectstack/widgets/animationwidget.cpp10
-rw-r--r--src/effectstack/widgets/animationwidget.h2
-rw-r--r--src/mltcontroller/effectscontroller.cpp20
-rw-r--r--src/timeline/abstractclipitem.cpp11
-rw-r--r--src/timeline/clipitem.cpp8
-rw-r--r--src/timeline/customtrackview.cpp3
-rw-r--r--src/timeline/effectmanager.cpp3
-rw-r--r--src/timeline/keyframeview.cpp69
-rw-r--r--src/timeline/keyframeview.h2
-rw-r--r--src/timeline/track.cpp6
11 files changed, 96 insertions, 40 deletions
diff --git a/src/doc/documentvalidator.cpp b/src/doc/documentvalidator.cpp
index 595f76f..7e524d6 100644
--- a/src/doc/documentvalidator.cpp
+++ b/src/doc/documentvalidator.cpp
@@ -1497,7 +1497,7 @@ bool DocumentValidator::upgrade(double version, const double currentVersion)
}
}
EffectsList::setProperty(eff, conversionParams.at(2), parsedValues.join(";"));
- EffectsList::setProperty(eff, QStringLiteral("kdenlive:sync_in_out"), QStringLiteral("1"));
+ //EffectsList::setProperty(eff, QStringLiteral("kdenlive:sync_in_out"), QStringLiteral("1"));
eff.setAttribute(QStringLiteral("out"), out);
}
}
diff --git a/src/effectstack/widgets/animationwidget.cpp b/src/effectstack/widgets/animationwidget.cpp
index 71ab9d2..aaffa78 100644
--- a/src/effectstack/widgets/animationwidget.cpp
+++ b/src/effectstack/widgets/animationwidget.cpp
@@ -232,9 +232,9 @@ void AnimationWidget::finishSetup()
}
//static
-QString AnimationWidget::getDefaultKeyframes(const QString &defaultValue, bool linearOnly)
+QString AnimationWidget::getDefaultKeyframes(int start, const QString &defaultValue, bool linearOnly)
{
- QString keyframes = QStringLiteral("0");
+ QString keyframes = QString::number(start);
if (linearOnly) {
keyframes.append(QStringLiteral("="));
} else {
@@ -671,7 +671,7 @@ void AnimationWidget::addParameter(const QDomElement &e)
keyframes = e.attribute(QStringLiteral("value"));
}
if (keyframes.isEmpty()) {
- keyframes = getDefaultKeyframes(e.attribute(QStringLiteral("default")));
+ keyframes = getDefaultKeyframes(m_inPoint, e.attribute(QStringLiteral("default")));
if (keyframes.contains('%')) {
keyframes = EffectsController::getStringRectEval(m_monitor->profileInfo(), keyframes);
}
@@ -1012,7 +1012,7 @@ void AnimationWidget::loadPresets(QString currentText)
QMap <QString, QVariant> defaultEntry;
QStringList paramNames = m_doubleWidgets.keys();
for (int i = 0; i < paramNames.count(); i++) {
- defaultEntry.insert(paramNames.at(i), getDefaultKeyframes(m_params.at(i).attribute(QStringLiteral("default"))));
+ defaultEntry.insert(paramNames.at(i), getDefaultKeyframes(m_inPoint, m_params.at(i).attribute(QStringLiteral("default"))));
}
m_presetCombo->addItem(i18n("Default"), defaultEntry);
loadPreset(dir.absoluteFilePath(m_xml.attribute(QStringLiteral("type"))));
@@ -1304,7 +1304,7 @@ void AnimationWidget::reload(const QString &tag, const QString &data)
if (!m_rectParameter.isEmpty() && tag != m_rectParameter) {
// reset geometry keyframes
// simple anim parameter, get default value
- QString def = getDefaultKeyframes(defaultValue(m_rectParameter));
+ QString def = getDefaultKeyframes(m_inPoint, defaultValue(m_rectParameter));
// Clear current keyframes
m_animProperties.set(m_rectParameter.toUtf8().constData(), def.toUtf8().constData());
// Add default keyframes
diff --git a/src/effectstack/widgets/animationwidget.h b/src/effectstack/widgets/animationwidget.h
index 4e13503..869dae5 100644
--- a/src/effectstack/widgets/animationwidget.h
+++ b/src/effectstack/widgets/animationwidget.h
@@ -51,7 +51,7 @@ public:
void updateTimecodeFormat();
void addParameter(const QDomElement &e);
const QMap <QString, QString> getAnimation();
- static QString getDefaultKeyframes(const QString &defaultValue, bool linearOnly = false);
+ static QString getDefaultKeyframes(int start, const QString &defaultValue, bool linearOnly = false);
void setActiveKeyframe(int frame);
void finishSetup();
/** @brief Returns true if currently active param is name */
diff --git a/src/mltcontroller/effectscontroller.cpp b/src/mltcontroller/effectscontroller.cpp
index 2bc2ec9..026092f 100644
--- a/src/mltcontroller/effectscontroller.cpp
+++ b/src/mltcontroller/effectscontroller.cpp
@@ -103,8 +103,9 @@ EffectsParameterList EffectsController::getEffectArgs(const ProfileInfo &info, c
parameters.addParam(QStringLiteral("tag"), effect.attribute(QStringLiteral("tag")));
//if (effect.hasAttribute("region")) parameters.addParam("region", effect.attribute("region"));
parameters.addParam(QStringLiteral("kdenlive_ix"), effect.attribute(QStringLiteral("kdenlive_ix")));
- if (effect.hasAttribute(QStringLiteral("sync_in_out")))
+ if (effect.hasAttribute(QStringLiteral("sync_in_out"))) {
parameters.addParam(QStringLiteral("kdenlive:sync_in_out"), effect.attribute(QStringLiteral("sync_in_out")));
+ }
parameters.addParam(QStringLiteral("kdenlive_info"), effect.attribute(QStringLiteral("kdenlive_info")));
parameters.addParam(QStringLiteral("id"), effect.attribute(QStringLiteral("id")));
if (effect.hasAttribute(QStringLiteral("src"))) parameters.addParam(QStringLiteral("src"), effect.attribute(QStringLiteral("src")));
@@ -137,10 +138,11 @@ void EffectsController::adjustEffectParameters(EffectsParameterList &parameters,
for (int i = 0; i < params.count(); ++i) {
QDomElement e = params.item(i).toElement();
QString paramname = prefix + e.attribute(QStringLiteral("name"));
- if (e.attribute(QStringLiteral("type")) == QLatin1String("animated") || (e.attribute(QStringLiteral("type")) == QLatin1String("geometry") && !e.hasAttribute(QStringLiteral("fixed")))) {
+ /*if (e.attribute(QStringLiteral("type")) == QLatin1String("animated") || (e.attribute(QStringLiteral("type")) == QLatin1String("geometry") && !e.hasAttribute(QStringLiteral("fixed")))) {
// effects with geometry param need in / out synced with the clip, request it...
- //parameters.addParam(QStringLiteral("kdenlive:sync_in_out"), QStringLiteral("1"));
- }
+ parameters.addParam(QStringLiteral("kdenlive:sync_in_out"), QStringLiteral("1"));
+ qDebug()<<" ** * ADDIN EFFECT ANIM SYN TRUE";
+ }*/
if (e.attribute(QStringLiteral("type")) == QLatin1String("animated")) {
parameters.addParam(paramname, e.attribute(QStringLiteral("value")));
} else if (e.attribute(QStringLiteral("type")) == QLatin1String("simplekeyframe")) {
@@ -229,7 +231,7 @@ void EffectsController::initTrackEffect(ProfileInfo pInfo, QDomElement effect)
bool hasValue = e.hasAttribute(QStringLiteral("value"));
// Check if this effect has a variable parameter, init effects default value
if ((type == QLatin1String("animatedrect") || type == QLatin1String("geometry")) && !hasValue) {
- QString kfr = AnimationWidget::getDefaultKeyframes(e.attribute(QStringLiteral("default")), type == QLatin1String("geometry"));
+ QString kfr = AnimationWidget::getDefaultKeyframes(0, e.attribute(QStringLiteral("default")), type == QLatin1String("geometry"));
if (kfr.contains("%")) {
kfr = EffectsController::getStringRectEval(pInfo, kfr);
}
@@ -244,7 +246,7 @@ void EffectsController::initTrackEffect(ProfileInfo pInfo, QDomElement effect)
} else e.setAttribute(QStringLiteral("value"), evaluatedValue);
} else {
if (type == QLatin1String("animated") && !hasValue) {
- e.setAttribute(QStringLiteral("value"), AnimationWidget::getDefaultKeyframes(e.attribute(QStringLiteral("default"))));
+ e.setAttribute(QStringLiteral("value"), AnimationWidget::getDefaultKeyframes(0, e.attribute(QStringLiteral("default"))));
}
else if (!hasValue) {
e.setAttribute(QStringLiteral("value"), e.attribute(QStringLiteral("default")));
@@ -273,7 +275,7 @@ void EffectsController::initEffect(ItemInfo info, ProfileInfo pInfo, EffectsList
bool hasValue = e.hasAttribute(QStringLiteral("value"));
// Check if this effect has a variable parameter, init effects default value
if ((type == QLatin1String("animatedrect") || type == QLatin1String("geometry")) && !hasValue) {
- QString kfr = AnimationWidget::getDefaultKeyframes(e.attribute(QStringLiteral("default")), type == QLatin1String("geometry"));
+ QString kfr = AnimationWidget::getDefaultKeyframes(info.cropStart.frames(fps), e.attribute(QStringLiteral("default")), type == QLatin1String("geometry"));
if (kfr.contains("%")) {
kfr = EffectsController::getStringRectEval(pInfo, kfr);
}
@@ -288,7 +290,7 @@ void EffectsController::initEffect(ItemInfo info, ProfileInfo pInfo, EffectsList
} else e.setAttribute(QStringLiteral("value"), evaluatedValue);
} else {
if (type == QLatin1String("animated") && !hasValue) {
- e.setAttribute(QStringLiteral("value"), AnimationWidget::getDefaultKeyframes(e.attribute(QStringLiteral("default"))));
+ e.setAttribute(QStringLiteral("value"), AnimationWidget::getDefaultKeyframes(info.cropStart.frames(fps), e.attribute(QStringLiteral("default"))));
}
else if (!hasValue) {
e.setAttribute(QStringLiteral("value"), e.attribute(QStringLiteral("default")));
@@ -312,7 +314,7 @@ void EffectsController::initEffect(ItemInfo info, ProfileInfo pInfo, EffectsList
}
}
- if (type.startsWith(QStringLiteral("animated")) || (type == QLatin1String("geometry") && !e.hasAttribute(QStringLiteral("fixed")))) {
+ if (EffectsList::parameter(effect, QStringLiteral("kdenlive:sync_in_out")) == QLatin1String("1") || (type == QLatin1String("geometry") && !e.hasAttribute(QStringLiteral("fixed")))) {
// Effects with a geometry parameter need to sync in / out with parent clip
effect.setAttribute(QStringLiteral("in"), QString::number((int) info.cropStart.frames(fps)));
effect.setAttribute(QStringLiteral("out"), QString::number((int) (info.cropStart + info.cropDuration).frames(fps) - 1));
diff --git a/src/timeline/abstractclipitem.cpp b/src/timeline/abstractclipitem.cpp
index 09c318e..4f4a876 100644
--- a/src/timeline/abstractclipitem.cpp
+++ b/src/timeline/abstractclipitem.cpp
@@ -200,7 +200,6 @@ void AbstractClipItem::resizeStart(int posx, bool hasSizeLimit, bool /*emitChang
}
m_info.startPos += durationDiff;
m_keyframeView.setOffset(durationDiff.frames(m_fps));
-
// set to true if crop from start is negative (possible for color clips, images as they have no size limit)
bool negCropStart = false;
if (type() == AVWidget) {
@@ -616,7 +615,7 @@ QString AbstractClipItem::resizeAnimations(QDomElement effect, int previousDurat
effect.setAttribute(QStringLiteral("out"), QString::number(start + duration));
}
else {
- keyframes = KeyframeView::cutAnimation(animation, cropstart, duration, previousDuration, false);
+ keyframes = KeyframeView::addBorderKeyframes(animation, cropstart, duration);
}
// TODO: in case of multiple animated params, use _intimeline to detect active one
e.setAttribute(QStringLiteral("value"), keyframes);
@@ -628,10 +627,12 @@ QString AbstractClipItem::resizeAnimations(QDomElement effect, int previousDurat
bool AbstractClipItem::switchKeyframes(QDomElement param, int in, int oldin, int out, int oldout)
{
QString animation = param.attribute(QStringLiteral("value"));
- if (in != oldin)
+ if (in != oldin) {
animation = KeyframeView::switchAnimation(animation, in, oldin, out, oldout, param.attribute(QStringLiteral("type")) == QLatin1String("animatedrect"));
- if (out != oldout)
- animation = KeyframeView::switchAnimation(animation, out - 1, oldout - 1, out, oldout, param.attribute(QStringLiteral("type")) == QLatin1String("animatedrect"));
+ }
+ if (out != oldout) {
+ animation = KeyframeView::switchAnimation(animation, out, oldout, out, oldout, param.attribute(QStringLiteral("type")) == QLatin1String("animatedrect"));
+ }
if (animation != param.attribute(QStringLiteral("value"))) {
param.setAttribute(QStringLiteral("value"), animation);
return true;
diff --git a/src/timeline/clipitem.cpp b/src/timeline/clipitem.cpp
index 579a7d8..687b978 100644
--- a/src/timeline/clipitem.cpp
+++ b/src/timeline/clipitem.cpp
@@ -1453,7 +1453,7 @@ EffectsParameterList ClipItem::addEffect(ProfileInfo info, QDomElement effect, b
else if (e.attribute(QStringLiteral("type")) == QLatin1String("animated")) {
parameters.addParam(e.attribute(QStringLiteral("name")), e.attribute(QStringLiteral("value")));
// Effects with a animated parameter need to sync in / out with parent clip
- if (!e.hasAttribute(QStringLiteral("sync_in_out")) || e.attribute(QStringLiteral("sync_in_out")) == QLatin1String("1")) {
+ if (e.attribute(QStringLiteral("sync_in_out")) == QLatin1String("1")) {
needInOutSync = true;
}
} else if (e.attribute(QStringLiteral("type")) == QLatin1String("simplekeyframe")) {
@@ -1808,10 +1808,9 @@ QMap<int, QDomElement> ClipItem::adjustEffectsToDuration(const ItemInfo &oldInfo
if (effect.attribute(QStringLiteral("sync_in_out")) == QLatin1String("1")) {
effect.setAttribute(QStringLiteral("in"), cropStart().frames(m_fps));
effect.setAttribute(QStringLiteral("out"), (cropStart() + cropDuration()).frames(m_fps) - 1);
- } else {
- // Check if we have keyframes at in/out points
- updateAnimatedKeyframes(i, param, oldInfo);
}
+ // Check if we have keyframes at in/out points
+ updateAnimatedKeyframes(i, param, oldInfo);
effects[i] = effect.cloneNode().toElement();
} else if (type == QLatin1String("roto-spline")) {
if (!effects.contains(i))
@@ -1856,7 +1855,6 @@ bool ClipItem::updateNormalKeyframes(QDomElement parameter, const ItemInfo &oldI
keyframes[keyframepos] = locale.toDouble(keyframe.section('=', 1, 1));
}
-
QMap<int, double>::iterator i = keyframes.end();
int lastPos = -1;
double lastValue = 0;
diff --git a/src/timeline/customtrackview.cpp b/src/timeline/customtrackview.cpp
index 6700af7..71736aa 100644
--- a/src/timeline/customtrackview.cpp
+++ b/src/timeline/customtrackview.cpp
@@ -1380,7 +1380,7 @@ void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event)
ClipItem * item = static_cast <ClipItem *>(m_dragItem);
QDomElement oldEffect = item->selectedEffect().cloneNode().toElement();
if (single == 1) {
- item->insertKeyframe(m_document->getProfileInfo(), item->getEffectAtIndex(item->selectedEffectIndex()), (item->cropDuration()).frames(m_document->fps()) - 1, -1, true);
+ item->insertKeyframe(m_document->getProfileInfo(), item->getEffectAtIndex(item->selectedEffectIndex()), (item->cropStart() + item->cropDuration()).frames(m_document->fps()) - 1, -1, true);
}
//QString previous = item->keyframes(item->selectedEffectIndex());
item->insertKeyframe(m_document->getProfileInfo(), item->getEffectAtIndex(item->selectedEffectIndex()), keyFramePos.frames(m_document->fps()), val);
@@ -1906,7 +1906,6 @@ bool CustomTrackView::itemCollision(AbstractClipItem *item, const ItemInfo &newP
void CustomTrackView::slotRefreshEffects(ClipItem *clip)
{
- // Does not seem used anywhere...
int track = clip->track();
GenTime pos = clip->startPos();
if (!m_timeline->track(track)->removeEffect(pos.seconds(), -1, false)) {
diff --git a/src/timeline/effectmanager.cpp b/src/timeline/effectmanager.cpp
index 75d38d2..bcfb84b 100644
--- a/src/timeline/effectmanager.cpp
+++ b/src/timeline/effectmanager.cpp
@@ -316,8 +316,7 @@ bool EffectManager::editEffect(EffectsParameterList params, int duration, bool r
if (params.paramValue(QStringLiteral("kdenlive:sync_in_out")) == QLatin1String("1")) {
// This effect must sync in / out with parent clip
//params.removeParam(QStringLiteral("sync_in_out"));
- Mlt::Producer prod(m_producer);
- filter->set_in_and_out(prod.get_in(), prod.get_out());
+ filter->set_in_and_out(m_producer.get_int("in"), m_producer.get_int("out"));
} else {
// Reset in/out properties
filter->set("in", (char*)NULL);
diff --git a/src/timeline/keyframeview.cpp b/src/timeline/keyframeview.cpp
index 93b5028..30586c7 100644
--- a/src/timeline/keyframeview.cpp
+++ b/src/timeline/keyframeview.cpp
@@ -23,7 +23,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QPainter>
#include <QAction>
#include <QApplication>
-
#include "klocalizedstring.h"
#include "keyframeview.h"
@@ -142,14 +141,28 @@ void KeyframeView::drawKeyFrames(QRectF br, int length, bool active, QPainter *p
Mlt::Animation drawAnim = m_keyProperties.get_animation(paramName.toUtf8().constData());
if (!drawAnim.is_valid()) continue;
QPainterPath path;
- int frame = drawAnim.key_get_frame(0);
+ // Find first key before our clip start, get frame for rect left first
+ int firstKF = qMax(0, drawAnim.previous_key(-m_offset));
+ int lastKF = drawAnim.next_key(duration - m_offset);
+ if (lastKF < duration - m_offset) {
+ lastKF = duration - m_offset;
+ }
+ int frame = firstKF;
double value = m_keyProperties.anim_get_double(paramName.toUtf8().constData(), frame, duration - m_offset);
QPointF start = keyframePoint(br, frame + m_offset, value, info.factor, info.min, info.max);
path.moveTo(br.x(), br.bottom());
path.lineTo(br.x(), start.y());
path.lineTo(start);
+ int currentFrame;
painter->setPen(paramName == m_inTimeline ? QColor(Qt::white) : Qt::NoPen);
for(int i = 0; i < drawAnim.key_count(); ++i) {
+ currentFrame = drawAnim.key_get_frame(i);
+ if (currentFrame < firstKF) {
+ continue;
+ }
+ if (currentFrame > lastKF) {
+ break;
+ }
if (active && paramName == m_inTimeline) {
painter->setBrush((drawAnim.key_get_frame(i) == activeKeyframe) ? QColor(Qt::red) : QColor(Qt::blue));
painter->drawEllipse(QRectF(transformation.map(start) - h/2, transformation.map(start) + h / 2));
@@ -170,10 +183,10 @@ void KeyframeView::drawKeyFrames(QRectF br, int length, bool active, QPainter *p
case mlt_keyframe_smooth:
frame = drawAnim.key_get_frame(qMax(i - 1, 0));
value = m_keyProperties.anim_get_double(paramName.toUtf8().constData(), frame, duration - m_offset);
- QPointF pre = keyframePoint(br, frame, value, info.factor, info.min, info.max);
+ QPointF pre = keyframePoint(br, frame + m_offset, value, info.factor, info.min, info.max);
frame = drawAnim.key_get_frame(qMin(i + 2, drawAnim.key_count() - 1));
value = m_keyProperties.anim_get_double(paramName.toUtf8().constData(), frame, duration - m_offset);
- QPointF post = keyframePoint(br, frame, value, info.factor, info.min, info.max);
+ QPointF post = keyframePoint(br, frame + m_offset, value, info.factor, info.min, info.max);
QPointF c1 = (end - pre) / 6.0; // + start
QPointF c2 = (start - post) / 6.0; // + end
double mid = (end.x() - start.x()) / 2;
@@ -832,7 +845,7 @@ bool KeyframeView::loadKeyframes(const QLocale locale, QDomElement effect, int c
}
attachToEnd = -2;
m_useOffset = effect.attribute(QStringLiteral("kdenlive:sync_in_out")) != QLatin1String("1");
- m_offset = effect.attribute("in").toInt() - cropStart;
+ m_offset = effect.attribute(QStringLiteral("in")).toInt() - cropStart;
QDomNodeList params = effect.elementsByTagName(QStringLiteral("parameter"));
for (int i = 0; i < params.count(); ++i) {
QDomElement e = params.item(i).toElement();
@@ -891,9 +904,23 @@ bool KeyframeView::loadKeyframes(const QLocale locale, QDomElement effect, int c
void KeyframeView::setOffset(int frames)
{
- if (m_useOffset) {
+ if (!m_keyAnim.is_valid())
+ return;
+ if (m_keyAnim.is_key(-m_offset)) {
+ mlt_keyframe_type type = m_keyAnim.keyframe_type(-m_offset);
+ double value = m_keyProperties.anim_get_double(m_inTimeline.toUtf8().constData(), -m_offset, duration - m_offset);
+ m_keyAnim.remove(-m_offset);
+ if (activeKeyframe == -m_offset) {
+ activeKeyframe -= frames;
+ }
+ m_offset -= frames;
+ m_keyProperties.anim_set(m_inTimeline.toUtf8().constData(), value, - m_offset, duration - m_offset, type);
+ //addKeyframe(-m_offset, value, type);
+ } else {
m_offset -= frames;
}
+ //double value = m_keyProperties.anim_get_double(m_inTimeline.toUtf8().constData(), 0, duration - m_offset);
+ //}
}
// static
@@ -962,6 +989,34 @@ QString KeyframeView::cutAnimation(const QString &animation, int start, int dura
}
//static
+const QString KeyframeView::addBorderKeyframes(const QString &animation, int start, int duration)
+{
+ bool modified = false;
+ Mlt::Properties props;
+ props.set("keyframes", animation.toUtf8().constData());
+ props.anim_get_double("keyframes", 0, start+duration);
+ Mlt::Animation anim = props.get_animation("keyframes");
+ if (!anim.is_key(start)) {
+ double value = props.anim_get_double("keyframes", start, start+duration);
+ int previous = anim.previous_key(start);
+ mlt_keyframe_type type = anim.keyframe_type(previous);
+ props.anim_set("keyframes", value, start, start+duration, type);
+ modified = true;
+ }
+ if (!anim.is_key(start+duration)) {
+ double value = props.anim_get_double("keyframes", start+duration, start+duration);
+ int previous = anim.previous_key(start+duration);
+ mlt_keyframe_type type = anim.keyframe_type(previous);
+ props.anim_set("keyframes", value, start+duration, start+duration, type);
+ modified = true;
+ }
+ if (modified) {
+ return anim.serialize_cut();
+ }
+ return animation;
+}
+
+//static
QString KeyframeView::switchAnimation(QString animation, int newPos, int oldPos, int newDuration, int oldDuration, bool isRect)
{
Mlt::Properties props;
@@ -971,7 +1026,7 @@ QString KeyframeView::switchAnimation(QString animation, int newPos, int oldPos,
if (anim.is_key(oldPos)) {
// insert new keyframe at start
if (isRect) {
- mlt_rect rect = props.anim_get_rect("keyframes", oldPos);
+ mlt_rect rect = props.anim_get_rect("keyframes", oldPos, oldDuration);
props.anim_set("keyframes", rect, newPos, newDuration, anim.keyframe_type(oldPos));
anim.remove(oldPos);
} else {
diff --git a/src/timeline/keyframeview.h b/src/timeline/keyframeview.h
index 2eef776..342b50f 100644
--- a/src/timeline/keyframeview.h
+++ b/src/timeline/keyframeview.h
@@ -97,6 +97,8 @@ public:
static QString switchAnimation(QString animation, int newPos, int oldPos, int newDuration, int oldDuration, bool isRect);
/** @brief when loading an animation from a serialized string, check where is the first negative keyframe) */
static int checkNegatives(const QString &data, int maxDuration);
+ /** @brief Add keyframes at start / end points if not existing */
+ static const QString addBorderKeyframes(const QString &animation, int start, int duration);
/** @brief returns true if currently edited parameter name is name */
bool activeParam(const QString &name) const;
/** @brief Sets a temporary offset for drawing keyframes when resizing clip start */
diff --git a/src/timeline/track.cpp b/src/timeline/track.cpp
index 32aa837..43ce2ad 100644
--- a/src/timeline/track.cpp
+++ b/src/timeline/track.cpp
@@ -905,9 +905,9 @@ bool Track::editEffect(double start, EffectsParameterList params, bool replace)
if (!clip) {
return false;
}
- Mlt::Service clipService(clip->get_service());
- EffectManager effect(clipService);
- return effect.editEffect(params, duration, replace);
+ EffectManager effect(*clip.data());
+ bool result = effect.editEffect(params, duration, replace);
+ return result;
}
bool Track::editTrackEffect(EffectsParameterList params, bool replace)