m_doc->commandStack()->push(command);
}
-void ClipManager::slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool crop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, QString group, const QString &groupId)
+void ClipManager::slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration,
+ const bool loop, const bool crop, const bool fade,
+ const QString &luma_duration, const QString &luma_file, const int softness,
+ const QString &animation, QString group, const QString &groupId)
{
QDomDocument doc;
QDomElement prod = doc.createElement("producer");
prod.setAttribute("fade", fade);
prod.setAttribute("softness", QString::number(softness));
prod.setAttribute("luma_file", luma_file);
+ prod.setAttribute("animation", animation);
if (!group.isEmpty()) {
prod.setAttribute("groupname", group);
prod.setAttribute("groupid", groupId);
void slotAddTextTemplateClip(QString titleName, const KUrl path, const QString group, const QString &groupId);
void slotAddXmlClipFile(const QString name, const QDomElement xml, 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 crop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, const QString group, const QString &groupId);
+ void slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration,
+ const bool loop, const bool crop,const bool fade,
+ const QString &luma_duration, const QString &luma_file, const int softness,
+ const QString &animation, const QString group, const QString &groupId);
DocClipBase *getClipById(QString clipId);
const QList <DocClipBase *> getClipByResource(QString resource);
void slotDeleteClips(QStringList ids);
m_view.image_type->addItem("TGA (*.tga)", "tga");
m_view.image_type->addItem("TIFF (*.tiff)", "tiff");
m_view.image_type->addItem("Open EXR (*.exr)", "exr");
+ m_view.animation->addItem(i18n("None"), QString());
+ m_view.animation->addItem(i18n("Pan"), "Pan");
+ m_view.animation->addItem(i18n("Pan, low-pass"), "Pan, low-pass");
+ m_view.animation->addItem(i18n("Pan and zoom"), "Pan and zoom");
+ m_view.animation->addItem(i18n("Pan and zoom, low-pass"), "Pan and zoom, low-pass");
+ m_view.animation->addItem(i18n("Zoom"), "Zoom");
+ m_view.animation->addItem(i18n("Zoom, low-pass"), "Zoom, low-pass");
m_view.slide_loop->setChecked(props.value("loop").toInt());
m_view.slide_crop->setChecked(props.value("crop").toInt());
m_view.slide_fade->setChecked(props.value("fade").toInt());
m_view.luma_softness->setValue(props.value("softness").toInt());
+ if (!props.value("animation").isEmpty())
+ m_view.animation->setCurrentItem(props.value("animation"));
+ else
+ m_view.animation->setCurrentIndex(0);
QString path = props.value("resource");
QString ext = path.section('.', -1);
for (int i = 0; i < m_view.image_type->count(); i++) {
}
}
+ QString animation = m_view.animation->itemData(m_view.animation->currentIndex()).toString();
+ if (animation != m_old_props.value("animation")) {
+ if (animation.isEmpty()) {
+ props["animation"].clear();
+ } else {
+ props["animation"] = animation;
+ }
+ m_clipNeedsRefresh = true;
+ }
}
return props;
}
#include "kdenlivesettings.h"
#include "kthumb.h"
#include "clipmanager.h"
+#include "slideshowclip.h"
#include <KIO/NetAccess>
#include <KDebug>
if (!getProperty("out").isEmpty()) m_clipProducer->set_in_and_out(getProperty("in").toInt(), getProperty("out").toInt());*/
setProducerProperty("ttl", getProperty("ttl").toInt());
//m_clipProducer->set("id", getProperty("id"));
+ if (!getProperty("animation").isEmpty()) {
+ Mlt::Service clipService(m_baseTrackProducers.at(0)->get_service());
+ int ct = 0;
+ Mlt::Filter *filter = clipService.filter(ct);
+ while (filter) {
+ if (strcmp(filter->get("mlt_service"), "affine") == 0) {
+ break;
+ }
+ else if (strcmp(filter->get("mlt_service"), "boxblur") == 0) {
+ clipService.detach(*filter);
+ } else ct++;
+ filter = clipService.filter(ct);
+ }
+
+ if (!filter || strcmp(filter->get("mlt_service"), "affine")) {
+ // filter does not exist, create it.
+ Mlt::Filter *filter = new Mlt::Filter(*(m_baseTrackProducers.at(0)->profile()), "affine");
+ if (filter && filter->is_valid()) {
+ int cycle = getProperty("ttl").toInt();
+ QString geometry = SlideshowClip::animationToGeometry(getProperty("animation"), cycle);
+ if (!geometry.isEmpty()) {
+ if (getProperty("animation").contains("low-pass")) {
+ Mlt::Filter *blur = new Mlt::Filter(*(m_baseTrackProducers.at(0)->profile()), "boxblur");
+ if (blur && blur->is_valid())
+ clipService.attach(*blur);
+ }
+ filter->set("transition.geometry", geometry.toUtf8().data());
+ filter->set("transition.cycle", cycle);
+ clipService.attach(*filter);
+ }
+ }
+ }
+ } else {
+ Mlt::Service clipService(m_baseTrackProducers.at(0)->get_service());
+ int ct = 0;
+ Mlt::Filter *filter = clipService.filter(0);
+ while (filter) {
+ if (strcmp(filter->get("mlt_service"), "affine") == 0 || strcmp(filter->get("mlt_service"), "boxblur") == 0) {
+ clipService.detach(*filter);
+ } else ct++;
+ filter = clipService.filter(ct);
+ }
+ }
if (getProperty("fade") == "1") {
// we want a fade filter effect
kDebug() << "//////////// FADE WANTED";
}
if (filter && strcmp(filter->get("mlt_service"), "luma") == 0) {
- filter->set("period", getProperty("ttl").toInt() - 1);
- filter->set("luma.out", getProperty("luma_duration").toInt());
+ filter->set("cycle", getProperty("ttl").toInt());
+ filter->set("duration", getProperty("luma_duration").toInt());
QString resource = getProperty("luma_file");
char *tmp = (char *) qstrdup(resource.toUtf8().data());
filter->set("luma.resource", tmp);
} else {
// filter does not exist, create it...
Mlt::Filter *filter = new Mlt::Filter(*(m_baseTrackProducers.at(0)->profile()), "luma");
- filter->set("period", getProperty("ttl").toInt() - 1);
- filter->set("luma.out", getProperty("luma_duration").toInt());
+ filter->set("cycle", getProperty("ttl").toInt());
+ filter->set("duration", getProperty("luma_duration").toInt());
QString resource = getProperty("luma_file");
char *tmp = (char *) qstrdup(resource.toUtf8().data());
filter->set("luma.resource", tmp);
emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
}
-void KdenliveDoc::slotCreateSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool crop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, QString group, const QString &groupId)
-{
- m_clipManager->slotAddSlideshowClipFile(name, path, count, duration, loop, crop, fade, luma_duration, luma_file, softness, group, groupId);
+void KdenliveDoc::slotCreateSlideshowClipFile(const QString name, const QString path, int count, const QString duration,
+ const bool loop, const bool crop, const bool fade,
+ const QString &luma_duration, const QString &luma_file, const int softness,
+ const QString &animation, QString group, const QString &groupId)
+{
+ m_clipManager->slotAddSlideshowClipFile(name, path, count, duration, loop,
+ crop, fade, luma_duration,
+ luma_file, softness,
+ animation, group, groupId);
setModified(true);
emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
}
public slots:
void slotCreateXmlClip(const QString &name, const QDomElement xml, QString group, const QString &groupId);
void slotCreateColorClip(const QString &name, const QString &color, const QString &duration, QString group, const QString &groupId);
- void slotCreateSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool crop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, QString group, const QString &groupId);
+ void slotCreateSlideshowClipFile(const QString name, const QString path, int count, const QString duration,
+ const bool loop, const bool crop, const bool fade,
+ const QString &luma_duration, const QString &luma_file, const int softness,
+ const QString &animation, QString group, const QString &groupId);
void slotCreateTextClip(QString group, const QString &groupId, const QString &templatePath = QString());
void slotCreateTextTemplateClip(QString group, const QString &groupId, KUrl path);
/** Set to true if document needs saving, false otherwise */
fileName.chop(1);
}
- m_doc->slotCreateSlideshowClipFile(fileName, pattern, count, m_timecode.reformatSeparators(KdenliveSettings::sequence_duration()), false, false, false, m_timecode.getTimecodeFromFrames(int(ceil(m_timecode.fps()))), QString(), 0, groupInfo.at(0), groupInfo.at(1));
+ m_doc->slotCreateSlideshowClipFile(fileName, pattern, count, m_timecode.reformatSeparators(KdenliveSettings::sequence_duration()),
+ false, false, false,
+ m_timecode.getTimecodeFromFrames(int(ceil(m_timecode.fps()))), QString(), 0,
+ QString(), groupInfo.at(0), groupInfo.at(1));
return;
}
}
if (dia->exec() == QDialog::Accepted) {
QStringList groupInfo = getGroup();
- m_doc->slotCreateSlideshowClipFile(dia->clipName(), dia->selectedPath(), dia->imageCount(), dia->clipDuration(), dia->loop(), dia->crop(), dia->fade(),
- dia->lumaDuration(), dia->lumaFile(), dia->softness(), groupInfo.at(0), groupInfo.at(1));
+ m_doc->slotCreateSlideshowClipFile(dia->clipName(), dia->selectedPath(), dia->imageCount(), dia->clipDuration(),
+ dia->loop(), dia->crop(), dia->fade(),
+ dia->lumaDuration(), dia->lumaFile(), dia->softness(),
+ dia->animation(), groupInfo.at(0), groupInfo.at(1));
}
delete dia;
}
#include "kdenlivesettings.h"
#include "kthumb.h"
#include "definitions.h"
+#include "slideshowclip.h"
#include <mlt++/Mlt.h>
Mlt::Frame *frame = producer->get_frame();
if (xml.attribute("type").toInt() == SLIDESHOW) {
- if (xml.hasAttribute("ttl")) producer->set("ttl", xml.attribute("ttl").toInt());
+ int ttl = xml.hasAttribute("ttl") ? xml.attribute("ttl").toInt() : 0;
+ if (ttl) producer->set("ttl", ttl);
+ if (!xml.attribute("animation").isEmpty()) {
+ Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, "affine");
+ if (filter && filter->is_valid()) {
+ int cycle = ttl;
+ QString geometry = SlideshowClip::animationToGeometry(xml.attribute("animation"), cycle);
+ if (!geometry.isEmpty()) {
+ if (xml.attribute("animation").contains("low-pass")) {
+ Mlt::Filter *blur = new Mlt::Filter(*m_mltProfile, "boxblur");
+ if (blur && blur->is_valid())
+ producer->attach(*blur);
+ }
+ filter->set("transition.geometry", geometry.toUtf8().data());
+ filter->set("transition.cycle", cycle);
+ producer->attach(*filter);
+ }
+ }
+ }
if (xml.attribute("fade") == "1") {
// user wants a fade effect to slideshow
Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, "luma");
if (filter && filter->is_valid()) {
- if (xml.hasAttribute("ttl")) filter->set("period", xml.attribute("ttl").toInt() - 1);
- if (xml.hasAttribute("luma_duration") && !xml.attribute("luma_duration").isEmpty()) filter->set("luma.out", xml.attribute("luma_duration").toInt());
+ if (ttl) filter->set("cycle", ttl);
+ if (xml.hasAttribute("luma_duration") && !xml.attribute("luma_duration").isEmpty()) filter->set("duration", xml.attribute("luma_duration").toInt());
if (xml.hasAttribute("luma_file") && !xml.attribute("luma_file").isEmpty()) {
char *tmp = decodedString(xml.attribute("luma_file"));
filter->set("luma.resource", tmp);
filter->set("luma.softness", (double) soft / 100.0);
}
}
- Mlt::Service clipService(producer->get_service());
- clipService.attach(*filter);
+ producer->attach(*filter);
}
}
if (xml.attribute("crop") == "1") {
m_view.image_type->addItem("TGA (*.tga)", "tga");
m_view.image_type->addItem("TIFF (*.tiff)", "tiff");
m_view.image_type->addItem("Open EXR (*.exr)", "exr");
+ m_view.animation->addItem(i18n("None"), QString());
+ m_view.animation->addItem(i18n("Pan"), "Pan");
+ m_view.animation->addItem(i18n("Pan, low-pass"), "Pan, low-pass");
+ m_view.animation->addItem(i18n("Pan and zoom"), "Pan and zoom");
+ m_view.animation->addItem(i18n("Pan and zoom, low-pass"), "Pan and zoom, low-pass");
+ m_view.animation->addItem(i18n("Zoom"), "Zoom");
+ m_view.animation->addItem(i18n("Zoom, low-pass"), "Zoom, low-pass");
m_view.clip_duration->setInputMask("");
m_view.clip_duration->setValidator(m_timecode.validator());
return m_view.luma_file->itemData(m_view.luma_file->currentIndex()).toString();
}
+QString SlideshowClip::animation() const
+{
+ if (m_view.animation->itemData(m_view.animation->currentIndex()).isNull()) return QString();
+ return m_view.animation->itemData(m_view.animation->currentIndex()).toString();
+}
+
void SlideshowClip::slotUpdateDurationFormat(int ix)
{
bool framesFormat = ix == 1;
parseFolder();
}
-
+// static
+QString SlideshowClip::animationToGeometry(const QString &animation, int &ttl)
+{
+ QString geometry;
+ if (animation.startsWith("Pan and zoom")) {
+ geometry = QString().sprintf("0=0,0:100%%x100%%;%d=-14%%,-14%%:120%%x120%%;%d=-5%%,-5%%:110%%x110%%;%d=0,0:110%%x110%%;%d=0,-5%%:110%%x110%%;%d=-5%%,0:110%%x110%%",
+ ttl-1, ttl, ttl*2 - 1, ttl*2, ttl*3 - 1 );
+ ttl *= 3;
+ } else if (animation.startsWith("Pan")) {
+ geometry = QString().sprintf("0=-5%%,-5%%:110%%x110%%;%d=0,0:110%%x110%%;%d=0,0:110%%x110%%;%d=0,-5%%:110%%x110%%;%d=0,-5%%:110%%x110%%;%d=-5%%,-5%%:110%%x110%%;%d=0,-5%%:110%%x110%%;%d=-5%%,0:110%%x110%%",
+ ttl-1, ttl, ttl*2 - 1, ttl*2, ttl*3 - 1, ttl*3, ttl*4 - 1 );
+ ttl *= 4;
+ } else if (animation.startsWith("Zoom")) {
+ geometry = QString().sprintf("0=0,0:100%%x100%%;%d=-14%%,-14%%:120%%x120%%",
+ ttl-1, ttl );
+ }
+ return geometry;
+}
#include "slideshowclip.moc"
bool fade() const;
QString lumaFile() const;
int softness() const;
+ QString animation() const;
/** @brief Check if there are several files with filename pattern, like: image_001.jpg, image_002.jpg,... */
static int sequenceCount(KUrl file);
/** @brief return the url pattern for selected slideshow. */
static QString selectedPath(KUrl url, bool isMime, QString extension, int *count);
+ /** @brief Convert the selection animation style into an affine geometry string. */
+ static QString animationToGeometry(const QString &animation, int &ttl);
private slots:
void parseFolder();
<rect>
<x>0</x>
<y>0</y>
- <width>302</width>
- <height>424</height>
+ <width>306</width>
+ <height>478</height>
</rect>
</property>
<property name="windowTitle">
</property>
</widget>
</item>
- <item row="8" column="0" colspan="3">
+ <item row="9" column="0" colspan="3">
<widget class="QLabel" name="slide_info">
<property name="text">
<string>No image found</string>
</property>
</widget>
</item>
- <item row="9" column="1">
+ <item row="10" column="1">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_animation">
+ <property name="text">
+ <string>Animation</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1" colspan="2">
+ <widget class="KComboBox" name="animation"/>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<rect>
<x>0</x>
<y>0</y>
- <width>287</width>
- <height>453</height>
+ <width>290</width>
+ <height>507</height>
</rect>
</property>
<property name="windowTitle">
</property>
</widget>
</item>
- <item row="8" column="0" colspan="4">
+ <item row="9" column="0" colspan="4">
<widget class="KListWidget" name="icon_list"/>
</item>
- <item row="9" column="0" colspan="4">
+ <item row="10" column="0" colspan="4">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="show_thumbs">
</item>
</layout>
</item>
- <item row="10" column="2" colspan="2">
+ <item row="11" column="2" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Animation</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="2" colspan="2">
+ <widget class="KComboBox" name="animation">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<customwidgets>