Commit 31c339ff authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle

Implement MLT's new consumer scaling feature. In Monitor menu, you can now...

Implement MLT's new consumer scaling feature. In Monitor menu, you can now select to work in full, 1/2, 1/4 and 1/8 resolution
parent 22ccb0bd
Pipeline #13246 passed with stage
in 14 minutes and 35 seconds
......@@ -30,7 +30,7 @@
QString BinPlaylist::binPlaylistId = QString("main_bin");
BinPlaylist::BinPlaylist()
: m_binPlaylist(new Mlt::Playlist(pCore->getCurrentProfile()->profile()))
: m_binPlaylist(new Mlt::Playlist(*pCore->getProjectProfile()))
{
m_binPlaylist->set("id", binPlaylistId.toUtf8().constData());
}
......@@ -54,7 +54,7 @@ void BinPlaylist::manageBinItemInsertion(const std::shared_ptr<AbstractProjectIt
m_binPlaylist->append(*clip->originalProducer().get());
} else {
// if clip is not loaded yet, we insert a dummy producer
Mlt::Producer dummy(pCore->getCurrentProfile()->profile(), "color:blue");
Mlt::Producer dummy(*pCore->getProjectProfile(), "color:blue");
dummy.set("kdenlive:id", id.toUtf8().constData());
m_binPlaylist->append(dummy);
}
......
......@@ -763,7 +763,7 @@ std::shared_ptr<Mlt::Producer> ProjectClip::timelineProducer(PlaylistState::Clip
std::shared_ptr<Mlt::Producer> ProjectClip::cloneProducer(bool removeEffects)
{
Mlt::Consumer c(pCore->getCurrentProfile()->profile(), "xml", "string");
Mlt::Consumer c(*pCore->getProjectProfile(), "xml", "string");
Mlt::Service s(m_masterProducer->get_service());
int ignore = s.get_int("ignore_points");
if (ignore) {
......@@ -782,7 +782,7 @@ std::shared_ptr<Mlt::Producer> ProjectClip::cloneProducer(bool removeEffects)
}
const QByteArray clipXml = c.get("string");
std::shared_ptr<Mlt::Producer> prod;
prod.reset(new Mlt::Producer(pCore->getCurrentProfile()->profile(), "xml-string", clipXml.constData()));
prod.reset(new Mlt::Producer(*pCore->getProjectProfile(), "xml-string", clipXml.constData()));
if (strcmp(prod->get("mlt_service"), "avformat") == 0) {
prod->set("mlt_service", "avformat-novalidate");
......
......@@ -133,6 +133,7 @@ void Core::initGUI(const QUrl &Url)
profileChanged();
KdenliveSettings::setDefault_profile(m_profile);
}
updatePreviewProfile();
if (!ProfileRepository::get()->profileExists(m_profile)) {
KMessageBox::sorry(m_mainWindow, i18n("The default profile of Kdenlive is not set or invalid, press OK to set it to a correct value."));
......@@ -310,6 +311,15 @@ std::unique_ptr<ProfileModel> &Core::getCurrentProfile() const
return ProfileRepository::get()->getProfile(m_currentProfile);
}
Mlt::Profile *Core::getProjectProfile()
{
if (!m_previewProfile) {
m_previewProfile = std::make_unique<Mlt::Profile>(m_currentProfile.toStdString().c_str());
updatePreviewProfile();
}
return m_previewProfile.get();
}
const QString &Core::getCurrentProfilePath() const
{
return m_currentProfile;
......@@ -323,12 +333,13 @@ bool Core::setCurrentProfile(const QString &profilePath)
}
if (ProfileRepository::get()->profileExists(profilePath)) {
m_currentProfile = profilePath;
updatePreviewProfile();
m_thumbProfile.reset();
// inform render widget
profileChanged();
m_mainWindow->updateRenderWidgetProfile();
if (m_guiConstructed && m_mainWindow->getCurrentTimeline()->controller()->getModel()) {
m_mainWindow->getCurrentTimeline()->controller()->getModel()->updateProfile(&getCurrentProfile()->profile());
m_mainWindow->getCurrentTimeline()->controller()->getModel()->updateProfile(getProjectProfile());
checkProfileValidity();
}
return true;
......@@ -336,6 +347,26 @@ bool Core::setCurrentProfile(const QString &profilePath)
return false;
}
void Core::updatePreviewProfile()
{
int newWidth = getCurrentProfile()->width() / KdenliveSettings::previewScaling();
int newHeight = getCurrentProfile()->height() / KdenliveSettings::previewScaling();
if (newWidth % 8 > 0) {
newWidth += 8 - newWidth % 8;
}
if (newHeight % 8 > 0) {
newHeight += 8 - newHeight % 8;
}
m_previewProfile->set_colorspace(getCurrentProfile()->colorspace());
m_previewProfile->set_frame_rate(getCurrentProfile()->frame_rate_num(), getCurrentProfile()->frame_rate_den());
m_previewProfile->set_width(newWidth);
m_previewProfile->set_height(newHeight);
m_previewProfile->set_progressive(getCurrentProfile()->progressive());
m_previewProfile->set_sample_aspect(getCurrentProfile()->sample_aspect_num(), getCurrentProfile()->sample_aspect_den());
m_previewProfile->set_display_aspect(getCurrentProfile()->display_aspect_num(), getCurrentProfile()->display_aspect_den());
m_previewProfile->set_explicit(true);
}
void Core::checkProfileValidity()
{
int offset = (getCurrentProfile()->profile().width() % 8) + (getCurrentProfile()->profile().height() % 2);
......
......@@ -35,8 +35,8 @@ class ProjectItemModel;
class ProjectManager;
namespace Mlt {
class Repository;
class Profile;
class Repository;
class Profile;
} // namespace Mlt
#define EXIT_RESTART (42)
......@@ -203,6 +203,9 @@ public:
void processInvalidFilter(const QString service, const QString id, const QString message);
/** @brief Update current project's tags */
void updateProjectTags(QMap <QString, QString> tags);
Mlt::Profile *getProjectProfile();
/** @brief Update MLT's preview profile */
void updatePreviewProfile();
private:
explicit Core();
......@@ -224,12 +227,13 @@ private:
QString m_profile;
std::unique_ptr<Mlt::Profile> m_thumbProfile;
/** @brief Mlt profile used in project / monitors */
std::unique_ptr<Mlt::Profile> m_previewProfile;
bool m_guiConstructed = false;
/** @brief Check that the profile is valid (width is a multiple of 8 and height a multiple of 2 */
void checkProfileValidity();
std::unique_ptr<MediaCapture> m_capture;
QUrl m_mediaCaptureFile;
QMutex m_thumbProfileMutex;
public slots:
......@@ -243,6 +247,7 @@ public slots:
signals:
void coreIsReady();
void updateLibraryPath();
void updateMonitorProfile();
/** @brief Call config dialog on a selected page / tab */
void showConfigDialog(int, int);
void finalizeRecording(const QString &captureFile);
......
......@@ -182,7 +182,7 @@ std::unique_ptr<Mlt::Filter> EffectsRepository::getEffect(const QString &effectI
Q_ASSERT(exists(effectId));
QString service_name = m_assets.at(effectId).mltId;
// We create the Mlt element from its name
auto filter = std::make_unique<Mlt::Filter>(pCore->getCurrentProfile()->profile(), service_name.toLatin1().constData(), nullptr);
auto filter = std::make_unique<Mlt::Filter>(*pCore->getProjectProfile(), service_name.toLatin1().constData(), nullptr);
return filter;
}
......
......@@ -117,7 +117,7 @@ std::shared_ptr<Mlt::Producer> LoadJob::loadResource(QString resource, const QSt
if (!resource.startsWith(type)) {
resource.prepend(type);
}
return std::make_shared<Mlt::Producer>(pCore->getCurrentProfile()->profile(), nullptr, resource.toUtf8().constData());
return std::make_shared<Mlt::Producer>(*pCore->getProjectProfile(), nullptr, resource.toUtf8().constData());
}
std::shared_ptr<Mlt::Producer> LoadJob::loadPlaylist(QString &resource)
......@@ -142,10 +142,10 @@ std::shared_ptr<Mlt::Producer> LoadJob::loadPlaylist(QString &resource)
QString loader = resource;
loader.prepend(QStringLiteral("consumer:"));
pCore->getCurrentProfile()->set_explicit(1);
return std::make_shared<Mlt::Producer>(pCore->getCurrentProfile()->profile(), loader.toUtf8().constData());
return std::make_shared<Mlt::Producer>(*pCore->getProjectProfile(), loader.toUtf8().constData());
}
pCore->getCurrentProfile()->set_explicit(1);
return std::make_shared<Mlt::Producer>(pCore->getCurrentProfile()->profile(), "xml", resource.toUtf8().constData());
return std::make_shared<Mlt::Producer>(*pCore->getProjectProfile(), "xml", resource.toUtf8().constData());
}
void LoadJob::checkProfile(const QString &clipId, const QDomElement &xml, const std::shared_ptr<Mlt::Producer> &producer)
......@@ -198,13 +198,13 @@ void LoadJob::processSlideShow()
int ttl = Xml::getXmlProperty(m_xml, QStringLiteral("ttl")).toInt();
QString anim = Xml::getXmlProperty(m_xml, QStringLiteral("animation"));
if (!anim.isEmpty()) {
auto *filter = new Mlt::Filter(pCore->getCurrentProfile()->profile(), "affine");
auto *filter = new Mlt::Filter(*pCore->getProjectProfile(), "affine");
if ((filter != nullptr) && filter->is_valid()) {
int cycle = ttl;
QString geometry = SlideshowClip::animationToGeometry(anim, cycle);
if (!geometry.isEmpty()) {
if (anim.contains(QStringLiteral("low-pass"))) {
auto *blur = new Mlt::Filter(pCore->getCurrentProfile()->profile(), "boxblur");
auto *blur = new Mlt::Filter(*pCore->getProjectProfile(), "boxblur");
if ((blur != nullptr) && blur->is_valid()) {
m_producer->attach(*blur);
}
......@@ -218,7 +218,7 @@ void LoadJob::processSlideShow()
QString fade = Xml::getXmlProperty(m_xml, QStringLiteral("fade"));
if (fade == QLatin1String("1")) {
// user wants a fade effect to slideshow
auto *filter = new Mlt::Filter(pCore->getCurrentProfile()->profile(), "luma");
auto *filter = new Mlt::Filter(*pCore->getProjectProfile(), "luma");
if ((filter != nullptr) && filter->is_valid()) {
if (ttl != 0) {
filter->set("cycle", ttl);
......@@ -242,7 +242,7 @@ void LoadJob::processSlideShow()
QString crop = Xml::getXmlProperty(m_xml, QStringLiteral("crop"));
if (crop == QLatin1String("1")) {
// user wants to center crop the slides
auto *filter = new Mlt::Filter(pCore->getCurrentProfile()->profile(), "crop");
auto *filter = new Mlt::Filter(*pCore->getProjectProfile(), "crop");
if ((filter != nullptr) && filter->is_valid()) {
filter->set("center", 1);
m_producer->attach(*filter);
......@@ -357,14 +357,14 @@ bool LoadJob::startJob()
break;
}
case ClipType::SlideShow:
m_producer = std::make_shared<Mlt::Producer>(pCore->getCurrentProfile()->profile(), nullptr, m_resource.toUtf8().constData());
m_producer = std::make_shared<Mlt::Producer>(*pCore->getProjectProfile(), nullptr, m_resource.toUtf8().constData());
break;
default:
if (!service.isEmpty()) {
service.append(QChar(':'));
m_producer = loadResource(m_resource, service);
} else {
m_producer = std::make_shared<Mlt::Producer>(pCore->getCurrentProfile()->profile(), nullptr, m_resource.toUtf8().constData());
m_producer = std::make_shared<Mlt::Producer>(*pCore->getProjectProfile(), nullptr, m_resource.toUtf8().constData());
}
break;
}
......
......@@ -779,6 +779,11 @@
<label>Show overlay info on monitor (in / out points, markers,...).</label>
<default>0x05</default>
</entry>
<entry name="previewScaling" type="Int">
<label>Divide monitor resolution by this factor to speedup preview.</label>
<default>1</default>
</entry>
<entry name="clipMonitorOverlayGuides" type="Int">
<label>index of current guides overlay for clip monitor.</label>
......
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<kpartgui name="kdenlive" version="168" translationDomain="kdenlive">
<kpartgui name="kdenlive" version="169" translationDomain="kdenlive">
<MenuBar>
<Menu name="file" >
<Action name="dvd_wizard" />
......@@ -195,6 +195,12 @@
<Action name="monitor_overlay_markers" />
<Action name="monitor_overlay_audiothumb" />
</Menu>
<Menu name="monitor_scaling" ><text>Preview Resolution</text>
<Action name="scale_no_preview" />
<Action name="scale_2_preview" />
<Action name="scale_4_preview" />
<Action name="scale_8_preview" />
</Menu>
<Menu name="monitor_config" ><text>Monitor config</text>
<Action name="mlt_interlace" />
<Action name="mlt_interpolation" />
......
......@@ -1253,6 +1253,48 @@ void MainWindow::setupActions()
overlayAudioInfo->setEnabled(toggled);
});
#if LIBMLT_VERSION_INT >= MLT_VERSION_PREVIEW_SCALE
// Monitor resolution scaling
m_scaleGroup = new QActionGroup(this);
m_scaleGroup->setExclusive(true);
m_scaleGroup->setEnabled(!KdenliveSettings::external_display());
QAction *scale_no = new QAction(i18n("Full Resolution Preview"), m_scaleGroup);
addAction(QStringLiteral("scale_no_preview"), scale_no);
scale_no->setCheckable(true);
scale_no->setData(1);
QAction *scale_2 = new QAction(i18n("1/2 Resolution Preview"), m_scaleGroup);
addAction(QStringLiteral("scale_2_preview"), scale_2);
scale_2->setCheckable(true);
scale_2->setData(2);
QAction *scale_4 = new QAction(i18n("1/4 Resolution Preview"), m_scaleGroup);
addAction(QStringLiteral("scale_4_preview"), scale_4);
scale_4->setCheckable(true);
scale_4->setData(4);
QAction *scale_8 = new QAction(i18n("1/8 Resolution Preview"), m_scaleGroup);
addAction(QStringLiteral("scale_8_preview"), scale_8);
scale_8->setCheckable(true);
scale_8->setData(8);
switch (KdenliveSettings::previewScaling()) {
case 2:
scale_2->setChecked(true);
break;
case 4:
scale_4->setChecked(true);
break;
case 8:
scale_8->setChecked(true);
break;
default:
scale_no->setChecked(true);
break;
}
connect(m_scaleGroup, &QActionGroup::triggered, [this] (QAction *ac) {
int scaling = ac->data().toInt();
KdenliveSettings::setPreviewScaling(scaling);
pCore->monitorManager()->updatePreviewScaling();
});
#endif
QAction *dropFrames = new QAction(QIcon(), i18n("Real Time (drop frames)"), this);
dropFrames->setCheckable(true);
dropFrames->setChecked(KdenliveSettings::monitor_dropframes());
......@@ -2133,7 +2175,10 @@ void MainWindow::slotPreferences(int page, int option)
connect(dialog, &KConfigDialog::settingsChanged, this, &MainWindow::updateConfiguration);
connect(dialog, &KConfigDialog::settingsChanged, this, &MainWindow::configurationChanged);
connect(dialog, &KdenliveSettingsDialog::doResetProfile, pCore->projectManager(), &ProjectManager::slotResetProfiles);
connect(dialog, &KdenliveSettingsDialog::doResetConsumer, pCore->projectManager(), &ProjectManager::slotResetConsumers);
connect(dialog, &KdenliveSettingsDialog::doResetConsumer, [this] (bool fullReset) {
m_scaleGroup->setEnabled(!KdenliveSettings::external_display());
pCore->projectManager()->slotResetConsumers(fullReset);
});
connect(dialog, &KdenliveSettingsDialog::checkTabPosition, this, &MainWindow::slotCheckTabPosition);
connect(dialog, &KdenliveSettingsDialog::restartKdenlive, this, &MainWindow::slotRestart);
connect(dialog, &KdenliveSettingsDialog::updateLibraryFolder, pCore.get(), &Core::updateLibraryPath);
......
......@@ -227,6 +227,7 @@ private:
KToolBar *m_timelineToolBar;
TimelineContainer *m_timelineToolBarContainer;
QLabel *m_trimLabel;
QActionGroup *m_scaleGroup;
/** @brief initialize startup values, return true if first run. */
bool readOptions();
......
......@@ -806,7 +806,7 @@ void ClipController::mirrorOriginalProperties(Mlt::Properties &props)
// This is a proxy, we need to use the real source properties
if (m_properties->get_int("kdenlive:original.backup") == 0) {
// We have a proxy clip, load original source producer
std::shared_ptr<Mlt::Producer> prod = std::make_shared<Mlt::Producer>(pCore->getCurrentProfile()->profile(), nullptr, m_path.toUtf8().constData());
std::shared_ptr<Mlt::Producer> prod = std::make_shared<Mlt::Producer>(*pCore->getProjectProfile(), nullptr, m_path.toUtf8().constData());
// Get frame to make sure we retrieve all original props
std::shared_ptr<Mlt::Frame> fr(prod->get_frame());
if (!prod->is_valid()) {
......@@ -846,7 +846,7 @@ void ClipController::mirrorOriginalProperties(Mlt::Properties &props)
QScopedPointer<Mlt::Producer> tmpProd(nullptr);
if (KdenliveSettings::gpu_accel()) {
QString service = m_masterProducer->get("mlt_service");
tmpProd.reset(new Mlt::Producer(pCore->getCurrentProfile()->profile(), service.toUtf8().constData(), m_masterProducer->get("resource")));
tmpProd.reset(new Mlt::Producer(*pCore->getProjectProfile(), service.toUtf8().constData(), m_masterProducer->get("resource")));
}
std::shared_ptr<Mlt::Frame> fr(tmpProd ? tmpProd->get_frame() : m_masterProducer->get_frame());
mlt_image_format format = mlt_image_none;
......
......@@ -116,7 +116,7 @@ GLWidget::GLWidget(int id, QObject *parent)
m_refreshTimer.setSingleShot(true);
m_refreshTimer.setInterval(50);
m_blackClip.reset(new Mlt::Producer(pCore->getCurrentProfile()->profile(), "color:0"));
m_blackClip.reset(new Mlt::Producer(*pCore->getProjectProfile(), "color:0"));
m_blackClip->set("kdenlive:id", "black");
m_blackClip->set("out", 3);
connect(&m_refreshTimer, &QTimer::timeout, this, &GLWidget::refresh);
......@@ -128,6 +128,7 @@ GLWidget::GLWidget(int id, QObject *parent)
connect(this, &QQuickWindow::sceneGraphInitialized, this, &GLWidget::initializeGL, Qt::DirectConnection);
connect(this, &QQuickWindow::beforeRendering, this, &GLWidget::paintGL, Qt::DirectConnection);
connect(pCore.get(), &Core::updateMonitorProfile, this, &GLWidget::reloadProfile);
registerTimelineItems();
m_proxy = new MonitorProxy(this);
......@@ -454,7 +455,7 @@ bool GLWidget::initGPUAccel()
{
if (!KdenliveSettings::gpu_accel()) return false;
m_glslManager = new Mlt::Filter(pCore->getCurrentProfile()->profile(), "glsl.manager");
m_glslManager = new Mlt::Filter(*pCore->getProjectProfile(), "glsl.manager");
return m_glslManager->is_valid();
}
......@@ -897,6 +898,10 @@ int GLWidget::setProducer(const std::shared_ptr<Mlt::Producer> &producer, bool i
m_consumer->stop();
}
}
if (m_id == Kdenlive::ProjectMonitor) {
// Make sure we apply preview scaling
pCore->updatePreviewProfile();
}
error = reconfigure();
if (error == 0) {
// The profile display aspect ratio may have changed.
......@@ -1036,17 +1041,11 @@ int GLWidget::reconfigureMulti(const QString &params, const QString &path, Mlt::
return -1;
}
int GLWidget::reconfigure(bool reload)
int GLWidget::reconfigure()
{
int error = 0;
// use SDL for audio, OpenGL for video
QString serviceName = property("mlt_service").toString();
if (reload) {
m_blackClip.reset(new Mlt::Producer(pCore->getCurrentProfile()->profile(), "color:0"));
m_blackClip->set("kdenlive:id", "black");
reloadProfile();
return error;
}
if ((m_consumer == nullptr) || !m_consumer->is_valid() || strcmp(m_consumer->get("mlt_service"), "multi") == 0) {
if (m_consumer) {
m_consumer->purge();
......@@ -1056,7 +1055,7 @@ int GLWidget::reconfigure(bool reload)
QString audioBackend = (KdenliveSettings::external_display()) ? QString("decklink:%1").arg(KdenliveSettings::blackmagic_output_device())
: KdenliveSettings::audiobackend();
if (m_consumer == nullptr || serviceName.isEmpty() || serviceName != audioBackend) {
m_consumer.reset(new Mlt::FilteredConsumer(pCore->getCurrentProfile()->profile(), audioBackend.toLatin1().constData()));
m_consumer.reset(new Mlt::FilteredConsumer(*pCore->getProjectProfile(), audioBackend.toLatin1().constData()));
if (m_consumer->is_valid()) {
serviceName = audioBackend;
setProperty("mlt_service", serviceName);
......@@ -1075,7 +1074,7 @@ int GLWidget::reconfigure(bool reload)
// Already tested
continue;
}
m_consumer.reset(new Mlt::FilteredConsumer(pCore->getCurrentProfile()->profile(), bk.toLatin1().constData()));
m_consumer.reset(new Mlt::FilteredConsumer(*pCore->getProjectProfile(), bk.toLatin1().constData()));
if (m_consumer->is_valid()) {
if (audioBackend == KdenliveSettings::sdlAudioBackend()) {
// switch sdl audio backend
......@@ -1120,6 +1119,9 @@ int GLWidget::reconfigure(bool reload)
dropFrames = -dropFrames;
}
m_consumer->set("real_time", dropFrames);
if (KdenliveSettings::previewScaling() > 1) {
m_consumer->set("scale", 1.0 / KdenliveSettings::previewScaling());
}
// C & D
if (m_glslManager) {
if (!m_threadStartEvent) {
......@@ -1170,7 +1172,7 @@ int GLWidget::reconfigure(bool reload)
m_consumer->set("audio_buffer", 512);
#endif
*/
int fps = qRound(pCore->getCurrentProfile()->profile().fps());
int fps = qRound(pCore->getCurrentFps());
m_consumer->set("buffer", qMax(25, fps));
m_consumer->set("prefill", qMax(1, fps / 25));
m_consumer->set("drop_max", fps / 4);
......@@ -1195,11 +1197,17 @@ float GLWidget::zoom() const
void GLWidget::reloadProfile()
{
// The profile display aspect ratio may have changed.
bool existingConsumer = false;
if (m_consumer) {
// Make sure to delete and rebuild consumer to match profile
m_consumer->purge();
m_consumer->stop();
m_consumer.reset();
existingConsumer = true;
}
m_blackClip.reset(new Mlt::Producer(*pCore->getProjectProfile(), "color:0"));
m_blackClip->set("kdenlive:id", "black");
if (existingConsumer) {
reconfigure();
}
resizeGL(width(), height());
......@@ -1270,7 +1278,6 @@ void GLWidget::purgeCache()
}
}
void GLWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
QQuickView::mouseDoubleClickEvent(event);
......@@ -1795,3 +1802,16 @@ void GLWidget::setConsumerProperty(const QString &name, const QString &value)
}
}
}
void GLWidget::updateScaling()
{
#if LIBMLT_VERSION_INT >= MLT_VERSION_PREVIEW_SCALE
bool hasConsumer = m_consumer != nullptr;
if (hasConsumer) {
m_consumer->stop();
m_consumer.reset();
}
pCore->updatePreviewProfile();
reconfigure();
#endif
}
......@@ -37,13 +37,14 @@
#include "kdenlivesettings.h"
#include "scopes/sharedframe.h"
#include <mlt++/MltProfile.h>
class QOpenGLFunctions_3_2_Core;
namespace Mlt {
class Filter;
class Producer;
class Consumer;
class Profile;
} // namespace Mlt
class RenderThread;
......@@ -85,7 +86,7 @@ public:
// TODO: currently unused
int reconfigureMulti(const QString &params, const QString &path, Mlt::Profile *profile);
void stopCapture();
int reconfigure(bool reload = false);
int reconfigure();
/** @brief Get the current MLT producer playlist.
* @return A string describing the playlist */
const QString sceneList(const QString &root, const QString &fullPath = QString());
......@@ -109,7 +110,6 @@ public:
void updateGamma();
/** @brief delete and rebuild consumer, for example when external display is switched */
void resetConsumer(bool fullReset);
void reloadProfile();
void lockMonitor();
void releaseMonitor();
int realTime() const;
......@@ -151,7 +151,6 @@ protected:
QString frameToTime(int frames) const;
public slots:
//void seek(int pos);
void requestSeek(int position);
void setZoom(float zoom);
void setOffsetX(int x, int max);
......@@ -160,6 +159,9 @@ public slots:
void initializeGL();
void releaseAnalyse();
void switchPlay(bool play, double speed = 1.0);
void reloadProfile();
/** @brief Update MLT's consumer scaling */
void updateScaling();
signals:
void frameDisplayed(const SharedFrame &frame);
......
......@@ -161,6 +161,10 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
connect(m_glMonitor->getControllerProxy(), &MonitorProxy::requestSeek, this, &Monitor::processSeek, Qt::DirectConnection);
connect(m_glMonitor->getControllerProxy(), &MonitorProxy::positionChanged, this, &Monitor::slotSeekPosition);
connect(m_glMonitor, &GLWidget::activateMonitor, this, &AbstractMonitor::slotActivateMonitor, Qt::DirectConnection);
connect(manager, &MonitorManager::updatePreviewScaling, [this]() {
m_glMonitor->updateScaling();
refreshMonitorIfActive();
});
m_videoWidget = QWidget::createWindowContainer(qobject_cast<QWindow *>(m_glMonitor));
m_videoWidget->setAcceptDrops(true);
auto *leventEater = new QuickEventEater(this);
......@@ -1771,7 +1775,7 @@ void Monitor::slotSwitchCompare(bool enable)
// Split scene is already active
return;
}
m_splitEffect.reset(new Mlt::Filter(pCore->getCurrentProfile()->profile(), "frei0r.alphagrad"));
m_splitEffect.reset(new Mlt::Filter(*pCore->getProjectProfile(), "frei0r.alphagrad"));
if ((m_splitEffect != nullptr) && m_splitEffect->is_valid()) {
m_splitEffect->set("0", 0.5); // 0 is the Clip left parameter
m_splitEffect->set("1", 0); // 1 is gradient width
......@@ -1823,7 +1827,7 @@ void Monitor::slotSwitchCompare(bool enable)
void Monitor::buildSplitEffect(Mlt::Producer *original)
{
m_splitEffect.reset(new Mlt::Filter(pCore->getCurrentProfile()->profile(), "frei0r.alphagrad"));
m_splitEffect.reset(new Mlt::Filter(*pCore->getProjectProfile(), "frei0r.alphagrad"));
if ((m_splitEffect != nullptr) && m_splitEffect->is_valid()) {
m_splitEffect->set("0", 0.5); // 0 is the Clip left parameter
m_splitEffect->set("1", 0); // 1 is gradient width
......@@ -1834,13 +1838,13 @@ void Monitor::buildSplitEffect(Mlt::Producer *original)
return;
}
QString splitTransition = TransitionsRepository::get()->getCompositingTransition();
Mlt::Transition t(pCore->getCurrentProfile()->profile(), splitTransition.toUtf8().constData());
Mlt::Transition t(*pCore->getProjectProfile(), splitTransition.toUtf8().constData());
if (!t.is_valid()) {
m_splitEffect.reset();
pCore->displayMessage(i18n("The cairoblend transition is required for that feature, please install frei0r and restart Kdenlive"), ErrorMessage);
return;
}
Mlt::Tractor trac(pCore->getCurrentProfile()->profile());
Mlt::Tractor trac(*pCore->getProjectProfile());
std::shared_ptr<Mlt::Producer> clone = ProjectClip::cloneProducer(std::make_shared<Mlt::Producer>(original));
// Delete all effects
int ct = 0;
......
......@@ -638,3 +638,4 @@ void MonitorManager::updateBgColor()
m_clipMonitor->updateBgColor();
}
}
......@@ -157,6 +157,8 @@ signals:
void frameDisplayed(const SharedFrame &);
/** @brief Triggered when the project monitor is paused (used to reset stored audiomixer data */
void cleanMixer();
/** @brief Update monitor preview resolution */
void updatePreviewScaling();
};
#endif
......@@ -443,7 +443,6 @@ bool ProjectManager::checkForBackupFile(const QUrl &url, bool newFile)
stale->open(QIODevice::ReadWrite);
delete stale;
}
return false;
}
......@@ -839,7 +838,7 @@ bool ProjectManager::updateTimeline(int pos, int scrollPos)
}*/
pCore->window()->getMainTimeline()->loading = true;
pCore->window()->slotSwitchTimelineZone(m_project->getDocumentProperty(QStringLiteral("enableTimelineZone")).toInt() == 1);
QScopedPointer<Mlt::Producer> xmlProd(new Mlt::Producer(pCore->getCurrentProfile()->profile(), "xml-string", m_project->getProjectXml().constData()));
QScopedPointer<Mlt::Producer> xmlProd(new Mlt::Producer(*pCore->getProjectProfile(), "xml-string", m_project->getProjectXml().constData()));
Mlt::Service s(*xmlProd);
Mlt::Tractor tractor(s);
if (tractor.count() == 0) {
......@@ -857,7 +856,7 @@ bool ProjectManager::updateTimeline(int pos, int scrollPos)
}
return false;
}
m_mainTimelineModel = TimelineItemModel::construct(&pCore->getCurrentProfile()->profile(), m_project->getGuideModel(), m_project->commandStack());
m_mainTimelineModel = TimelineItemModel::construct(pCore->getProjectProfile(), m_project->getGuideModel(), m_project->commandStack());
pCore->window()->getMainTimeline()->setModel(m_mainTimelineModel, pCore->monitorManager()->projectMonitor()->getControllerProxy());
if (!constructTimelineFromMelt(m_mainTimelineModel, tractor, m_progressDialog)) {
//TODO: act on project load failure
......
......@@ -132,7 +132,7 @@ bool PreviewManager::buildPreviewTrack()
}
// Create overlay track
qDebug() << "/// BUILDING PREVIEW TRACK\n----------------------\n----------------__";
m_previewTrack = new Mlt::Playlist(pCore->getCurrentProfile()->profile());
m_previewTrack = new Mlt::Playlist(*pCore->getProjectProfile());