Commit 91176f62 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle

Merge branch '2008'

parents 60fdc1e9 5d9f20c1
Pipeline #28757 passed with stage
in 11 minutes and 19 seconds
......@@ -3954,7 +3954,9 @@ void Bin::reloadAllProducers(bool reloadThumbs)
ThumbnailCache::get()->invalidateThumbsForClip(clip->clipId(), true);
}
pCore->jobManager()->startJob<ThumbJob>({clip->clipId()}, jobId, QString(), -1, true, true);
pCore->jobManager()->startJob<AudioThumbJob>({clip->clipId()}, jobId, QString());
if (KdenliveSettings::audiothumbnails()) {
pCore->jobManager()->startJob<AudioThumbJob>({clip->clipId()}, jobId, QString());
}
}
}
}
......
......@@ -361,7 +361,9 @@ void ProjectClip::reloadProducer(bool refreshOnly, bool audioStreamChanged, bool
// refresh bin/monitor mini thumb only
discardAudioThumb(true);
}
emit pCore->jobManager()->startJob<AudioThumbJob>({clipId()}, loadjobId, QString());
if (KdenliveSettings::audiothumbnails()) {
emit pCore->jobManager()->startJob<AudioThumbJob>({clipId()}, loadjobId, QString());
}
}
}
}
......
......@@ -709,8 +709,10 @@ bool ProjectItemModel::requestAddBinClip(QString &id, const QDomElement &descrip
int loadJob = emit pCore->jobManager()->startJob<LoadJob>({id}, -1, QString(), description, std::bind(readyCallBack, id));
emit pCore->jobManager()->startJob<ThumbJob>({id}, loadJob, QString(), 0, true);
ClipType::ProducerType type = new_clip->clipType();
if (type == ClipType::AV || type == ClipType::Audio || type == ClipType::Playlist || type == ClipType::Unknown) {
emit pCore->jobManager()->startJob<AudioThumbJob>({id}, loadJob, QString());
if (KdenliveSettings::audiothumbnails()) {
if (type == ClipType::AV || type == ClipType::Audio || type == ClipType::Playlist || type == ClipType::Unknown) {
emit pCore->jobManager()->startJob<AudioThumbJob>({id}, loadJob, QString());
}
}
}
return res;
......@@ -745,7 +747,9 @@ bool ProjectItemModel::requestAddBinClip(QString &id, const std::shared_ptr<Mlt:
if (new_clip->isReady() || new_clip->sourceExists()) {
int blocking = pCore->jobManager()->getBlockingJobId(id, AbstractClipJob::LOADJOB);
emit pCore->jobManager()->startJob<ThumbJob>({id}, blocking, QString(), -1, true);
emit pCore->jobManager()->startJob<AudioThumbJob>({id}, blocking, QString());
if (KdenliveSettings::audiothumbnails()) {
emit pCore->jobManager()->startJob<AudioThumbJob>({id}, blocking, QString());
}
}
}
return res;
......
......@@ -133,6 +133,7 @@ void LayoutManagement::initializeLayouts()
layoutOrder.writeEntry(QString::number(j), entry);
j++;
}
config->reparseConfiguration();
}
for (int i = 1; i < 10; i++) {
QString layoutName;
......@@ -173,7 +174,7 @@ void LayoutManagement::activateLayout(QAbstractButton *button)
if (!button) {
return;
}
loadLayout(button->text());
loadLayout(button->text(), false);
}
void LayoutManagement::slotLoadLayout(QAction *action)
......@@ -186,26 +187,10 @@ void LayoutManagement::slotLoadLayout(QAction *action)
if (layoutId.isEmpty()) {
return;
}
if (loadLayout(layoutId)) {
// Activate layout button
QList<QAbstractButton *>buttons = m_containerGrp->buttons();
bool buttonFound = false;
for (auto *button : buttons) {
if (button->text() == layoutId) {
QSignalBlocker bk(m_containerGrp);
button->setChecked(true);
buttonFound = true;
}
}
if (!buttonFound && m_containerGrp->checkedButton()) {
m_containerGrp->setExclusive(false);
m_containerGrp->checkedButton()->setChecked(false);
m_containerGrp->setExclusive(true);
}
}
loadLayout(layoutId, true);
}
bool LayoutManagement::loadLayout(const QString &layoutId)
bool LayoutManagement::loadLayout(const QString &layoutId, bool selectButton)
{
KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("kdenlive-layoutsrc"));
KConfigGroup layouts(config, "Layouts");
......@@ -221,6 +206,23 @@ bool LayoutManagement::loadLayout(const QString &layoutId)
}
pCore->window()->centralWidget()->setHidden(!timelineVisible);
pCore->window()->restoreState(state);
if (selectButton) {
// Activate layout button
QList<QAbstractButton *>buttons = m_containerGrp->buttons();
bool buttonFound = false;
for (auto *button : buttons) {
if (button->text() == layoutId) {
QSignalBlocker bk(m_containerGrp);
button->setChecked(true);
buttonFound = true;
}
}
if (!buttonFound && m_containerGrp->checkedButton()) {
m_containerGrp->setExclusive(false);
m_containerGrp->checkedButton()->setChecked(false);
m_containerGrp->setExclusive(true);
}
}
return true;
}
......@@ -334,6 +336,15 @@ void LayoutManagement::slotManageLayouts()
currentNames << list.item(i)->data(Qt::UserRole).toString();
}
int pos = 0;
// Reset selected layout if it is a default one
if (list.currentItem()) {
QString selectedName = list.currentItem()->data(Qt::UserRole).toString();
if (defaultLayoutNames.contains(selectedName)) {
layouts.writeEntry(selectedName, defaultLayout.readEntry(selectedName));
}
}
// Re-add missing default layouts
for (const QString &name : defaultLayoutNames) {
if (!currentNames.contains(name)) {
// Insert default layout
......
......@@ -26,6 +26,8 @@ class LayoutManagement : public QObject
public:
explicit LayoutManagement(QObject *parent);
/** @brief Load a layout by its name. */
bool loadLayout(const QString &layoutId, bool selectButton);
private slots:
/** @brief Saves the widget layout. */
......@@ -45,8 +47,6 @@ private:
QHBoxLayout *m_containerLayout;
KSelectAction *m_loadLayout;
QList <QAction *> m_layoutActions;
/** @brief Load a layout by its name. */
bool loadLayout(const QString &layoutId);
};
#endif
......@@ -257,7 +257,7 @@ void MainWindow::init()
fr->setLineWidth(1);
ctnLay->addWidget(fr);
setupActions();
new LayoutManagement(this);
LayoutManagement *layoutManager = new LayoutManagement(this);
QDockWidget *libraryDock = addDock(i18n("Library"), QStringLiteral("library"), pCore->library());
......@@ -511,10 +511,13 @@ void MainWindow::init()
setupGUI(KXmlGuiWindow::ToolBar | KXmlGuiWindow::StatusBar | KXmlGuiWindow::Save | KXmlGuiWindow::Create);
if (firstRun) {
if (QScreen *current = QApplication::primaryScreen()) {
if (current->availableSize().height() < 1000) {
int screenHeight = current->availableSize().height();
if (screenHeight < 1000) {
resize(current->availableSize());
} else if (screenHeight < 2000) {
resize(current->availableSize() / 1.2);
} else {
resize(current->availableSize() / 1.5);
resize(current->availableSize() / 1.6);
}
}
}
......@@ -743,6 +746,9 @@ void MainWindow::init()
KdenliveSettings::setCurrenttmpfolder(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
updateActionsToolTip();
if (firstRun) {
layoutManager->loadLayout(QStringLiteral("Editing"), true);
}
QTimer::singleShot(0, this, &MainWindow::GUISetupDone);
#ifdef USE_JOGSHUTTLE
......
......@@ -342,7 +342,7 @@ static void uploadTextures(QOpenGLContext *context, const SharedFrame &frame, GL
{
int width = frame.get_image_width();
int height = frame.get_image_height();
const uint8_t *image = frame.get_image();
const uint8_t *image = frame.get_image(mlt_image_yuv420p);
QOpenGLFunctions *f = context->functions();
// The planes of pixel data may not be a multiple of the default 4 bytes.
......@@ -420,7 +420,7 @@ bool GLWidget::acquireSharedFrameTextures()
// C & D
m_contextSharedAccess.lock();
if (m_sharedFrame.is_valid()) {
m_texture[0] = *((const GLuint *)m_sharedFrame.get_image());
m_texture[0] = *((const GLuint *)m_sharedFrame.get_image(mlt_image_glsl_texture));
}
}
......@@ -656,9 +656,7 @@ void GLWidget::requestSeek(int position)
if (!qFuzzyIsNull(m_producer->get_speed())) {
m_consumer->purge();
}
if (m_consumer->is_stopped()) {
m_consumer->start();
}
restartConsumer();
m_consumer->set("refresh", 1);
}
......@@ -679,9 +677,7 @@ void GLWidget::refresh()
{
m_refreshTimer.stop();
QMutexLocker locker(&m_mltMutex);
if (m_consumer->is_stopped()) {
m_consumer->start();
}
restartConsumer();
m_consumer->set("refresh", 1);
}
......@@ -1488,10 +1484,6 @@ FrameRenderer::~FrameRenderer()
void FrameRenderer::showFrame(Mlt::Frame frame)
{
int width = 0;
int height = 0;
mlt_image_format format = mlt_image_yuv420p;
frame.get_image(format, width, height);
// Save this frame for future use and to keep a reference to the GL Texture.
m_displayFrame = SharedFrame(frame);
......@@ -1519,12 +1511,6 @@ void FrameRenderer::showFrame(Mlt::Frame frame)
void FrameRenderer::showGLFrame(Mlt::Frame frame)
{
if ((m_context != nullptr) && m_context->isValid()) {
int width = 0;
int height = 0;
frame.set("movit.convert.use_texture", 1);
mlt_image_format format = mlt_image_glsl_texture;
frame.get_image(format, width, height);
m_context->makeCurrent(m_surface);
pipelineSyncToFrame(frame);
......@@ -1543,12 +1529,8 @@ void FrameRenderer::showGLFrame(Mlt::Frame frame)
void FrameRenderer::showGLNoSyncFrame(Mlt::Frame frame)
{
if ((m_context != nullptr) && m_context->isValid()) {
int width = 0;
int height = 0;
frame.set("movit.convert.use_texture", 1);
mlt_image_format format = mlt_image_glsl_texture;
frame.get_image(format, width, height);
m_context->makeCurrent(m_surface);
m_context->functions()->glFinish();
......@@ -1655,9 +1637,7 @@ bool GLWidget::playZone(bool loop)
m_consumer->purge();
m_producer->set("out", m_proxy->zoneOut());
m_producer->set_speed(1.0);
if (m_consumer->is_stopped()) {
m_consumer->start();
}
restartConsumer();
m_consumer->set("scrub_audio", 0);
m_consumer->set("refresh", 1);
m_isZoneMode = true;
......@@ -1665,6 +1645,23 @@ bool GLWidget::playZone(bool loop)
return true;
}
bool GLWidget::restartConsumer()
{
int result = 0;
if (m_consumer->is_stopped()) {
// When restarting the consumer, we need to restore the preview scaling
int cWidth = m_consumer->get_int("width");
int cHeigth = m_consumer->get_int("height");
result = m_consumer->start();
if (cWidth > 0) {
m_consumer->set("width", cWidth);
m_consumer->set("height", cHeigth);
}
}
return result != -1;
}
bool GLWidget::loopClip(QPoint inOut)
{
if (!m_producer || inOut.y() <= inOut.x()) {
......@@ -1677,9 +1674,7 @@ bool GLWidget::loopClip(QPoint inOut)
m_consumer->purge();
m_producer->set("out", inOut.y());
m_producer->set_speed(1.0);
if (m_consumer->is_stopped()) {
m_consumer->start();
}
restartConsumer();
m_consumer->set("scrub_audio", 0);
m_consumer->set("refresh", 1);
m_isZoneMode = false;
......@@ -1722,7 +1717,7 @@ void GLWidget::startConsumer()
if (m_consumer == nullptr) {
return;
}
if (m_consumer->is_stopped() && m_consumer->start() == -1) {
if (!restartConsumer()) {
// ARGH CONSUMER BROKEN!!!!
KMessageBox::error(
qApp->activeWindow(),
......
......@@ -242,6 +242,8 @@ private:
QOpenGLFramebufferObject *m_fbo;
void refreshSceneLayout();
void resetZoneMode();
/** @brief Restart consumer, keeping preview scaling settings */
bool restartConsumer();
/* OpenGL context management. Interfaces to MLT according to the configured render pipeline.
*/
......
......@@ -16,6 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sharedframe.h"
#include <mutex>
void destroyFrame(void* p)
{
delete static_cast<Mlt::Frame*>(p);
}
class FrameData : public QSharedData
{
......@@ -31,6 +37,7 @@ public:
~FrameData() = default;
Mlt::Frame f;
std::mutex m;
private:
Q_DISABLE_COPY(FrameData)
......@@ -164,12 +171,54 @@ int SharedFrame::get_image_height() const
return d->f.get_int("height");
}
const uint8_t *SharedFrame::get_image() const
const uint8_t *SharedFrame::get_image(mlt_image_format format) const
{
mlt_image_format format = get_image_format();
mlt_image_format native_format = get_image_format();
int width = get_image_width();
int height = get_image_height();
return (uint8_t *)d->f.get_image(format, width, height, 0);
uint8_t* image = nullptr;
if (format == mlt_image_none) {
format = native_format;
}
if (format == native_format) {
// Native format is requested. Return frame image.
image = (uint8_t*)d->f.get_image(format, width, height, 0);
} else {
// Non-native format is requested. Return a cached converted image.
const char* formatName = mlt_image_format_name( format );
// Convert to non-const so that the cache can be accessed/modified while
// under lock.
FrameData* nonConstData = const_cast<FrameData*>(d.data());
nonConstData->m.lock();
Mlt::Frame* cacheFrame = static_cast<Mlt::Frame*>(nonConstData->f.get_data(formatName));
if (cacheFrame == nullptr) {
// A cached image does not exist, create one.
// Make a non-deep clone of the frame (including convert function)
mlt_frame cloneFrame = mlt_frame_clone(nonConstData->f.get_frame(), 0);
cloneFrame->convert_image = nonConstData->f.get_frame()->convert_image;
// Create a new cache frame
cacheFrame = new Mlt::Frame(cloneFrame);
// Release the reference on the clone
// (now it is owned by the cache frame)
mlt_frame_close( cloneFrame );
// Save the cache frame as a property under the name of the image
// format for later use.
nonConstData->f.set(formatName, static_cast<void*>(cacheFrame), 0, destroyFrame);
// Break a circular reference
cacheFrame->clear("_cloned_frame");
}
// Get the image from the cache frame.
// This will cause a conversion if it was just created.
image = (uint8_t*)cacheFrame->get_image(format, width, height, 0);
nonConstData->m.unlock();
}
return image;
}
mlt_audio_format SharedFrame::get_audio_format() const
......
......@@ -63,7 +63,7 @@ public:
mlt_image_format get_image_format() const;
int get_image_width() const;
int get_image_height() const;
const uint8_t *get_image() const;
const uint8_t *get_image(mlt_image_format format) const;
mlt_audio_format get_audio_format() const;
int get_audio_channels() const;
int get_audio_frequency() const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment