widgets/configmisc_ui.ui
widgets/configenv_ui.ui
widgets/configdisplay_ui.ui
+ widgets/configsdl_ui.ui
widgets/configcapture_ui.ui
widgets/effectlist_ui.ui
widgets/effectstack_ui.ui
//kDebug() << "-- RESCALE: CROP=" << m_cropStart << ", DIFF = " << durationDiff;
if (m_cropDuration + durationDiff <= GenTime()) {
durationDiff = GenTime() - (m_cropDuration - GenTime(3, m_fps));
- } else if (m_cropStart + m_cropDuration + durationDiff >= m_maxDuration) {
- durationDiff = m_maxDuration - m_cropDuration - m_cropStart;
+ } else if (m_cropStart + m_cropDuration + durationDiff >= maxDuration()) {
+ durationDiff = maxDuration() - m_cropDuration - m_cropStart;
}
m_cropDuration += durationDiff;
setRect(m_startPos.frames(m_fps) * scale, rect().y(), m_cropDuration.frames(m_fps) * scale, rect().height());
if (endThumbTimer) delete endThumbTimer;
}
-ClipItem *ClipItem::clone(double scale) const {
- ClipItem *duplicate = new ClipItem(m_clip, info(), scale, m_fps);
+ClipItem *ClipItem::clone(double scale, ItemInfo info) const {
+ ClipItem *duplicate = new ClipItem(m_clip, info, scale, m_fps);
duplicate->setEffectList(m_effectList);
+ duplicate->setSpeed(m_speed);
return duplicate;
}
update();
}
+GenTime ClipItem::maxDuration() const {
+ return m_maxDuration / m_speed;
+}
+
//virtual
void ClipItem::dropEvent(QGraphicsSceneDragDropEvent * event) {
QString effects = QString(event->mimeData()->data("kdenlive/effectslist"));
DocClipBase *baseClip() const;
QString clipName() const;
QDomElement xml() const;
- ClipItem *clone(double scale) const;
+ ClipItem *clone(double scale, ItemInfo info) const;
const EffectsList effectList();
void setFadeOut(int pos, double scale);
void setFadeIn(int pos, double scale);
void setEffectList(const EffectsList effectList);
void setSpeed(const double speed);
double speed() const;
+ GenTime maxDuration() const;
protected:
//virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
newPos.cropStart = item->cropStart() + (cutTime - info.startPos);
newPos.track = info.track;
item->resizeEnd(cutPos, m_scale);
- ClipItem *dup = new ClipItem(item->baseClip(), newPos, m_scale, m_document->fps());
- dup->setEffectList(item->effectList());
+ ClipItem *dup = item->clone(m_scale, newPos);
scene()->addItem(dup);
m_document->renderer()->mltCutClip(m_tracksList.count() - info.track, cutTime);
item->baseClip()->addReference();
} else if (m_operationMode == RESIZESTART && m_dragItem->startPos() != m_dragItemInfo.startPos) {
// resize start
if (m_dragItem->type() == AVWIDGET) {
- m_document->renderer()->mltResizeClipStart(m_tracksList.count() - m_dragItem->track(), m_dragItem->endPos(), m_dragItem->startPos(), m_dragItemInfo.startPos, m_dragItem->cropStart(), m_dragItem->cropStart() + m_dragItem->endPos() - m_dragItem->startPos());
- updateClipFade((ClipItem *) m_dragItem);
- ResizeClipCommand *command = new ResizeClipCommand(this, m_dragItemInfo, info, false);
- m_commandStack->push(command);
+ bool success = m_document->renderer()->mltResizeClipStart(m_tracksList.count() - m_dragItem->track(), m_dragItem->endPos(), m_dragItem->startPos(), m_dragItemInfo.startPos, m_dragItem->cropStart(), m_dragItem->cropStart() + m_dragItem->endPos() - m_dragItem->startPos());
+ if (success) {
+ updateClipFade((ClipItem *) m_dragItem);
+ ResizeClipCommand *command = new ResizeClipCommand(this, m_dragItemInfo, info, false);
+ m_commandStack->push(command);
+ }
+ else {
+ m_dragItem->resizeStart((int) m_dragItemInfo.startPos.frames(m_document->fps()), m_scale);
+ emit displayMessage(i18n("Error when resizing clip"), ErrorMessage);
+ }
} else if (m_dragItem->type() == TRANSITIONWIDGET) {
MoveTransitionCommand *command = new MoveTransitionCommand(this, m_dragItemInfo, info, false);
m_commandStack->push(command);
ItemInfo info = item->info();
int percent = QInputDialog::getInteger(this, i18n("Edit Clip Speed"), i18n("New speed (percents)"), 100, 1, 300);
double speed = (double) percent / 100.0;
- new ChangeSpeedCommand(this, info, item->speed(), speed, item->clipProducer(), true, changeSelected);
+ if (item->speed() != speed)
+ new ChangeSpeedCommand(this, info, item->speed(), speed, item->clipProducer(), true, changeSelected);
}
}
m_commandStack->push(changeSelected);
DocClipBase *baseclip = m_document->clipManager()->getClipById(id);
ClipItem *item = getClipItemAt((int) info.startPos.frames(m_document->fps()) + 1, info.track);
info.track = m_tracksList.count() - item->track();
- int newLength = m_document->renderer()->mltChangeClipSpeed(info, speed, baseclip->producer());
- GenTime maxDuration(newLength, m_document->fps());
- item->setMaxDuration(maxDuration);
+ m_document->renderer()->mltChangeClipSpeed(info, speed, baseclip->producer());
item->setSpeed(speed);
+ GenTime maxDuration = item->maxDuration();
if (maxDuration < item->duration()) {
info = item->info();
ItemInfo endInfo = info;
return;
}
if (resizeClipStart) {
- m_document->renderer()->mltResizeClipStart(m_tracksList.count() - item->track(), item->endPos(), end.startPos, item->startPos(), item->cropStart() + end.startPos - start.startPos, item->cropStart() + end.startPos - start.startPos + item->endPos() - end.startPos);
- item->resizeStart((int) end.startPos.frames(m_document->fps()), m_scale);
- updateClipFade(item);
+ bool success = m_document->renderer()->mltResizeClipStart(m_tracksList.count() - item->track(), item->endPos(), end.startPos, item->startPos(), item->cropStart() + end.startPos - start.startPos, item->cropStart() + end.startPos - start.startPos + item->endPos() - end.startPos);
+ if (success) {
+ item->resizeStart((int) end.startPos.frames(m_document->fps()), m_scale);
+ updateClipFade(item);
+ }
+ else emit displayMessage(i18n("Error when resizing clip"), ErrorMessage);
} else {
m_document->renderer()->mltResizeClipEnd(m_tracksList.count() - item->track(), item->startPos(), item->cropStart(), item->cropStart() + end.endPos - item->startPos());
item->resizeEnd((int) end.endPos.frames(m_document->fps()), m_scale);
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i)->type() == AVWIDGET) {
ClipItem *dup = static_cast <ClipItem *>(itemList.at(i));
- m_copiedItems.append(dup->clone(m_scale));
+ m_copiedItems.append(dup->clone(m_scale, dup->info()));
} else if (itemList.at(i)->type() == TRANSITIONWIDGET) {
Transition *dup = static_cast <Transition *>(itemList.at(i));
m_copiedItems.append(dup->clone(m_scale));
#include "mainwindow.h"
-KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, MltVideoProfile profile, QUndoGroup *undoGroup, MainWindow *parent): QObject(parent), m_render(NULL), m_url(url), m_projectFolder(projectFolder), m_profile(profile), m_fps((double)profile.frame_rate_num / profile.frame_rate_den), m_width(profile.width), m_height(profile.height), m_commandStack(new KUndoStack(undoGroup)), m_modified(false), m_documentLoadingProgress(0), m_documentLoadingStep(0.0), m_startPos(0), m_zoom(4) {
+KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, MltVideoProfile profile, QUndoGroup *undoGroup, MainWindow *parent): QObject(parent), m_render(NULL), m_url(url), m_projectFolder(projectFolder), m_profile(profile), m_fps((double)profile.frame_rate_num / profile.frame_rate_den), m_width(profile.width), m_height(profile.height), m_commandStack(new KUndoStack(undoGroup)), m_modified(false), m_documentLoadingProgress(0), m_documentLoadingStep(0.0), m_startPos(0), m_zoom(7) {
kDebug() << "// init profile, ratnum: " << profile.frame_rate_num << ", " << profile.frame_rate_num << ", width: " << profile.width;
m_clipManager = new ClipManager(this);
KdenliveSettings::setProject_fps(m_fps);
QDomElement infoXml = infoXmlNode.toElement();
QString profilePath = infoXml.attribute("profile");
m_startPos = infoXml.attribute("position").toInt();
- m_zoom = infoXml.attribute("zoom", "4").toInt();
+ m_zoom = infoXml.attribute("zoom", "7").toInt();
if (!profilePath.isEmpty()) setProfilePath(profilePath);
double version = infoXml.attribute("version").toDouble();
if (version < 0.7) convertDocument(version);
int pos = 0;
for (int i = 0; i < maxprod; i++) {
QDomNode m = prods.at(pos);
- if (m.toElement().attribute("id") == "black")
- pos = 1;
+ QString prodId = m.toElement().attribute("id");
+ if (prodId == "black" || prodId.startsWith("slowmotion"))
+ pos++;
else westley.removeChild(m);
}
prods = m_document.elementsByTagName("kdenlive_producer");
parent->slotGotProgressInfo(QString(), (int) m_documentLoadingProgress);
qApp->processEvents();
}
- if (!e.isNull() && e.attribute("id") != "black") {
+ QString prodId = e.attribute("id");
+ if (!e.isNull() && prodId != "black" && prodId.toInt() > 0) {
addClip(e, e.attribute("id").toInt());
}
}
<label>Tracks height in pixel.</label>
<default>50</default>
</entry>
+
+ <entry name="audio_device" type="UInt">
+ <label>Audio device used for sound output.</label>
+ <default>0</default>
+ </entry>
+
+ <entry name="audio_driver" type="UInt">
+ <label>Audio driver used for sound output.</label>
+ <default>0</default>
+ </entry>
+
+ <entry name="video_driver" type="UInt">
+ <label>Video driver used for output.</label>
+ <default>0</default>
+ </entry>
+
+ <entry name="audiodevicename" type="String">
+ <label>Audio device used for sound output.</label>
+ <default></default>
+ </entry>
+
+ <entry name="audiodrivername" type="String">
+ <label>Audio driver used for sound output.</label>
+ <default></default>
+ </entry>
+
+ <entry name="videodrivername" type="String">
+ <label>Video driver used for output.</label>
+ <default></default>
+ </entry>
+
</group>
<group name="env">
slotCheckShuttle(KdenliveSettings::enableshuttle());
page5 = addPage(p5, i18n("JogShuttle"), "input-mouse");
+ QWidget *p6 = new QWidget;
+ m_configSdl.setupUi(p6);
+ page6 = addPage(p6, i18n("Playback"), "audio-card");
+
QStringList actions;
actions << i18n("Do nothing");
actions << i18n("Play / Pause");
}
slotUpdateDisplay();
-
+ m_audioDevice = KdenliveSettings::audio_device();
+ initDevices();
connect(m_configMisc.kcfg_profiles_list, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateDisplay()));
}
KdenliveSettingsDialog::~KdenliveSettingsDialog() {}
+void KdenliveSettingsDialog::initDevices()
+{
+ // Fill audio drivers
+ m_configSdl.kcfg_audio_driver->addItem(i18n("Automatic"), QString());
+ m_configSdl.kcfg_audio_driver->addItem(i18n("OSS"), "dsp");
+ m_configSdl.kcfg_audio_driver->addItem(i18n("ALSA"), "alsa");
+ m_configSdl.kcfg_audio_driver->addItem(i18n("OSS with DMA access"), "dma");
+ m_configSdl.kcfg_audio_driver->addItem(i18n("Esound daemon"), "esd");
+ m_configSdl.kcfg_audio_driver->addItem(i18n("ARTS daemon"), "artsc");
+
+ /*if (!KdenliveSettings::audiodriver().isEmpty())
+ for (uint i = 1;i < m_configDisplay.kcfg_audio_driver->count(); i++) {
+ if (m_configDisplay.kcfg_audio_driver->itemData(i).toString() == KdenliveSettings::audiodriver())
+ m_configDisplay.kcfg_audio_driver->setCurrentIndex(i);
+ }*/
+
+ // Fill video drivers
+ m_configSdl.kcfg_video_driver->addItem(i18n("Automatic"), QString());
+ m_configSdl.kcfg_video_driver->addItem(i18n("X11"), "x11");
+ m_configSdl.kcfg_video_driver->addItem(i18n("XFREE86 DGA 2.0"), "dga");
+ m_configSdl.kcfg_video_driver->addItem(i18n("Nano X"), "nanox");
+ m_configSdl.kcfg_video_driver->addItem(i18n("Framebuffer console"), "fbcon");
+ m_configSdl.kcfg_video_driver->addItem(i18n("Direct FB"), "directfb");
+ m_configSdl.kcfg_video_driver->addItem(i18n("SVGAlib"), "svgalib");
+ m_configSdl.kcfg_video_driver->addItem(i18n("General graphics interface"), "ggi");
+ m_configSdl.kcfg_video_driver->addItem(i18n("Ascii art library"), "aalib");
+
+ // Fill the list of audio playback devices
+ m_configSdl.kcfg_audio_device->addItem(i18n("Default"), QString());
+ if (KStandardDirs::findExe("aplay") != QString::null) {
+ m_readProcess.setOutputChannelMode(KProcess::OnlyStdoutChannel);
+ m_readProcess.setProgram("aplay", QStringList() << "-l");
+ connect(&m_readProcess, SIGNAL(readyReadStandardOutput()) ,this, SLOT(slotReadAudioDevices()));
+ m_readProcess.execute(5000);
+ }
+ else {
+ // If aplay is not installed on the system, parse the /proc/asound/pcm file
+ QFile file("/proc/asound/pcm");
+ if ( file.open( QIODevice::ReadOnly ) ) {
+ QTextStream stream( &file );
+ QString line;
+ while ( !stream.atEnd() ) {
+ line = stream.readLine();
+ if (line.contains("playback")) {
+ QString deviceId = line.section(":", 0, 0);
+ m_configSdl.kcfg_audio_device->addItem(line.section(":", 1, 1), "plughw:" + QString::number(deviceId.section("-", 0, 0).toInt()) + "," + QString::number(deviceId.section("-", 1, 1).toInt()));
+ }
+ }
+ file.close();
+ }
+ }
+}
+
+
+void KdenliveSettingsDialog::slotReadAudioDevices()
+{
+ QString result = QString(m_readProcess.readAllStandardOutput());
+ kDebug()<<"// / / / / / READING APLAY: ";
+ kDebug()<< result;
+ QStringList lines = result.split('\n');
+ foreach (QString data, lines) {
+ kDebug()<<"// READING LINE: "<<data;
+ if (data.simplified().startsWith("card")) {
+ QString card = data.section(":", 0, 0).section(" ", -1);
+ QString device = data.section(":", 1, 1).section(" ", -1);
+ m_configSdl.kcfg_audio_device->addItem(data.section(":", -1), "plughw:" + card + "," + device);
+ }
+ }
+}
+
void KdenliveSettingsDialog::showPage(int page, int option) {
switch (page) {
case 1:
m_configCapture.kcfg_video4playback->setText(playbackCommand);
}
+
+// virtual protected
+bool KdenliveSettingsDialog::isDefault() {
+ return KConfigDialog::isDefault();
+}
+
+// virtual protected
bool KdenliveSettingsDialog::hasChanged() {
kDebug() << "// // // KCONFIG hasChanged called: " << m_configMisc.kcfg_profiles_list->currentText() << ", " << m_defaultProfile;
+
if (m_configMisc.kcfg_profiles_list->currentText() != m_defaultProfile) return true;
return KConfigDialog::hasChanged();
}
kDebug() << "// // // KCONFIG UPDATE called";
m_defaultProfile = m_configMisc.kcfg_profiles_list->currentText();
KdenliveSettings::setDefault_profile(m_defaultPath);
+
+ bool resetProfile = false;
+ QString value = m_configSdl.kcfg_audio_device->itemData(m_configSdl.kcfg_audio_device->currentIndex()).toString();
+ if (value != KdenliveSettings::audiodevicename()) {
+ KdenliveSettings::setAudiodevicename(value);
+ resetProfile = true;
+ }
+
+ value = m_configSdl.kcfg_audio_driver->itemData(m_configSdl.kcfg_audio_driver->currentIndex()).toString();
+ if (value != KdenliveSettings::audiodrivername()) {
+ KdenliveSettings::setAudiodrivername(value);
+ resetProfile = true;
+ }
+
+ value = m_configSdl.kcfg_video_driver->itemData(m_configSdl.kcfg_video_driver->currentIndex()).toString();
+ if (value != KdenliveSettings::videodrivername()) {
+ KdenliveSettings::setVideodrivername(value);
+ resetProfile = true;
+ }
+
KConfigDialog::updateSettings();
+ if (resetProfile) emit doResetProfile();
}
void KdenliveSettingsDialog::slotUpdateDisplay() {
#include <QDialog>
#include <KConfigDialog>
+#include <KProcess>
#include "ui_configmisc_ui.h"
#include "ui_configenv_ui.h"
#include "ui_configdisplay_ui.h"
#include "ui_configcapture_ui.h"
#include "ui_configjogshuttle_ui.h"
+#include "ui_configsdl_ui.h"
class KdenliveSettingsDialog : public KConfigDialog {
Q_OBJECT
~KdenliveSettingsDialog();
void showPage(int page, int option);
-protected:
- virtual bool hasChanged();
- virtual void updateSettings();
+ bool hasChanged();
+ bool isDefault();
+ void updateSettings();
private slots:
void slotUpdateDisplay();
void slotEditImageApplication();
void slotEditAudioApplication();
void slotEditVideoApplication();
+ void slotReadAudioDevices();
private:
KPageWidgetItem *page1;
KPageWidgetItem *page3;
KPageWidgetItem *page4;
KPageWidgetItem *page5;
+ KPageWidgetItem *page6;
Ui::ConfigEnv_UI m_configEnv;
Ui::ConfigMisc_UI m_configMisc;
Ui::ConfigDisplay_UI m_configDisplay;
Ui::ConfigCapture_UI m_configCapture;
Ui::ConfigJogShuttle_UI m_configShuttle;
+ Ui::ConfigSdl_UI m_configSdl;
QStringList m_mltProfilesList;
QStringList m_customProfilesList;
bool m_isCustomProfile;
QString m_defaultProfile;
QString m_defaultPath;
+ KProcess m_readProcess;
+ void initDevices();
+ uint m_audioDevice;
signals:
void customChanged();
-
+ void doResetProfile();
};
// create it :
KdenliveSettingsDialog* dialog = new KdenliveSettingsDialog(this);
connect(dialog, SIGNAL(settingsChanged(const QString&)), this, SLOT(updateConfiguration()));
+ connect(dialog, SIGNAL(doResetProfile()), this, SLOT(resetProfiles()));
dialog->show();
if (page != -1) dialog->showPage(page, option);
}
}
+void MainWindow::resetProfiles() {
+ m_monitorManager->resetProfiles(m_activeDocument->profilePath());
+}
+
void MainWindow::slotSwitchVideoThumbs() {
KdenliveSettings::setVideothumbnails(!KdenliveSettings::videothumbnails());
if (m_activeTimeline) {
void slotPasteEffects();
void slotReloadEffects();
void slotChangeClipSpeed();
-
+ void resetProfiles();
};
m_mltConsumer->set("terminate_on_pause", 1);
m_mltConsumer->set("rescale", "nearest");
m_mltConsumer->set("progressive", 1);
+ char *tmp;
+
+ QString audioDevice = KdenliveSettings::audiodevicename();
+ if (!audioDevice.isEmpty()) {
+ tmp = decodedString(audioDevice);
+ m_mltConsumer->set("audio_device", tmp);
+ delete[] tmp;
+ }
+
+ QString videoDriver = KdenliveSettings::videodrivername();
+ if (!videoDriver.isEmpty()) {
+ tmp = decodedString(videoDriver);
+ m_mltConsumer->set("video_driver", tmp);
+ delete[] tmp;
+ }
+
+ QString audioDriver = KdenliveSettings::audiodrivername();
+ if (!audioDriver.isEmpty()) {
+ tmp = decodedString(audioDriver);
+ m_mltConsumer->set("audio_driver", tmp);
+ delete[] tmp;
+ }
+
m_mltConsumer->set("audio_buffer", 1024);
m_mltConsumer->set("frequency", 48000);
m_externalwinid = extid;
m_winid = winid;
m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show);
- Mlt::Producer *producer = new Mlt::Producer(*m_mltProfile , "westley-xml", "<westley><playlist><producer mlt_service=\"colour\" colour=\"blue\" in=\"0\" out=\"25\" /></playlist></westley>");
+ Mlt::Producer *producer = new Mlt::Producer(*m_mltProfile , "colour", "black");
m_mltProducer = producer;
if (m_blackClip) delete m_blackClip;
m_blackClip = new Mlt::Producer(*m_mltProfile , "colour", "black");
m_mltConsumer->set("terminate_on_pause", 1);
m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show);
m_mltConsumer->set("rescale", "nearest");
+
+ QString audioDevice = KdenliveSettings::audiodevicename();
+ if (!audioDevice.isEmpty()) {
+ tmp = decodedString(audioDevice);
+ m_mltConsumer->set("audio_device", tmp);
+ delete[] tmp;
+ }
+
+ QString videoDriver = KdenliveSettings::videodrivername();
+ if (!videoDriver.isEmpty()) {
+ tmp = decodedString(videoDriver);
+ m_mltConsumer->set("video_driver", tmp);
+ delete[] tmp;
+ }
+
+ QString audioDriver = KdenliveSettings::audiodrivername();
+ if (!audioDriver.isEmpty()) {
+ tmp = decodedString(audioDriver);
+ m_mltConsumer->set("audio_driver", tmp);
+ delete[] tmp;
+ }
+
+
m_mltConsumer->set("progressive", 1);
m_mltConsumer->set("audio_buffer", 1024);
m_mltConsumer->set("frequency", 48000);
ct++;
filter = clipService.filter(ct);
}
+ m_isBlocked = false;
}
void Render::mltUpdateClip(ItemInfo info, QDomElement element, Mlt::Producer *prod) {
int newLength = 0;
Mlt::Service service(m_mltProducer->parent().get_service());
if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
-
+ kDebug()<<"Changing clip speed, set in and out: "<<info.cropStart.frames(m_fps)<<" to "<<(info.endPos - info.startPos).frames(m_fps) - 1;
Mlt::Tractor tractor(service);
Mlt::Producer trackProducer(tractor.track(info.track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
if (serv == "avformat" && speed != 1.0) {
mlt_service_lock(service.get_service());
QString url = clip.parent().get("resource");
- url.append(":" + QString::number(speed));
- char *tmp = decodedString(url);
- Mlt::Producer *slow = new Mlt::Producer(*m_mltProfile, "framebuffer", tmp);
- delete[] tmp;
- tmp = decodedString(id);
- slow->set("id", tmp);
- delete[] tmp;
- slow->set_in_and_out(info.cropStart.frames(m_fps), (info.endPos - info.startPos).frames(m_fps));
- newLength = slow->get_length();
+ url.append("?" + QString::number(speed));
+ 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;
+ QString producerid = "slowmotion:" + id + ":" + QString::number(speed);
+ tmp = decodedString(producerid);
+ slowprod->set("id", tmp);
+ delete[] tmp;
+ m_slowmotionProducers.insert(url, slowprod);
+ }
+ Mlt::Producer *cut = slowprod->cut(info.cropStart.frames(m_fps), (info.endPos - info.startPos).frames(m_fps) - 1);
+ newLength = cut->get_length();
trackPlaylist.replace_with_blank(clipIndex);
trackPlaylist.consolidate_blanks(0);
- trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *slow, 1);
+ trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *cut, 1);
mlt_service_unlock(service.get_service());
- kDebug() << "AVFORMAT CLIP!!!:";
} else if (speed == 1.0) {
mlt_service_lock(service.get_service());
Mlt::Producer *cut = prod->cut(info.cropStart.frames(m_fps), (info.endPos - info.startPos).frames(m_fps) - 1);
} else if (serv == "framebuffer") {
mlt_service_lock(service.get_service());
QString url = clip.parent().get("resource");
- url = url.section(":", 0, -1);
- url.append(":" + QString::number(speed));
- char *tmp = decodedString(url);
- Mlt::Producer *slow = new Mlt::Producer(*m_mltProfile, "framebuffer", tmp);
- delete[] tmp;
- tmp = decodedString(id);
- slow->set("id", tmp);
- delete[] tmp;
- slow->set_in_and_out(info.cropStart.frames(m_fps), (info.endPos - info.startPos).frames(m_fps));
- newLength = slow->get_length();
+ url = url.section("?", 0, 0);
+ url.append("?" + QString::number(speed));
+ 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;
+ QString producerid = "slowmotion:" + id.section(":", 1, 1) + ":" + QString::number(speed);
+ tmp = decodedString(producerid);
+ slowprod->set("id", tmp);
+ delete[] tmp;
+ m_slowmotionProducers.insert(url, slowprod);
+ }
+ Mlt::Producer *cut = slowprod->cut(info.cropStart.frames(m_fps), (info.endPos - info.startPos).frames(m_fps) - 1);
+ newLength = cut->get_length();
trackPlaylist.replace_with_blank(clipIndex);
trackPlaylist.consolidate_blanks(0);
- trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *slow, 1);
+ trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *cut, 1);
mlt_service_unlock(service.get_service());
kDebug() << "AVFORMAT CLIP!!!:";
}
refresh();
}
-void Render::mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime moveStart, GenTime in, GenTime out) {
- m_isBlocked = true;
-
+bool Render::mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime moveStart, GenTime in, GenTime out) {
Mlt::Service service(m_mltProducer->parent().get_service());
-
int moveFrame = (int)(moveEnd - moveStart).frames(m_fps);
-
Mlt::Tractor tractor(service);
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
- if (trackPlaylist.is_blank_at((int) pos.frames(m_fps) - 1))
+ if (trackPlaylist.is_blank_at((int) pos.frames(m_fps) - 1)) {
kDebug() << "//////// ERROR RSIZING BLANK CLIP!!!!!!!!!!!";
+ return false;
+ }
int clipIndex = trackPlaylist.get_clip_index_at((int) pos.frames(m_fps) - 1);
int previousStart = trackPlaylist.clip_start(clipIndex);
//kDebug() << " ** RESIZING CLIP START:" << clipIndex << " on track:" << track << ", mid pos: " << pos.frames(25) << ", moving: " << moveFrame << ", in: " << in.frames(25) << ", out: " << out.frames(25);
Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
+ if (clip == NULL) {
+ return false;
+ }
+ m_isBlocked = true;
trackPlaylist.resize_clip(clipIndex, (int) in.frames(m_fps), (int) out.frames(m_fps));
if (moveFrame > 0) trackPlaylist.insert_blank(clipIndex, moveFrame - 1);
else {
mltAddClipTransparency(info, info.track - 1, QString(clip->parent().get("id")).toInt());
}
m_isBlocked = false;
+ return true;
}
bool Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTime moveEnd) {
if (endTrack == startTrack) {
//mlt_service_lock(service.get_service());
Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
- trackPlaylist.consolidate_blanks(0);
if (!trackPlaylist.is_blank_at(moveEnd)) {
// error, destination is not empty
m_isBlocked = false;
return false;
} else {
- trackPlaylist.insert_at(moveEnd, clipProducer, 1);
trackPlaylist.consolidate_blanks(0);
+ trackPlaylist.insert_at(moveEnd, clipProducer, 1);
if (QString(clipProducer.parent().get("transparency")).toInt() == 1) {
mltMoveTransparency(moveStart, moveEnd, startTrack, endTrack, QString(clipProducer.parent().get("id")).toInt());
}
void mltUpdateClip(ItemInfo info, QDomElement element, Mlt::Producer *prod);
void mltCutClip(int track, GenTime position);
void mltResizeClipEnd(int track, GenTime pos, GenTime in, GenTime out);
- void mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime moveStart, GenTime in, GenTime out);
+ bool mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime moveStart, GenTime in, GenTime out);
bool mltMoveClip(int startTrack, int endTrack, GenTime pos, GenTime moveStart);
bool mltMoveClip(int startTrack, int endTrack, int pos, int moveStart);
void mltRemoveClip(int track, GenTime position);
void mltMoveTransparency(int startTime, int endTime, int startTrack, int endTrack, int id);
void mltDeleteTransparency(int pos, int track, int id);
void mltResizeTransparency(int oldStart, int newStart, int newEnd, int track, int id);
+
+ /** Change speed of a clip in playlist. To do this, we create a new "framebuffer" producer.
+ This new producer must have its "resource" param set to: video.mpg?0.6 where video.mpg is the path
+ 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, Mlt::Producer *prod);
private: // Private attributes & methods
void closeMlt();
void mltCheckLength(bool reload = true);
QMap<QString, QString> mltGetTransitionParamsFromXml(QDomElement xml);
+ QMap<QString, Mlt::Producer *> m_slowmotionProducers;
private slots: // Private slots
/** refresh monitor display */
void TrackView::parseDocument(QDomDocument doc) {
int cursorPos = 0;
+
// kDebug() << "//// DOCUMENT: " << doc.toString();
QDomNode props = doc.elementsByTagName("properties").item(0);
if (!props.isNull()) {
int pos = m_projectTracks - 1;
+
for (int i = 0; i < m_projectTracks; i++) {
e = tracks.item(i).toElement();
QString playlist_name = e.attribute("producer");
qApp->processEvents();
// Found a clip
int in = elem.attribute("in").toInt();
- int id = elem.attribute("producer").toInt();
+ QString idString = elem.attribute("producer");
+ int id = idString.toInt();
+ bool hasSpeedAttribute = false;
+ double speed;
+ if (idString.startsWith("slowmotion")) {
+ hasSpeedAttribute = true;
+ id = idString.section(":", 1, 1).toInt();
+ speed = idString.section(":", 2, 2).toDouble();
+ }
DocClipBase *clip = m_doc->clipManager()->getClipById(id);
if (clip != NULL) {
int out = elem.attribute("out").toInt();
clipinfo.track = ix;
//kDebug() << "// INSERTING CLIP: " << in << "x" << out << ", track: " << ix << ", ID: " << id << ", SCALE: " << m_scale << ", FPS: " << m_doc->fps();
ClipItem *item = new ClipItem(clip, clipinfo, m_scale, m_doc->fps());
+ if (hasSpeedAttribute) item->setSpeed(speed);
m_scene->addItem(item);
clip->addReference();
position += (out - in + 1);