From 9c59a265a6ded9306fa7afa13b18c96e25d45f77 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Sat, 2 Aug 2008 20:57:20 +0000 Subject: [PATCH] * New configuration page to set SDL audio/video driver and audio device * Fixed small issues in clip move * Slowmotion now working (still needs a small MLT patch to be committed soon) svn path=/branches/KDE4/; revision=2354 --- src/CMakeLists.txt | 1 + src/abstractclipitem.cpp | 4 +- src/clipitem.cpp | 9 ++- src/clipitem.h | 3 +- src/customtrackview.cpp | 36 ++++++---- src/kdenlivedoc.cpp | 12 ++-- src/kdenlivesettings.kcfg | 31 +++++++++ src/kdenlivesettingsdialog.cpp | 106 +++++++++++++++++++++++++++- src/kdenlivesettingsdialog.h | 16 +++-- src/mainwindow.cpp | 5 ++ src/mainwindow.h | 2 +- src/renderer.cpp | 122 ++++++++++++++++++++++++--------- src/renderer.h | 9 ++- src/trackview.cpp | 13 +++- 14 files changed, 305 insertions(+), 64 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ede02c85..b5fdf7f1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,7 @@ kde4_add_ui_files(kdenlive_UI 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 diff --git a/src/abstractclipitem.cpp b/src/abstractclipitem.cpp index 2fce8d1d..77a26f5b 100644 --- a/src/abstractclipitem.cpp +++ b/src/abstractclipitem.cpp @@ -136,8 +136,8 @@ void AbstractClipItem::resizeEnd(int posx, double scale) { //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()); diff --git a/src/clipitem.cpp b/src/clipitem.cpp index 8235ff55..f2180558 100644 --- a/src/clipitem.cpp +++ b/src/clipitem.cpp @@ -97,9 +97,10 @@ ClipItem::~ClipItem() { 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; } @@ -983,6 +984,10 @@ void ClipItem::setSpeed(const double speed) { update(); } +GenTime ClipItem::maxDuration() const { + return m_maxDuration / m_speed; +} + //virtual void ClipItem::dropEvent(QGraphicsSceneDragDropEvent * event) { QString effects = QString(event->mimeData()->data("kdenlive/effectslist")); diff --git a/src/clipitem.h b/src/clipitem.h index dc5b3b75..f21d049e 100644 --- a/src/clipitem.h +++ b/src/clipitem.h @@ -52,7 +52,7 @@ public: 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); @@ -93,6 +93,7 @@ public: void setEffectList(const EffectsList effectList); void setSpeed(const double speed); double speed() const; + GenTime maxDuration() const; protected: //virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event); diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 1fe7b944..aa087fad 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -817,8 +817,7 @@ void CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut) { 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(); @@ -1149,10 +1148,16 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) { } 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); @@ -1294,7 +1299,8 @@ void CustomTrackView::changeClipSpeed() { 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); @@ -1304,10 +1310,9 @@ void CustomTrackView::doChangeClipSpeed(ItemInfo info, double speed, int id) { 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; @@ -1456,9 +1461,12 @@ void CustomTrackView::resizeClip(const ItemInfo start, const ItemInfo end) { 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); @@ -1988,7 +1996,7 @@ void CustomTrackView::copyClip() { for (int i = 0; i < itemList.count(); i++) { if (itemList.at(i)->type() == AVWIDGET) { ClipItem *dup = static_cast (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 (itemList.at(i)); m_copiedItems.append(dup->clone(m_scale)); diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index fdc5745e..6de60180 100644 --- a/src/kdenlivedoc.cpp +++ b/src/kdenlivedoc.cpp @@ -37,7 +37,7 @@ #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); @@ -53,7 +53,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, MltVideoPro 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); @@ -64,8 +64,9 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, MltVideoPro 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"); @@ -90,7 +91,8 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, MltVideoPro 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()); } } diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg index f55679a5..46fa1778 100644 --- a/src/kdenlivesettings.kcfg +++ b/src/kdenlivesettings.kcfg @@ -55,6 +55,37 @@ 50 + + + + 0 + + + + + 0 + + + + + 0 + + + + + + + + + + + + + + + + + diff --git a/src/kdenlivesettingsdialog.cpp b/src/kdenlivesettingsdialog.cpp index 67de3edc..f644642a 100644 --- a/src/kdenlivesettingsdialog.cpp +++ b/src/kdenlivesettingsdialog.cpp @@ -67,6 +67,10 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(QWidget * parent): KConfigDialog( 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"); @@ -99,12 +103,83 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(QWidget * parent): KConfigDialog( } 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: "<addItem(data.section(":", -1), "plughw:" + card + "," + device); + } + } +} + void KdenliveSettingsDialog::showPage(int page, int option) { switch (page) { case 1: @@ -196,8 +271,16 @@ void KdenliveSettingsDialog::rebuildVideo4Commands() { 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(); } @@ -206,7 +289,28 @@ void KdenliveSettingsDialog::updateSettings() { 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() { diff --git a/src/kdenlivesettingsdialog.h b/src/kdenlivesettingsdialog.h index 3c606070..7fad4d6e 100644 --- a/src/kdenlivesettingsdialog.h +++ b/src/kdenlivesettingsdialog.h @@ -24,12 +24,14 @@ #include #include +#include #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 @@ -39,9 +41,9 @@ public: ~KdenliveSettingsDialog(); void showPage(int page, int option); -protected: - virtual bool hasChanged(); - virtual void updateSettings(); + bool hasChanged(); + bool isDefault(); + void updateSettings(); private slots: void slotUpdateDisplay(); @@ -51,6 +53,7 @@ private slots: void slotEditImageApplication(); void slotEditAudioApplication(); void slotEditVideoApplication(); + void slotReadAudioDevices(); private: KPageWidgetItem *page1; @@ -58,20 +61,25 @@ private: 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(); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e199bf45..ba08511d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1119,6 +1119,7 @@ void MainWindow::slotPreferences(int page, int option) { // 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); } @@ -1137,6 +1138,10 @@ void MainWindow::updateConfiguration() { } +void MainWindow::resetProfiles() { + m_monitorManager->resetProfiles(m_activeDocument->profilePath()); +} + void MainWindow::slotSwitchVideoThumbs() { KdenliveSettings::setVideothumbnails(!KdenliveSettings::videothumbnails()); if (m_activeTimeline) { diff --git a/src/mainwindow.h b/src/mainwindow.h index b4dc7477..cd7df070 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -232,7 +232,7 @@ private slots: void slotPasteEffects(); void slotReloadEffects(); void slotChangeClipSpeed(); - + void resetProfiles(); }; diff --git a/src/renderer.cpp b/src/renderer.cpp index 19ec0e18..df027a68 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -82,12 +82,35 @@ Render::Render(const QString & rendererName, int winid, int extid, QWidget *pare 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", ""); + 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"); @@ -154,6 +177,29 @@ int Render::resetProfile(QString profile) { 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); @@ -1239,6 +1285,7 @@ void Render::mltCutClip(int track, GenTime position) { ct++; filter = clipService.filter(ct); } + m_isBlocked = false; } void Render::mltUpdateClip(ItemInfo info, QDomElement element, Mlt::Producer *prod) { @@ -1273,7 +1320,7 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, 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: "<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); @@ -1310,19 +1361,24 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, Mlt::Producer *prod) } 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!!!:"; } @@ -1657,22 +1713,24 @@ void Render::mltChangeTrackState(int track, bool mute, bool blind) { 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 { @@ -1696,6 +1754,7 @@ void Render::mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime 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) { @@ -1718,7 +1777,6 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn 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 @@ -1728,8 +1786,8 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn 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()); } diff --git a/src/renderer.h b/src/renderer.h index e9311ebf..4f0d8427 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -152,7 +152,7 @@ Q_OBJECT public: 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); @@ -170,6 +170,12 @@ Q_OBJECT public: 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 @@ -208,6 +214,7 @@ private: // Private attributes & methods void closeMlt(); void mltCheckLength(bool reload = true); QMap mltGetTransitionParamsFromXml(QDomElement xml); + QMap m_slowmotionProducers; private slots: // Private slots /** refresh monitor display */ diff --git a/src/trackview.cpp b/src/trackview.cpp index ec26ff63..3cdd33d4 100644 --- a/src/trackview.cpp +++ b/src/trackview.cpp @@ -116,6 +116,7 @@ void TrackView::setDuration(int dur) { void TrackView::parseDocument(QDomDocument doc) { int cursorPos = 0; + // kDebug() << "//// DOCUMENT: " << doc.toString(); QDomNode props = doc.elementsByTagName("properties").item(0); if (!props.isNull()) { @@ -134,6 +135,7 @@ void TrackView::parseDocument(QDomDocument doc) { int pos = m_projectTracks - 1; + for (int i = 0; i < m_projectTracks; i++) { e = tracks.item(i).toElement(); QString playlist_name = e.attribute("producer"); @@ -331,7 +333,15 @@ int TrackView::slotAddProjectTrack(int ix, QDomElement xml, bool videotrack) { 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(); @@ -343,6 +353,7 @@ int TrackView::slotAddProjectTrack(int ix, QDomElement xml, bool videotrack) { 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); -- 2.39.2