From bd5516fb41619cf454a4018a3cff911e2305fefb Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Fri, 5 Jan 2024 14:10:18 +0100 Subject: [PATCH] Refactor video wizard into a single wizard --- ScreenPlay/CMakeLists.txt | 9 +- ScreenPlay/inc/public/ScreenPlay/create.h | 40 +- .../inc/public/ScreenPlay/createimportvideo.h | 12 +- .../public/ScreenPlay/installedlistmodel.h | 2 - ScreenPlay/qml/Create/CreateSidebar.qml | 27 +- .../ImportVideoAndConvert/CreateWallpaper.qml | 25 +- .../CreateWallpaperFileSelect.qml} | 61 +-- ...erInit.qml => CreateWallpaperSettings.qml} | 36 +- .../CreateWallpaperVideoImportConvert.qml | 11 +- .../Create/Wizards/ImportWebm/ImportWebm.qml | 39 -- .../Wizards/ImportWebm/ImportWebmConvert.qml | 373 ----------------- .../Wizards/ImportWebm/ImportWebmInit.qml | 158 -------- .../Create/Wizards/Importh264/Importh264.qml | 39 -- .../Wizards/Importh264/Importh264Convert.qml | 374 ------------------ ScreenPlay/qml/Installed/Sidebar.qml | 39 +- ScreenPlay/src/create.cpp | 138 ++----- ScreenPlay/src/createimportvideo.cpp | 126 +++--- .../inc/public/ScreenPlayUtil/contenttypes.h | 3 - ScreenPlayUtil/qml/Slider.qml | 4 +- 19 files changed, 231 insertions(+), 1285 deletions(-) rename ScreenPlay/qml/Create/Wizards/{Importh264/Importh264Init.qml => ImportVideoAndConvert/CreateWallpaperFileSelect.qml} (62%) rename ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/{CreateWallpaperInit.qml => CreateWallpaperSettings.qml} (74%) delete mode 100644 ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml delete mode 100644 ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml delete mode 100644 ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml delete mode 100644 ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml delete mode 100644 ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index cf2b1309..8511d3a0 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -64,16 +64,11 @@ set(QML qml/Create/Wizards/GodotWallpaper.qml qml/Create/Wizards/HTMLWallpaper.qml qml/Create/Wizards/HTMLWidget.qml - qml/Create/Wizards/Importh264/Importh264.qml - qml/Create/Wizards/Importh264/Importh264Convert.qml - qml/Create/Wizards/Importh264/Importh264Init.qml qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml - qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml + qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperFileSelect.qml + qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperSettings.qml qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml - qml/Create/Wizards/ImportWebm/ImportWebm.qml - qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml - qml/Create/Wizards/ImportWebm/ImportWebmInit.qml qml/Create/Wizards/QMLWallpaper.qml qml/Create/Wizards/QMLWidget.qml qml/Create/Wizards/WebsiteWallpaper.qml diff --git a/ScreenPlay/inc/public/ScreenPlay/create.h b/ScreenPlay/inc/public/ScreenPlay/create.h index 26caa8d7..6d7c539b 100644 --- a/ScreenPlay/inc/public/ScreenPlay/create.h +++ b/ScreenPlay/inc/public/ScreenPlay/create.h @@ -34,7 +34,6 @@ class Create : public QObject { Q_OBJECT QML_ELEMENT QML_UNCREATABLE("") - Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") Q_PROPERTY(QString workingDir READ workingDir WRITE setWorkingDir NOTIFY workingDirChanged) Q_PROPERTY(float progress READ progress WRITE setProgress NOTIFY progressChanged) @@ -45,13 +44,22 @@ public: Create(); - enum class VideoCodec { - VP8, - VP9, - AV1, - H264 - }; - Q_ENUM(VideoCodec) + Q_INVOKABLE void cancel(); + + Q_INVOKABLE void createWallpaperStart( + QString videoPath, + ScreenPlay::Video::VideoCodec codec, + const int quality = 50); + + Q_INVOKABLE void saveWallpaper(const QString title, + const QString description, + QString filePath, + QString previewImagePath, + const QString youtube, + const ScreenPlay::Video::VideoCodec codec, + const QVector tags); + + Q_INVOKABLE void abortAndCleanup(); float progress() const { return m_progress; } QString workingDir() const { return m_workingDir; } @@ -68,22 +76,6 @@ signals: void finished(); public slots: - void cancel(); - - void createWallpaperStart(QString videoPath, Create::VideoCodec codec = Create::VideoCodec::VP9, const int quality = 50); - - void importH264(QString videoPath); - - void saveWallpaper(const QString title, - const QString description, - QString filePath, - QString previewImagePath, - const QString youtube, - const ScreenPlay::Create::VideoCodec codec, - const QVector tags); - - void abortAndCleanup(); - void setProgress(float progress) { if (qFuzzyCompare(m_progress, progress)) diff --git a/ScreenPlay/inc/public/ScreenPlay/createimportvideo.h b/ScreenPlay/inc/public/ScreenPlay/createimportvideo.h index da255051..1eb111b3 100644 --- a/ScreenPlay/inc/public/ScreenPlay/createimportvideo.h +++ b/ScreenPlay/inc/public/ScreenPlay/createimportvideo.h @@ -19,6 +19,7 @@ #include #include "ScreenPlay/createimportstates.h" +#include "ScreenPlayUtil/contenttypes.h" namespace ScreenPlay { @@ -30,8 +31,12 @@ class CreateImportVideo : public QObject { Q_PROPERTY(float progress READ progress WRITE setProgress NOTIFY progressChanged) public: - explicit CreateImportVideo(const QString& videoPath, const QString& exportPath, const QString& codec, const int quality, std::atomic& interrupt); - explicit CreateImportVideo(const QString& videoPath, const QString& exportPath, std::atomic& interrupt); + explicit CreateImportVideo( + const QString& videoPath, + const QString& exportPath, + const ScreenPlay::Video::VideoCodec targetCodec, + const int quality, + std::atomic& interrupt); enum class Executable { FFMPEG, @@ -50,7 +55,8 @@ public: QString m_videoPath; QString m_exportPath; QString m_format; - QString m_codec; + Video::VideoCodec m_targetCodec; + Video::VideoCodec m_sourceCodec; const int m_quality = 50; int m_numberOfFrames { 0 }; diff --git a/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h b/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h index 274cc481..56cef13a 100644 --- a/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h +++ b/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h @@ -23,10 +23,8 @@ #include #include "ScreenPlay/globalvariables.h" -#include "ScreenPlay/profilelistmodel.h" #include "ScreenPlay/settings.h" #include "ScreenPlayUtil/projectfile.h" -#include "ScreenPlayUtil/util.h" #include diff --git a/ScreenPlay/qml/Create/CreateSidebar.qml b/ScreenPlay/qml/Create/CreateSidebar.qml index a7b3ac8e..d76ecb42 100644 --- a/ScreenPlay/qml/Create/CreateSidebar.qml +++ b/ScreenPlay/qml/Create/CreateSidebar.qml @@ -17,7 +17,7 @@ Rectangle { property alias model: listView.model property StackView stackView - width: 380 + width: 340 state: expanded ? "" : "inactive" layer.enabled: true Component.onCompleted: expanded = true @@ -56,19 +56,7 @@ Rectangle { } ListElement { - headline: qsTr("Video Import h264 (.mp4)") - source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/Importh264/Importh264.qml" - category: "Video Wallpaper" - } - - ListElement { - headline: qsTr("Video Import VP8 & VP9 (.webm)") - source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/ImportWebm/ImportWebm.qml" - category: "Video Wallpaper" - } - - ListElement { - headline: qsTr("Video import (all types)") + headline: qsTr("Import Video") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml" category: "Video Wallpaper" objectName: "videoImportConvert" @@ -83,25 +71,25 @@ Rectangle { ListElement { headline: qsTr("3D Engine Wallpaper (Godot 4.2)") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/GodotWallpaper.qml" - category: "3D Engine & Code Wallpaper" + category: "3D Engine & \nCode Wallpaper" } ListElement { headline: qsTr("QML Wallpaper") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/QMLWallpaper.qml" - category: "3D Engine & Code Wallpaper" + category: "3D Engine & \nCode Wallpaper" } ListElement { headline: qsTr("HTML5 Wallpaper") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/HTMLWallpaper.qml" - category: "3D Engine & Code Wallpaper" + category: "3D Engine & \nCode Wallpaper" } ListElement { headline: qsTr("Website Wallpaper") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/WebsiteWallpaper.qml" - category: "3D Engine & Code Wallpaper" + category: "3D Engine & \nCode Wallpaper" } ListElement { @@ -123,9 +111,10 @@ Rectangle { } section.delegate: Item { - height: 60 + height: headline.contentHeight + 20 Text { + id:headline font.pointSize: 18 color: Material.primaryTextColor text: section diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml index c3d6ee8e..52b5e715 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml @@ -19,18 +19,20 @@ Item { anchors.fill: parent interactive: false clip: true - - CreateWallpaperInit { - onNext: function (filePath, codec) { - startConvert(filePath, codec); + CreateWallpaperFileSelect { + onNext: function (filePath) { + createWallpaperVideoImportConvert.filePath = filePath + swipeView.currentIndex = 1 } + } - function startConvert(filePath, codec) { - root.wizardStarted(); - swipeView.currentIndex = 1; - createWallpaperVideoImportConvert.codec = codec; - createWallpaperVideoImportConvert.filePath = filePath; - App.create.createWallpaperStart(filePath, codec, quality); + CreateWallpaperSettings { + id: createWallpaperSettings + onNext: function (codec,quality) { + root.wizardStarted() + swipeView.currentIndex = 2 + createWallpaperVideoImportConvert.codec = codec + App.create.createWallpaperStart(createWallpaperVideoImportConvert.filePath, codec, quality) } } @@ -40,7 +42,6 @@ Item { onAbort: root.wizardExited() } - CreateWallpaperResult { - } + CreateWallpaperResult {} } } diff --git a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Init.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperFileSelect.qml similarity index 62% rename from ScreenPlay/qml/Create/Wizards/Importh264/Importh264Init.qml rename to ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperFileSelect.qml index c0156117..f3bb0164 100644 --- a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Init.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperFileSelect.qml @@ -11,6 +11,7 @@ import "../../" Item { id: root + property var allowedVideoFileEndings: ["*.webm", "*.mkv", "*.mp4", "*.mpg", "*.mp2", "*.mpeg", "*.ogv", "*.avi", "*.wmv", "*.m4v", "*.3gp"] signal next(var filePath) @@ -29,7 +30,7 @@ Item { Util.Headline { Layout.fillWidth: true - text: qsTr("Import a .mp4 video") + text: qsTr("Import Video Wallpaper") } RowLayout { @@ -42,37 +43,37 @@ Item { Layout.fillHeight: true spacing: 40 - Text { - id: txtDescription - - text: qsTr("ScreenPlay v0.15 and up can play *.mp4 (also more known as h264). This can improove performance on older systems.") - color: Material.primaryTextColor - Layout.fillWidth: true - font.pointSize: 13 - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - font.family: App.settings.font - } - DropArea { id: dropArea Layout.fillHeight: true Layout.fillWidth: true onExited: { - bg.color = Qt.darker(Material.backgroundColor); - } - onEntered: { - bg.color = Qt.darker(Qt.darker(Material.backgroundColor)); - drag.accept(Qt.LinkAction); - } - onDropped: { - let file = App.util.toLocal(drop.urls[0]); - bg.color = Qt.darker(Qt.darker(Material.backgroundColor)); - if (file.endsWith(".mp4")) - root.next(drop.urls[0]); - else - txtFile.text = qsTr("Invalid file type. Must be valid h264 (*.mp4)!"); + bg.color = Qt.darker(Material.backgroundColor) } + onEntered: drag => { + bg.color = Qt.darker( + Qt.darker(Material.backgroundColor)) + drag.accept(Qt.LinkAction) + } + onDropped: drop => { + let file = App.util.toLocal(drop.urls[0]) + bg.color = Qt.darker( + Qt.darker(Material.backgroundColor)) + let found = false + for (let ending in root.allowedVideoFileEndings) { + if (file.endsWith(ending)) { + found = true + break + } + } + if (found) { + root.next(drop.urls[0]) + } else { + txtFile.text = qsTr( + "Invalid file type. Must be valid video!") + } + } Rectangle { id: bg @@ -94,7 +95,8 @@ Item { Text { id: txtFile - text: qsTr("Drop a *.mp4 file here or use 'Select file' below.") + text: qsTr("Drag and drop your video here. Supported video formats are:\n\n%1").arg( + root.allowedVideoFileEndings.join(" ")) wrapMode: Text.WrapAtWordBoundaryOrAnywhere color: Material.primaryTextColor font.pointSize: 13 @@ -123,7 +125,8 @@ Item { icon.width: 16 icon.height: 16 font.family: App.settings.font - onClicked: Qt.openUrlExternally("https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance") + onClicked: Qt.openUrlExternally( + "https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance") anchors { bottom: parent.bottom @@ -137,7 +140,7 @@ Item { highlighted: true font.family: App.settings.font onClicked: { - fileDialogImportVideo.open(); + fileDialogImportVideo.open() } FileDialog { @@ -145,7 +148,7 @@ Item { nameFilters: ["Video files (*.mp4)"] onAccepted: { - root.next(fileDialogImportVideo.currentFile); + root.next(fileDialogImportVideo.currentFile) } } diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperSettings.qml similarity index 74% rename from ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml rename to ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperSettings.qml index c778401c..789efd81 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperSettings.qml @@ -14,7 +14,7 @@ Item { property int quality: sliderQuality.slider.value - signal next(var filePath, var codec) + signal next(var codec, var quality) ColumnLayout { spacing: 40 @@ -29,14 +29,13 @@ Item { Util.Headline { Layout.alignment: Qt.AlignTop Layout.fillWidth: true - text: qsTr("Import any video type") + text: qsTr("Import Video Wallpaper - Select Codec") } Text { id: txtDescription - text: qsTr("Depending on your PC configuration it is better to convert your wallpaper to a specific video codec. If both have bad performance you can also try a QML wallpaper! Supported video formats are: \n -*.mp4 *.mpg *.mp2 *.mpeg *.ogv *.avi *.wmv *.m4v *.3gp *.flv") + text: qsTr("Depending on your PC configuration it is better to convert your wallpaper to a specific video codec. We skip encoding if the input format matches the ouput format.") color: Material.primaryTextColor Layout.fillWidth: true font.pointSize: 13 @@ -63,11 +62,15 @@ Item { Layout.preferredWidth: 400 textRole: "text" valueRole: "value" - currentIndex: 1 + currentIndex: 0 font.family: App.settings.font model: ListModel { id: model + ListElement { + text: "✨h.264 (Better for all hardware)" + value: Util.Video.VideoCodec.H264 + } ListElement { text: "VP8 (Better for older hardware)" @@ -86,7 +89,7 @@ Item { id: sliderQuality iconSource: "qrc:/qml/ScreenPlayApp/assets/icons/icon_settings.svg" - headline: qsTr("Quality slider. Lower value means better quality.") + headline: qsTr("Set video quality. Lower value means better quality.") Layout.preferredWidth: 400 slider { @@ -107,7 +110,8 @@ Item { icon.width: 16 icon.height: 16 font.family: App.settings.font - onClicked: Qt.openUrlExternally("https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance") + onClicked: Qt.openUrlExternally( + "https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance") anchors { bottom: parent.bottom @@ -116,23 +120,15 @@ Item { } Button { - objectName: "createWallpaperInitFileSelectButton" - text: qsTr("Select file") + objectName: "createWallpaperStartImportButton" + text: qsTr("Start import") highlighted: true font.family: App.settings.font onClicked: { - fileDialogImportVideo.open(); + let a = Util.Video.VideoCodec.H264 + let targetCodec = comboBoxCodec.currentValue + root.next(a, sliderQuality.slider.value) } - - FileDialog { - id: fileDialogImportVideo - - nameFilters: ["Video files (*.mp4 *.mpg *.mp2 *.mpeg *.ogv *.avi *.wmv *.m4v *.3gp *.flv)"] - onAccepted: { - root.next(fileDialogImportVideo.currentFile, model.get(comboBoxCodec.currentIndex).value); - } - } - anchors { right: parent.right bottom: parent.bottom diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml index 9f16675b..7c2cebcd 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml @@ -12,7 +12,7 @@ Item { property bool conversionFinishedSuccessful: false property bool canSave: false - property var codec: Create.VP8 + property var codec: Util.Video.VideoCodec.H264 property string filePath signal abort @@ -335,7 +335,14 @@ Item { onClicked: { if (conversionFinishedSuccessful) { btnSave.enabled = false; - App.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, codec, textFieldTags.getTags()); + App.create.saveWallpaper( + textFieldName.text, + textFieldDescription.text, + root.filePath, + previewSelector.imageSource, + textFieldYoutubeURL.text, + root.codec, + textFieldTags.getTags()); savePopup.open(); } } diff --git a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml deleted file mode 100644 index 81ad6c4c..00000000 --- a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml +++ /dev/null @@ -1,39 +0,0 @@ -import QtQuick -import Qt5Compat.GraphicalEffects -import QtQuick.Controls -import QtQuick.Controls.Material -import QtQuick.Layouts -import ScreenPlayApp -import ScreenPlay - -Item { - id: root - - signal wizardStarted - signal wizardExited - signal next - - SwipeView { - id: swipeView - - anchors.fill: parent - interactive: false - clip: true - - ImportWebmInit { - onNext: function (filePath) { - root.wizardStarted(); - swipeView.currentIndex = 1; - createWallpaperVideoImportConvert.filePath = filePath; - App.util.setNavigationActive(false); - App.create.createWallpaperStart(filePath); - } - } - - ImportWebmConvert { - id: createWallpaperVideoImportConvert - - onExit: root.wizardExited() - } - } -} diff --git a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml deleted file mode 100644 index 83373dd9..00000000 --- a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml +++ /dev/null @@ -1,373 +0,0 @@ -import QtQuick -import Qt5Compat.GraphicalEffects -import QtQuick.Controls -import QtQuick.Controls.Material -import QtQuick.Layouts -import ScreenPlayApp -import ScreenPlay -import ScreenPlayUtil as Util - -Item { - id: root - - property bool conversionFinishedSuccessful: false - property bool canSave: false - property string filePath - - signal exit - signal save - - function basename(str) { - let filenameWithExtentions = (str.slice(str.lastIndexOf("/") + 1)); - let filename = filenameWithExtentions.split('.').slice(0, -1).join('.'); - return filename; - } - - function checkCanSave() { - if (canSave && conversionFinishedSuccessful) - btnSave.enabled = true; - else - btnSave.enabled = false; - } - - onCanSaveChanged: root.checkCanSave() - onFilePathChanged: { - textFieldName.text = basename(filePath); - } - - Connections { - function onCreateWallpaperStateChanged(state) { - switch (state) { - case Import.State.AnalyseVideo: - txtConvert.text = qsTr("AnalyseVideo..."); - break; - case Import.State.ConvertingPreviewImage: - txtConvert.text = qsTr("Generating preview image..."); - break; - case Import.State.ConvertingPreviewThumbnailImage: - txtConvert.text = qsTr("Generating preview thumbnail image..."); - break; - case Import.State.ConvertingPreviewImageFinished: - imgPreview.source = "file:///" + App.create.workingDir + "/preview.jpg"; - imgPreview.visible = true; - break; - case Import.State.ConvertingPreviewVideo: - txtConvert.text = qsTr("Generating 5 second preview video..."); - break; - case Import.State.ConvertingPreviewGif: - txtConvert.text = qsTr("Generating preview gif..."); - break; - case Import.State.ConvertingPreviewGifFinished: - gifPreview.source = "file:///" + App.create.workingDir + "/preview.gif"; - imgPreview.visible = false; - gifPreview.visible = true; - gifPreview.playing = true; - break; - case Import.State.ConvertingAudio: - txtConvert.text = qsTr("Converting Audio..."); - break; - case Import.State.ConvertingVideo: - txtConvert.text = qsTr("Converting Video... This can take some time!"); - break; - case Import.State.ConvertingVideoError: - txtConvert.text = qsTr("Converting Video ERROR!"); - break; - case Import.State.AnalyseVideoError: - txtConvert.text = qsTr("Analyse Video ERROR!"); - break; - case Import.State.Finished: - txtConvert.text = ""; - conversionFinishedSuccessful = true; - busyIndicator.running = false; - btnExit.enabled = false; - root.checkCanSave(); - break; - } - } - - function onProgressChanged(progress) { - var percentage = Math.floor(progress * 100); - if (percentage > 100 || progress > 0.95) - percentage = 100; - if (percentage === NaN) - print(progress, percentage); - txtConvertNumber.text = percentage + "%"; - } - - target: App.create - } - - Util.Headline { - id: txtHeadline - - text: qsTr("Import a video to a wallpaper") - - anchors { - top: parent.top - left: parent.left - margins: 40 - bottomMargin: 0 - } - } - - Item { - id: wrapperLeft - - width: parent.width * 0.66 - - anchors { - left: parent.left - top: txtHeadline.bottom - margins: 30 - bottom: parent.bottom - } - - Rectangle { - id: imgWrapper - - color: Material.color(Material.Grey) - - anchors { - top: parent.top - right: parent.right - rightMargin: 20 - bottom: previewSelector.top - bottomMargin: 20 - left: parent.left - } - - Image { - id: imgPreview - - fillMode: Image.PreserveAspectCrop - asynchronous: true - visible: false - anchors.fill: parent - } - - AnimatedImage { - id: gifPreview - - fillMode: Image.PreserveAspectCrop - asynchronous: true - playing: true - visible: false - anchors.fill: parent - } - - Rectangle { - id: shadow - anchors.fill: parent - gradient: Gradient { - GradientStop { - id: gradientStop0 - position: 1 - color: "#DD000000" - } - - GradientStop { - id: gradientStop1 - position: 0 - color: "#00000000" - } - } - } - - BusyIndicator { - id: busyIndicator - - anchors.centerIn: parent - running: true - } - - Text { - id: txtConvertNumber - - color: "white" - font.pointSize: 21 - font.family: App.settings.font - - anchors { - horizontalCenter: parent.horizontalCenter - bottom: parent.bottom - bottomMargin: 40 - } - } - - Text { - id: txtConvert - - color: Material.secondaryTextColor - text: qsTr("Generating preview video...") - font.pointSize: 14 - font.family: App.settings.font - - anchors { - horizontalCenter: parent.horizontalCenter - bottom: parent.bottom - bottomMargin: 20 - } - } - } - - Util.ImageSelector { - id: previewSelector - - height: 80 - - anchors { - right: parent.right - rightMargin: 20 - left: parent.left - bottom: parent.bottom - } - } - } - - Item { - id: wrapperRight - - width: parent.width * 0.33 - - anchors { - top: txtHeadline.bottom - topMargin: 30 - bottom: parent.bottom - right: parent.right - } - - ColumnLayout { - id: column - - spacing: 0 - - anchors { - right: parent.right - left: parent.left - margins: 30 - top: parent.top - topMargin: 0 - bottom: column1.top - bottomMargin: 50 - } - - Util.TextField { - id: textFieldName - - placeholderText: qsTr("Name (required!)") - width: parent.width - Layout.fillWidth: true - onTextChanged: { - if (textFieldName.text.length >= 3) - canSave = true; - else - canSave = false; - } - } - - Util.TextField { - id: textFieldDescription - - placeholderText: qsTr("Description") - width: parent.width - Layout.fillWidth: true - } - - Util.TextField { - id: textFieldYoutubeURL - - placeholderText: qsTr("Youtube URL") - width: parent.width - Layout.fillWidth: true - } - - Util.TagSelector { - id: textFieldTags - - width: parent.width - Layout.fillWidth: true - } - } - - Row { - id: column1 - - height: 80 - width: childrenRect.width - spacing: 10 - - anchors { - right: parent.right - rightMargin: 30 - bottomMargin: -10 - bottom: parent.bottom - } - - Button { - id: btnExit - - text: qsTr("Abort") - Material.accent: Material.color(Material.Red) - highlighted: true - font.family: App.settings.font - onClicked: { - root.exit(); - App.create.cancel(); - } - } - - Button { - id: btnSave - objectName: "btnSave" - text: qsTr("Save") - enabled: false - Material.background: Material.accent - Material.foreground: "white" - font.family: App.settings.font - onClicked: { - if (conversionFinishedSuccessful) { - btnSave.enabled = false; - App.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, Util.Video.VideoCodec.VP9, textFieldTags.getTags()); - savePopup.open(); - } - } - } - } - } - - Popup { - id: savePopup - - modal: true - focus: true - width: 250 - anchors.centerIn: parent - height: 200 - onOpened: timerSave.start() - - BusyIndicator { - anchors.centerIn: parent - running: true - } - - Text { - text: qsTr("Save Wallpaper...") - color: Material.primaryTextColor - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - anchors.bottomMargin: 30 - font.family: App.settings.font - } - - Timer { - id: timerSave - - interval: 1000 + Math.random() * 1000 - onTriggered: { - savePopup.close(); - App.util.setNavigationActive(true); - root.exit(); - } - } - } -} diff --git a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml deleted file mode 100644 index a5b2477d..00000000 --- a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml +++ /dev/null @@ -1,158 +0,0 @@ -import QtQuick -import Qt5Compat.GraphicalEffects -import QtQuick.Controls -import QtQuick.Controls.Material -import QtQuick.Layouts -import QtQuick.Dialogs -import ScreenPlayApp -import ScreenPlay -import ScreenPlayUtil as Util -import "../../" - -Item { - id: root - - signal next(var filePath) - - ColumnLayout { - id: wrapper - - spacing: 40 - - anchors { - top: parent.top - bottom: btnOpenDocs.top - left: parent.left - right: parent.right - margins: 20 - } - - Util.Headline { - Layout.fillWidth: true - text: qsTr("Import a .webm video") - } - - RowLayout { - Layout.fillHeight: true - Layout.fillWidth: true - spacing: 40 - - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - spacing: 40 - - Text { - id: txtDescription - - text: qsTr("When importing webm we can skip the long conversion. When you get unsatisfying results with the ScreenPlay importer from 'ideo import and convert (all types)' you can also convert via the free and open source HandBrake!") - color: Material.primaryTextColor - Layout.fillWidth: true - font.pointSize: 13 - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - font.family: App.settings.font - } - - DropArea { - id: dropArea - - Layout.fillHeight: true - Layout.fillWidth: true - onExited: { - bg.color = Qt.darker(Material.backgroundColor); - } - onEntered: { - bg.color = Qt.darker(Qt.darker(Material.backgroundColor)); - drag.accept(Qt.LinkAction); - } - onDropped: { - let file = App.util.toLocal(drop.urls[0]); - bg.color = Qt.darker(Qt.darker(Material.backgroundColor)); - if (file.endsWith(".webm")) - root.next(drop.urls[0]); - else - txtFile.text = qsTr("Invalid file type. Must be valid VP8 or VP9 (*.webm)!"); - } - - Rectangle { - id: bg - - anchors.fill: parent - radius: 3 - color: Qt.darker(Material.backgroundColor) - } - - Image { - id: bgPattern - - anchors.fill: parent - fillMode: Image.Tile - opacity: 0.2 - source: "qrc:/qml/ScreenPlayApp/assets/images/noisy-texture-3.png" - } - - Text { - id: txtFile - - text: qsTr("Drop a *.webm file here or use 'Select file' below.") - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - color: Material.primaryTextColor - font.pointSize: 13 - horizontalAlignment: Qt.AlignHCenter - verticalAlignment: Qt.AlignVCenter - font.family: App.settings.font - - anchors { - fill: parent - margins: 40 - } - } - } - } - } - } - - Button { - id: btnOpenDocs - - text: qsTr("Open Documentation") - Material.accent: Material.color(Material.LightGreen) - highlighted: true - icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_document.svg" - icon.color: "white" - icon.width: 16 - icon.height: 16 - font.family: App.settings.font - onClicked: Qt.openUrlExternally("https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance") - - anchors { - bottom: parent.bottom - left: parent.left - margins: 20 - } - } - - Button { - text: qsTr("Select file") - highlighted: true - font.family: App.settings.font - onClicked: { - fileDialogImportVideo.open(); - } - - FileDialog { - id: fileDialogImportVideo - - nameFilters: ["Video files (*.webm)"] - onAccepted: { - root.next(fileDialogImportVideo.currentFile); - } - } - - anchors { - right: parent.right - bottom: parent.bottom - margins: 20 - } - } -} diff --git a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml b/ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml deleted file mode 100644 index 970038d4..00000000 --- a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml +++ /dev/null @@ -1,39 +0,0 @@ -import QtQuick -import Qt5Compat.GraphicalEffects -import QtQuick.Controls -import QtQuick.Controls.Material -import QtQuick.Layouts -import ScreenPlayApp -import ScreenPlay - -Item { - id: root - - signal wizardStarted - signal wizardExited - signal next - - SwipeView { - id: swipeView - - anchors.fill: parent - interactive: false - clip: true - - Importh264Init { - onNext: function (filePath) { - root.wizardStarted(); - swipeView.currentIndex = 1; - createWallpaperVideoImportConvert.filePath = filePath; - App.util.setNavigationActive(false); - App.create.importH264(filePath); - } - } - - Importh264Convert { - id: createWallpaperVideoImportConvert - - onExit: root.wizardExited() - } - } -} diff --git a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml b/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml deleted file mode 100644 index 55cf0919..00000000 --- a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml +++ /dev/null @@ -1,374 +0,0 @@ -import QtQuick -import Qt5Compat.GraphicalEffects -import QtQuick.Controls -import QtQuick.Controls.Material -import QtQuick.Layouts -import ScreenPlayApp -import ScreenPlay -import ScreenPlayUtil as Util - -Item { - id: root - - property bool conversionFinishedSuccessful: false - property bool canSave: false - property string filePath - - signal exit - signal save - - function basename(str) { - let filenameWithExtentions = (str.slice(str.lastIndexOf("/") + 1)); - let filename = filenameWithExtentions.split('.').slice(0, -1).join('.'); - return filename; - } - - function checkCanSave() { - if (canSave && conversionFinishedSuccessful) - btnSave.enabled = true; - else - btnSave.enabled = false; - } - - onCanSaveChanged: root.checkCanSave() - onFilePathChanged: { - textFieldName.text = basename(filePath); - } - - Connections { - function onCreateWallpaperStateChanged(state) { - switch (state) { - case Import.State.AnalyseVideo: - txtConvert.text = qsTr("AnalyseVideo..."); - break; - case Import.State.ConvertingPreviewImage: - txtConvert.text = qsTr("Generating preview image..."); - break; - case Import.State.ConvertingPreviewThumbnailImage: - txtConvert.text = qsTr("Generating preview thumbnail image..."); - break; - case Import.State.ConvertingPreviewImageFinished: - imgPreview.source = "file:///" + App.create.workingDir + "/preview.jpg"; - imgPreview.visible = true; - break; - case Import.State.ConvertingPreviewVideo: - txtConvert.text = qsTr("Generating 5 second preview video..."); - break; - case Import.State.ConvertingPreviewGif: - txtConvert.text = qsTr("Generating preview gif..."); - break; - case Import.State.ConvertingPreviewGifFinished: - gifPreview.source = "file:///" + App.create.workingDir + "/preview.gif"; - imgPreview.visible = false; - gifPreview.visible = true; - gifPreview.playing = true; - break; - case Import.State.ConvertingAudio: - txtConvert.text = qsTr("Converting Audio..."); - break; - case Import.State.ConvertingVideo: - txtConvert.text = qsTr("Converting Video... This can take some time!"); - break; - case Import.State.ConvertingVideoError: - txtConvert.text = qsTr("Converting Video ERROR!"); - break; - case Import.State.AnalyseVideoError: - txtConvert.text = qsTr("Analyse Video ERROR!"); - break; - case Import.State.Finished: - txtConvert.text = ""; - conversionFinishedSuccessful = true; - busyIndicator.running = false; - btnExit.enabled = false; - root.checkCanSave(); - break; - } - } - - function onProgressChanged(progress) { - var percentage = Math.floor(progress * 100); - if (percentage > 100 || progress > 0.95) - percentage = 100; - if (percentage === NaN) - print(progress, percentage); - txtConvertNumber.text = percentage + "%"; - } - - target: App.create - } - - Util.Headline { - id: txtHeadline - - text: qsTr("Import a video to a wallpaper") - - anchors { - top: parent.top - left: parent.left - margins: 40 - bottomMargin: 0 - } - } - - Item { - id: wrapperLeft - - width: parent.width * 0.66 - - anchors { - left: parent.left - top: txtHeadline.bottom - margins: 30 - bottom: parent.bottom - } - - Rectangle { - id: imgWrapper - - color: Material.color(Material.Grey) - - anchors { - top: parent.top - right: parent.right - rightMargin: 20 - bottom: previewSelector.top - bottomMargin: 20 - left: parent.left - } - - Image { - id: imgPreview - - fillMode: Image.PreserveAspectCrop - asynchronous: true - visible: false - anchors.fill: parent - } - - AnimatedImage { - id: gifPreview - - fillMode: Image.PreserveAspectCrop - asynchronous: true - playing: true - visible: false - anchors.fill: parent - } - - Rectangle { - id: shadow - anchors.fill: parent - - gradient: Gradient { - GradientStop { - id: gradientStop0 - position: 1 - color: "#DD000000" - } - - GradientStop { - id: gradientStop1 - position: 0 - color: "#00000000" - } - } - } - - BusyIndicator { - id: busyIndicator - - anchors.centerIn: parent - running: true - } - - Text { - id: txtConvertNumber - - color: "white" - font.pointSize: 21 - font.family: App.settings.font - - anchors { - horizontalCenter: parent.horizontalCenter - bottom: parent.bottom - bottomMargin: 40 - } - } - - Text { - id: txtConvert - - color: Material.secondaryTextColor - text: qsTr("Generating preview video...") - font.pointSize: 14 - font.family: App.settings.font - - anchors { - horizontalCenter: parent.horizontalCenter - bottom: parent.bottom - bottomMargin: 20 - } - } - } - - Util.ImageSelector { - id: previewSelector - - height: 80 - - anchors { - right: parent.right - rightMargin: 20 - left: parent.left - bottom: parent.bottom - } - } - } - - Item { - id: wrapperRight - - width: parent.width * 0.33 - - anchors { - top: txtHeadline.bottom - topMargin: 30 - bottom: parent.bottom - right: parent.right - } - - ColumnLayout { - id: column - - spacing: 0 - - anchors { - right: parent.right - left: parent.left - margins: 30 - top: parent.top - topMargin: 0 - bottom: column1.top - bottomMargin: 50 - } - - Util.TextField { - id: textFieldName - - placeholderText: qsTr("Name (required!)") - width: parent.width - Layout.fillWidth: true - onTextChanged: { - if (textFieldName.text.length >= 3) - canSave = true; - else - canSave = false; - } - } - - Util.TextField { - id: textFieldDescription - - placeholderText: qsTr("Description") - width: parent.width - Layout.fillWidth: true - } - - Util.TextField { - id: textFieldYoutubeURL - - placeholderText: qsTr("Youtube URL") - width: parent.width - Layout.fillWidth: true - } - - Util.TagSelector { - id: textFieldTags - - width: parent.width - Layout.fillWidth: true - } - } - - Row { - id: column1 - - height: 80 - width: childrenRect.width - spacing: 10 - - anchors { - right: parent.right - rightMargin: 30 - bottomMargin: -10 - bottom: parent.bottom - } - - Button { - id: btnExit - - text: qsTr("Abort") - Material.background: Material.Red - Material.foreground: "white" - font.family: App.settings.font - onClicked: { - root.exit(); - App.create.cancel(); - } - } - - Button { - id: btnSave - objectName: "btnSave" - text: qsTr("Save") - enabled: false - Material.background: Material.accent - Material.foreground: "white" - font.family: App.settings.font - onClicked: { - if (conversionFinishedSuccessful) { - btnSave.enabled = false; - App.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, Create.H264, textFieldTags.getTags()); - savePopup.open(); - } - } - } - } - } - - Popup { - id: savePopup - - modal: true - focus: true - width: 250 - anchors.centerIn: parent - height: 200 - onOpened: timerSave.start() - - BusyIndicator { - anchors.centerIn: parent - running: true - } - - Text { - text: qsTr("Save Wallpaper...") - color: Material.primaryTextColor - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - anchors.bottomMargin: 30 - font.family: App.settings.font - } - - Timer { - id: timerSave - - interval: 1000 + Math.random() * 1000 - onTriggered: { - savePopup.close(); - App.util.setNavigationActive(true); - root.exit(); - } - } - } -} diff --git a/ScreenPlay/qml/Installed/Sidebar.qml b/ScreenPlay/qml/Installed/Sidebar.qml index d0d34b8a..6b83b91c 100644 --- a/ScreenPlay/qml/Installed/Sidebar.qml +++ b/ScreenPlay/qml/Installed/Sidebar.qml @@ -340,9 +340,15 @@ Item { } } } - MessageDialog { - id: errorDialog - buttons: MessageDialog.Ok + + Dialog { + id: dialog + standardButtons: Dialog.Ok + title: qsTr("Export Godot project") + property alias message: messageText.text + Text { + id: messageText + } } Button { @@ -375,21 +381,22 @@ Item { absoluteStoragePath, App.globalVariables.godotEditorExecutablePath).then( result => { - if(!result.success){ - errorDialog.text = ("Error exporting Godot") - errorDialog.informativeText = result.messag - errorDialog.open() - return + if (!result.success) { + dialog.title = ("Error exporting Godot") + dialog.message = result.message + dialog.open() + } else { + const screenFile = item.m_file + let success = App.screenPlayManager.createWallpaper( + root.type, + cbVideoFillMode.currentValue, + absoluteStoragePath, + previewImage, screenFile, + activeMonitors, volume, + 1, {}, true) } - const screenFile = item.m_file - let success = App.screenPlayManager.createWallpaper( - root.type, - cbVideoFillMode.currentValue, - absoluteStoragePath, - previewImage, screenFile, - activeMonitors, volume, - 1, {}, true) }) + root.state = "inactive" return } diff --git a/ScreenPlay/src/create.cpp b/ScreenPlay/src/create.cpp index 5e867b99..84d2dc78 100644 --- a/ScreenPlay/src/create.cpp +++ b/ScreenPlay/src/create.cpp @@ -2,6 +2,7 @@ #include "ScreenPlay/create.h" #include "ScreenPlayUtil/util.h" +#include "qguiapplication.h" namespace ScreenPlay { @@ -43,7 +44,7 @@ void Create::reset() /*! \brief Starts the process. */ -void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, const int quality) +void Create::createWallpaperStart(QString videoPath, ScreenPlay::Video::VideoCodec target_codec, const int quality) { reset(); ScreenPlay::Util util; @@ -63,19 +64,6 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c return; } - QString target_codec; - switch (codec) { - case Create::VideoCodec::VP8: - target_codec = "vp8"; - break; - case Create::VideoCodec::VP9: - target_codec = "vp9"; - break; - case Create::VideoCodec::AV1: - target_codec = "av1"; - break; - } - m_createImportFuture = QtConcurrent::run(QThreadPool::globalInstance(), [videoPath, target_codec, quality, this]() { CreateImportVideo import(videoPath, workingDir(), target_codec, quality, m_interrupt); QObject::connect(&import, &CreateImportVideo::createWallpaperStateChanged, this, &Create::createWallpaperStateChanged, Qt::ConnectionType::QueuedConnection); @@ -134,13 +122,7 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c } } - // Skip convert for webm - if (import.m_isWebm) { - emit createWallpaperStateChanged(Import::State::Finished); - return; - } - - qInfo() << "createWallpaperVideo()"; + qInfo() << "createWallpaperVideo"; if (!import.createWallpaperVideo() || m_interrupt) { emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); @@ -157,91 +139,6 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c m_createImportFutureWatcher.setFuture(m_createImportFuture); } -void Create::importH264(QString videoPath) -{ - reset(); - ScreenPlay::Util util; - videoPath = util.toLocal(videoPath); - - const QDir installedDir = util.toLocal(m_globalVariables->localStoragePath().toString()); - - // Create a temp dir so we can later alter it to the workshop id - const QDateTime date = QDateTime::currentDateTime(); - const auto folderName = date.toString("ddMMyyyyhhmmss"); - setWorkingDir(installedDir.path() + "/" + folderName); - - if (!installedDir.mkdir(folderName)) { - qInfo() << "Unable to create folder with name: " << folderName << " at: " << installedDir; - emit createWallpaperStateChanged(Import::State::CreateTmpFolderError); - emit abortCreateWallpaper(); - return; - } - - m_createImportFuture = QtConcurrent::run(QThreadPool::globalInstance(), [videoPath, this]() { - CreateImportVideo import(videoPath, workingDir(), m_interrupt); - QObject::connect(&import, &CreateImportVideo::createWallpaperStateChanged, this, &Create::createWallpaperStateChanged, Qt::ConnectionType::QueuedConnection); - QObject::connect(&import, &CreateImportVideo::abortAndCleanup, this, &Create::abortAndCleanup, Qt::ConnectionType::QueuedConnection); - QObject::connect( - &import, &CreateImportVideo::processOutput, this, [this](const QString text) { - appendFfmpegOutput(text + "\n"); - }, - Qt::ConnectionType::QueuedConnection); - - if (!import.createWallpaperInfo() || m_interrupt) { - emit createWallpaperStateChanged(Import::State::Failed); - emit import.abortAndCleanup(); - return; - } - - qInfo() << "createWallpaperImageThumbnailPreview()"; - if (!import.createWallpaperImageThumbnailPreview() || m_interrupt) { - emit createWallpaperStateChanged(Import::State::Failed); - emit import.abortAndCleanup(); - return; - } - - qInfo() << "createWallpaperImagePreview()"; - if (!import.createWallpaperImagePreview() || m_interrupt) { - emit createWallpaperStateChanged(Import::State::Failed); - emit import.abortAndCleanup(); - return; - } - - // Skip preview convert for webm - if (!import.createWallpaperVideoPreview() || m_interrupt) { - emit createWallpaperStateChanged(Import::State::Failed); - emit import.abortAndCleanup(); - return; - } - - qInfo() << "createWallpaperGifPreview()"; - if (!import.createWallpaperGifPreview() || m_interrupt) { - emit createWallpaperStateChanged(Import::State::Failed); - emit import.abortAndCleanup(); - return; - } - - // If the video has no audio we can skip the extraction - if (!import.m_skipAudio) { - qInfo() << "extractWallpaperAudio()"; - if (!import.extractWallpaperAudio() || m_interrupt) { - emit createWallpaperStateChanged(Import::State::Failed); - emit import.abortAndCleanup(); - return; - } - } - - emit createWallpaperStateChanged(Import::State::Finished); - return; - }); - - QObject::connect(&m_createImportFutureWatcher, &QFutureWatcherBase::finished, this, [this]() { - if (m_interrupt) - abortAndCleanup(); - }); - - m_createImportFutureWatcher.setFuture(m_createImportFuture); -} /*! \brief When converting of the wallpaper steps where successful. @@ -252,7 +149,7 @@ void Create::saveWallpaper( QString filePath, QString previewImagePath, const QString youtube, - const Create::VideoCodec codec, + const ScreenPlay::Video::VideoCodec codec, const QVector tags) { ScreenPlay::Util util; @@ -282,13 +179,13 @@ void Create::saveWallpaper( } QFileInfo filePathFile(filePath); - if (filePath.endsWith(".webm") || filePath.endsWith(".mp4")) { - if (!QFile::copy(filePath, m_workingDir + "/" + filePathFile.fileName())) { - qDebug() << "Could not copy" << filePath << " to " << m_workingDir + "/" + filePathFile.fileName(); - emit createWallpaperStateChanged(Import::State::CopyFilesError); - return; - } - } + // if (filePath.endsWith(".webm") || filePath.endsWith(".mp4")) { + // if (!QFile::copy(filePath, m_workingDir + "/" + filePathFile.fileName())) { + // qDebug() << "Could not copy" << filePath << " to " << m_workingDir + "/" + filePathFile.fileName(); + // emit createWallpaperStateChanged(Import::State::CopyFilesError); + // return; + // } + // } emit createWallpaperStateChanged(Import::State::CopyFilesFinished); emit createWallpaperStateChanged(Import::State::CreateProjectFile); @@ -296,8 +193,17 @@ void Create::saveWallpaper( obj.insert("description", description); obj.insert("title", title); obj.insert("youtube", youtube); - obj.insert("videoCodec", QVariant::fromValue(codec).toString()); - obj.insert("file", filePathFile.completeBaseName() + (codec == VideoCodec::H264 ? ".mp4" : ".webm")); + obj.insert("videoCodec", QVariant::fromValue(codec).toString()); + + QString fileEnding; + if (codec == Video::VideoCodec::H264) + fileEnding = ".mp4"; + if (codec == Video::VideoCodec::AV1) + fileEnding = ".mkv"; + if (codec == Video::VideoCodec::VP8 || codec == Video::VideoCodec::VP9) + fileEnding = ".webm"; + + obj.insert("file", filePathFile.completeBaseName() + fileEnding); obj.insert("previewGIF", "preview.gif"); obj.insert("previewWEBM", "preview.webm"); obj.insert("preview", previewImageFile.exists() ? previewImageFile.fileName() : "preview.jpg"); diff --git a/ScreenPlay/src/createimportvideo.cpp b/ScreenPlay/src/createimportvideo.cpp index ce350deb..60b3ea3e 100644 --- a/ScreenPlay/src/createimportvideo.cpp +++ b/ScreenPlay/src/createimportvideo.cpp @@ -24,7 +24,7 @@ namespace ScreenPlay { CreateImportVideo::CreateImportVideo( const QString& videoPath, const QString& exportPath, - const QString& codec, + const ScreenPlay::Video::VideoCodec targetCodec, const int quality, std::atomic& interrupt) : QObject(nullptr) @@ -33,17 +33,7 @@ CreateImportVideo::CreateImportVideo( { m_videoPath = videoPath; m_exportPath = exportPath; - m_codec = codec; - setupFFMPEG(); -} - -CreateImportVideo::CreateImportVideo(const QString& videoPath, const QString& exportPath, std::atomic& interrupt) - : QObject(nullptr) - , m_quality(0) - , m_interrupt(interrupt) -{ - m_videoPath = videoPath; - m_exportPath = exportPath; + m_targetCodec = targetCodec; setupFFMPEG(); } @@ -86,10 +76,6 @@ void CreateImportVideo::setupFFMPEG() */ bool CreateImportVideo::createWallpaperInfo() { - if (m_videoPath.endsWith(".webm") || m_videoPath.endsWith(".mkv")) { - m_isWebm = true; - } - // Get video info QStringList args; args.append("-print_format"); @@ -138,12 +124,7 @@ bool CreateImportVideo::createWallpaperInfo() emit createWallpaperStateChanged(Import::State::AnalyseVideoError); return false; } - - if (m_isWebm) { - return analyzeWebmReadFrames(obj.value()); - } else { - return analyzeVideo(obj.value()); - } + return analyzeVideo(obj.value()); } /*! @@ -165,6 +146,15 @@ bool CreateImportVideo::analyzeWebmReadFrames(const QJsonObject& obj) const QJsonObject firstStream = streams.first().toObject(); qInfo() << "streams:" << streams; + for (const auto& stream : streams) { + QString codec_type = stream.toObject().value("codec_type").toString(); + if (codec_type == "audio") { + m_skipAudio = false; + } else { + m_skipAudio = true; + } + } + bool okParseNumberOfFrames { false }; int numberOfFrames = firstStream.value("nb_read_frames").toString().toInt(&okParseNumberOfFrames); if (!okParseNumberOfFrames) { @@ -202,6 +192,37 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj) { // Check for audio and video streams const QJsonArray arrayStream = obj.value("streams").toArray(); + // Get framerate + const QJsonArray streams = obj.value("streams").toArray(); + if (streams.empty()) { + qDebug() << "Error container does not have any video streams"; + emit processOutput("Error container does not have any video streams"); + return false; + } + + const QJsonObject firstStream = streams.first().toObject(); + const QString codecName = firstStream.value("codec_name").toVariant().toString(); + + // It is not that important to check for all codecs, + // we just need a check for the important once to skip + // import convertion if it is the same codec. + if (codecName == "vp8") { + m_sourceCodec = Video::VideoCodec::VP8; + } else if (codecName == "vp9") { + m_sourceCodec = Video::VideoCodec::VP9; + } else if (codecName == "av1") { + m_sourceCodec = Video::VideoCodec::AV1; + } else if (codecName == "h264") { + m_sourceCodec = Video::VideoCodec::H264; + } else if (codecName == "hevc") { + m_sourceCodec = Video::VideoCodec::H265; // HEVC is H.265 + } else { + m_sourceCodec = Video::VideoCodec::Unknown; + } + + if (m_sourceCodec == Video::VideoCodec::VP8 || m_sourceCodec == Video::VideoCodec::VP9) { + return analyzeWebmReadFrames(obj); + } bool hasAudioStream { false }; bool hasVideoStream { false }; @@ -257,16 +278,6 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj) m_length = static_cast(tmpLength); - // Get framerate - const QJsonArray streams = obj.value("streams").toArray(); - if (streams.empty()) { - qDebug() << "Error container does not have any video streams"; - emit processOutput("Error container does not have any video streams"); - return false; - } - - const QJsonObject firstStream = streams.first().toObject(); - // The paramter gets us the exact framerate // "avg_frame_rate":"47850000/797509" // so we need no calc the value by dividing the two numbers @@ -519,6 +530,18 @@ bool CreateImportVideo::createWallpaperImagePreview() */ bool CreateImportVideo::createWallpaperVideo() { + const QFileInfo sourceFile(m_videoPath); + + if (m_sourceCodec == m_targetCodec) { + qInfo() << "Skip video convert because they are the same"; + if (!QFile::copy(sourceFile.absoluteFilePath(), m_exportPath + "/" + sourceFile.fileName())) { + qDebug() << "Could not copy" << sourceFile.absoluteFilePath() << " to " << m_exportPath; + return false; + } + emit createWallpaperStateChanged(Import::State::Finished); + return true; + } + emit createWallpaperStateChanged(Import::State::ConvertingVideo); connect(m_process.get(), &QProcess::readyReadStandardOutput, this, [&]() { @@ -543,6 +566,26 @@ bool CreateImportVideo::createWallpaperVideo() emit processOutput(tmpOut); }); + QString targetCodec; + QString targetFileEnding; + if (m_targetCodec == Video::VideoCodec::VP8) + targetCodec = "libvpx"; + targetFileEnding = ".webm"; + if (m_targetCodec == Video::VideoCodec::VP8) + targetCodec = "libvpx"; + targetFileEnding = ".webm"; + if (m_targetCodec == Video::VideoCodec::AV1) + targetCodec = "libaom-av1"; + targetFileEnding = ".mkv"; + if (m_targetCodec == Video::VideoCodec::H264) { + targetFileEnding = ".mp4"; + if (QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Windows) { + targetCodec = "h264_mf"; + } else { + targetCodec = "libx264"; + } + } + QStringList args; args.append("-hide_banner"); args.append("-y"); @@ -550,12 +593,7 @@ bool CreateImportVideo::createWallpaperVideo() args.append("-i"); args.append(m_videoPath); args.append("-c:v"); - if (m_codec == "vp8") - args.append("libvpx"); - if (m_codec == "vp9") - args.append("libvpx-vp9"); - if (m_codec == "av1") - args.append("libaom-av1"); + args.append(targetCodec); args.append("-b:v"); args.append("13000k"); args.append("-threads"); @@ -593,12 +631,7 @@ bool CreateImportVideo::createWallpaperVideo() args.append("-i"); args.append(m_videoPath); args.append("-c:v"); - if (m_codec == "vp8") - args.append("libvpx"); - if (m_codec == "vp9") - args.append("libvpx-vp9"); - if (m_codec == "av1") - args.append("libaom-av1"); + args.append(targetCodec); args.append("-b:v"); args.append("13000k"); args.append("-threads"); @@ -617,8 +650,7 @@ bool CreateImportVideo::createWallpaperVideo() args.append(QString::number(m_quality)); args.append("-pass"); args.append("2"); - const QFileInfo file(m_videoPath); - const QString convertedFileAbsolutePath { m_exportPath + "/" + file.completeBaseName() + ".webm" }; + const QString convertedFileAbsolutePath { m_exportPath + "/" + sourceFile.completeBaseName() + targetFileEnding }; args.append(convertedFileAbsolutePath); const QString ffmpegOutput = waitForFinished(args); @@ -696,7 +728,7 @@ QString CreateImportVideo::waitForFinished( { m_process = std::make_unique(); - QObject::connect(m_process.get(), &QProcess::errorOccurred, [=, this](QProcess::ProcessError error) { + QObject::connect(m_process.get(), &QProcess::errorOccurred, this, [=, this](QProcess::ProcessError error) { qDebug() << "error enum val = " << error << m_process->errorString(); emit createWallpaperStateChanged(Import::State::AnalyseVideoError); m_process->terminate(); diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/contenttypes.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/contenttypes.h index e0f45d44..f3550a27 100644 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/contenttypes.h +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/contenttypes.h @@ -5,9 +5,6 @@ #include #include -// We must package everything into a class for -// qml to be able to have typed enums. Making -// qml enums unscoped as default was a mistake. namespace ScreenPlay { class ContentTypes : public QObject { diff --git a/ScreenPlayUtil/qml/Slider.qml b/ScreenPlayUtil/qml/Slider.qml index 5ae3eb8e..602e3719 100644 --- a/ScreenPlayUtil/qml/Slider.qml +++ b/ScreenPlayUtil/qml/Slider.qml @@ -12,7 +12,7 @@ Item { property string iconSource: "qrc:/qml/ScreenPlayApp/assets/icons/icon_volume.svg" property alias slider: slider - height: 70 + height: 80 Text { id: txtHeadline @@ -40,7 +40,7 @@ Item { left: parent.left } - Image { + ColorImage { id: imgIcon width: 20