diff --git a/ScreenPlay/qml/Create/Create.qml b/ScreenPlay/qml/Create/Create.qml index efd3dba2..7156d6e6 100644 --- a/ScreenPlay/qml/Create/Create.qml +++ b/ScreenPlay/qml/Create/Create.qml @@ -13,9 +13,8 @@ Item { anchors.fill: parent state: "out" - Component.onCompleted: { - create.state = "in" - } + Component.onCompleted: create.state = "in" + property url activeVideoFile: "" property url activeFolder: "" @@ -27,29 +26,15 @@ Item { activeVideoFile = videoFile loader.setSource( "Wizards/CreateWallpaper/CreateWallpaperWizard.qml", { - "filePath": activeVideoFile, - "importState": CreateWallpaperWizard.ImportState.Convert - }) - } - onVideoImportFileSelected: { - create.state = "import" - - - activeVideoFile = videoFile - loader.setSource( - "Wizards/CreateWallpaper/CreateWallpaperWizard.qml", { - "filePath": activeVideoFile, - "importState": CreateWallpaperWizard.ImportState.Import + "filePath": activeVideoFile }) } onProjectFileSelected: { create.state = "import" - - activeFolder = projectFile - loader.setSource("CreateNew.qml", { - - }) + // TODO + // activeFolder = projectFile + // loader.setSource("CreateNew.qml", { }) } } diff --git a/ScreenPlay/qml/Create/CreateWallpaper.qml b/ScreenPlay/qml/Create/CreateWallpaper.qml index 7f5bd474..252c4d7e 100644 --- a/ScreenPlay/qml/Create/CreateWallpaper.qml +++ b/ScreenPlay/qml/Create/CreateWallpaper.qml @@ -13,15 +13,14 @@ Item { Component.onCompleted: createWallpaper.state = "in" signal videoImportConvertFileSelected(var videoFile) - signal videoImportFileSelected(var videoFile) - signal projectFileSelected(var projectFile) + WorkshopLoader { id: wl } Text { id: txtHeadline - text: qsTr("Import Video Wallpaper") + text: qsTr("Import Wallpaper") opacity: 0 anchors { top: parent.top @@ -42,10 +41,9 @@ Item { anchors { top: parent.top topMargin: 50 - left:parent.left + left: parent.left } - Rectangle { id: importVideoBg radius: 3 @@ -91,9 +89,10 @@ Item { FileDialog { id: fileDialogImportVideo - // nameFilters: ["Video files (*.mp4)"] + nameFilters: ["Video files (*.webm)"] onAccepted: { - videoImportConvertFileSelected(fileDialogImportVideo.currentFile) + videoImportConvertFileSelected( + fileDialogImportVideo.currentFile) } } } @@ -122,7 +121,7 @@ Item { anchors { top: parent.top topMargin: 50 - left:wrapperImportVideo.right + left: wrapperImportVideo.right leftMargin: 20 } @@ -137,7 +136,7 @@ Item { Image { id: imgUploadImportVideo2 - source: "qrc:/assets/icons/icon_movie.svg" + source: "qrc:/assets/icons/icon_scene.svg" height: 120 width: 120 anchors { @@ -154,7 +153,8 @@ Item { } Button { - text: qsTr("Convert Video") + text: qsTr("Import ThreeJs Scene") + enabled: false anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom @@ -166,14 +166,15 @@ Item { icon.color: "white" icon.width: 16 icon.height: 16 - onClicked: fileDialogImportVideo.open() + onClicked: fileDialogImportProject.open() } FileDialog { - id: fileDialogImportVideo2 - // nameFilters: ["Video files (*.mp4)"] + id: fileDialogImportProject + nameFilters: ["ThreeJS Scene files(scene.pkg)"] onAccepted: { - videoImportConvertFileSelected(fileDialogImportVideo.currentFile) + projectFileSelected( + fileDialogImportProject.currentFile) } } } @@ -204,7 +205,7 @@ Item { anchors { top: wrapperConvertVideo.bottom - left:parent.left + left: parent.left } RectangularGlow { @@ -224,16 +225,15 @@ Item { opacity: 0 } - Rectangle { id: importVideoBg3 radius: 3 - + z: 10 anchors { fill: parent margins: 10 } - z: 10 + Button { text: qsTr("Upload Exsisting Project to Steam") anchors.centerIn: parent @@ -244,14 +244,7 @@ Item { icon.width: 16 icon.height: 16 onClicked: { - fileDialogOpenProject.open() - } - } - FileDialog { - id: fileDialogOpenProject3 - nameFilters: ["Project files (project.json)"] - onAccepted: { - projectFileSelected(fileDialogOpenProject.currentFile) + } } } @@ -292,7 +285,6 @@ Item { opacity: 0 anchors.topMargin: -100 } - }, State { name: "in" @@ -355,8 +347,6 @@ Item { easing.type: Easing.InOutQuart } } - - } PropertyAnimation { targets: [txtHeadline] @@ -379,32 +369,6 @@ Item { - - - - - - - - - - - - - - - - - - - - - - - - - - /*##^## Designer { D{i:0;autoSize:true;height:480;width:640} } diff --git a/ScreenPlay/qml/Create/Wizards/CreateWallpaper/CreateWallpaperWizard.qml b/ScreenPlay/qml/Create/Wizards/CreateWallpaper/CreateWallpaperWizard.qml index af2856c6..55581551 100644 --- a/ScreenPlay/qml/Create/Wizards/CreateWallpaper/CreateWallpaperWizard.qml +++ b/ScreenPlay/qml/Create/Wizards/CreateWallpaper/CreateWallpaperWizard.qml @@ -15,18 +15,12 @@ Item { property bool canNext: false property int importState: CreateWallpaperWizard.ImportState.Import - enum ImportState { - Create, - Import - } - - Component.onCompleted: { state = "in" - print(importState) utility.setNavigationActive(false) if (importState === CreateWallpaperWizard.ImportState.Import) { - loader_wrapperContent.source = "qrc:/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImport.qml" + loader_wrapperContent.source + = "qrc:/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImport.qml" } else { loader_wrapperContent.source = "qrc:/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml" } @@ -46,7 +40,6 @@ Item { || state === Create.State.ConvertingPreviewImageError || state === Create.State.AnalyseVideoError) { createNew.state = "error" - return } } } @@ -142,7 +135,7 @@ Item { id: timerBack interval: 800 onTriggered: { - screenPlayCreate.abort() + screenPlayCreate.abortAndCleanup() utility.setNavigationActive(true) utility.setNavigation("Create") } @@ -195,7 +188,7 @@ Item { opacity: .4 } PropertyChanges { - target: wrapperContent + target: loader_wrapperContent opacity: 0 z: 0 } @@ -216,7 +209,7 @@ Item { opacity: .4 } PropertyChanges { - target: wrapperContent + target: loader_wrapperContent opacity: 0 z: 0 } @@ -301,7 +294,7 @@ Item { to: "error" SequentialAnimation { PropertyAnimation { - target: wrapperContent + target: loader_wrapperContent duration: 600 property: "opacity" easing.type: Easing.OutQuart @@ -322,7 +315,7 @@ Item { to: "success" SequentialAnimation { PropertyAnimation { - target: wrapperContent + target: loader_wrapperContent duration: 600 property: "opacity" easing.type: Easing.OutQuart diff --git a/ScreenPlay/src/create.cpp b/ScreenPlay/src/create.cpp index 9bd87c07..d5908f00 100644 --- a/ScreenPlay/src/create.cpp +++ b/ScreenPlay/src/create.cpp @@ -65,21 +65,26 @@ void Create::createWallpaperStart(QString videoPath) return; m_createWallpaperData.exportPath = dir.path() + "/" + folderName; - m_workingDir = m_createWallpaperData.exportPath; - + this->setWorkingDir(m_createWallpaperData.exportPath); // If we return early/false this means the creation // process did not work - // Todo: cleanup! + bool ok = true; if (!this->createWallpaperInfo()) - return; + ok = false; - if (!this->createWallpaperVideoPreview()) - return; + if (ok && !this->createWallpaperVideoPreview()) + ok = false; - if (!this->createWallpaperVideo()) - return; + if (ok && !this->createWallpaperGifPreview()) + ok = false; + + if (ok && !this->extractWallpaperAudio()) + ok = false; + + if (!ok) + abortAndCleanup(); }); } @@ -167,11 +172,106 @@ bool Create::createWallpaperInfo() bool Create::createWallpaperVideoPreview() { - /* - * - * Create png - * - */ + QStringList args; + args.append("-loglevel"); + args.append("error"); + args.append("-y"); + args.append("-stats"); + args.append("-i"); + args.append(m_createWallpaperData.videoPath); + args.append("-speed"); + args.append("ultrafast"); + args.append("-vf"); + // We allways want to have a 5 second clip via 24fps -> 120 frames + // Divided by the number of frames we can skip (timeInSeconds * Framrate) + // scale & crop parameter: https://unix.stackexchange.com/a/284731 + args.append("select='not(mod(n," + QString::number((m_createWallpaperData.length / 5)) + "))',setpts=N/FRAME_RATE/TB,crop=in_h*16/9:in_h,scale=-2:400"); + // Disable audio + args.append("-an"); + args.append(m_createWallpaperData.exportPath + "/preview.webm"); + QScopedPointer proConvertPreviewWebM(new QProcess()); + + proConvertPreviewWebM.data()->setArguments(args); +#ifdef Q_OS_WIN + proConvertPreviewWebM.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg.exe"); +#endif +#ifdef Q_OS_MACOS + proConvertPreviewMP4.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg"); +#endif + emit createWallpaperStateChanged(Create::State::ConvertingPreviewVideo); + + connect(this, &Create::abortCreateWallpaper, proConvertPreviewWebM.data(), &QProcess::kill); + proConvertPreviewWebM.data()->start(); + while (!proConvertPreviewWebM.data()->waitForFinished(100)) //Wake up every 100ms and check if we must exit + { + QCoreApplication::processEvents(); + } + disconnect(this, &Create::abortCreateWallpaper, proConvertPreviewWebM.data(), &QProcess::kill); + QString tmpErr = proConvertPreviewWebM.data()->readAllStandardError(); + if (!tmpErr.isEmpty()) { + QFile previewVideo(m_createWallpaperData.exportPath + "/preview.webm"); + if (!previewVideo.exists() && !(previewVideo.size() > 0)) { + emit processOutput(tmpErr); + emit createWallpaperStateChanged(Create::State::ConvertingPreviewVideoError); + return false; + } + } + + this->processOutput(proConvertPreviewWebM.data()->readAll()); + proConvertPreviewWebM.data()->close(); + + emit createWallpaperStateChanged(Create::State::ConvertingPreviewVideoFinished); + + return true; +} + +bool Create::createWallpaperGifPreview() +{ + + emit createWallpaperStateChanged(Create::State::ConvertingPreviewGif); + + QStringList args; + args.append("-y"); + args.append("-stats"); + args.append("-i"); + args.append(m_createWallpaperData.exportPath + "/preview.webm"); + args.append("-filter_complex"); + args.append("[0:v] fps=12,scale=w=480:h=-1,split [a][b];[a] palettegen=stats_mode=single [p];[b][p] paletteuse=new=1"); + args.append(m_createWallpaperData.exportPath + "/preview.gif"); + + QScopedPointer proConvertGif(new QProcess()); + proConvertGif.data()->setArguments(args); +#ifdef Q_OS_WIN + proConvertGif.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg.exe"); +#endif +#ifdef Q_OS_MACOS + proConvertGif.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg"); +#endif + connect(this, &Create::abortCreateWallpaper, proConvertGif.data(), &QProcess::kill); + proConvertGif.data()->start(); + while (!proConvertGif.data()->waitForFinished(100)) //Wake up every 100ms and check if we must exit + { + QCoreApplication::processEvents(); + } + disconnect(this, &Create::abortCreateWallpaper, proConvertGif.data(), &QProcess::kill); + QString tmpErrGif = proConvertGif.data()->readAllStandardError(); + if (!tmpErrGif.isEmpty()) { + QFile previewGif(m_createWallpaperData.exportPath + "/preview.gif"); + if (!previewGif.exists() && !(previewGif.size() > 0)) { + emit createWallpaperStateChanged(Create::State::ConvertingPreviewGifError); + return false; + } + } + + this->processOutput(proConvertGif.data()->readAll()); + proConvertGif.data()->close(); + emit createWallpaperStateChanged(Create::State::ConvertingPreviewGifFinished); + + return true; +} + +bool Create::createWallpaperImagePreview() +{ emit createWallpaperStateChanged(Create::State::ConvertingPreviewImage); @@ -217,118 +317,12 @@ bool Create::createWallpaperVideoPreview() proConvertImage.data()->close(); emit createWallpaperStateChanged(Create::State::ConvertingPreviewImageFinished); - /* - * - * Create preview mp4 - * - */ - - args.append("-loglevel"); - args.append("error"); - args.append("-y"); - args.append("-stats"); - args.append("-i"); - args.append(m_createWallpaperData.videoPath); - args.append("-speed"); - args.append("ultrafast"); - args.append("-vf"); - // We allways want to have a 5 second clip via 24fps -> 120 frames - // Divided by the number of frames we can skip (timeInSeconds * Framrate) - // scale & crop parameter: https://unix.stackexchange.com/a/284731 - args.append("select='not(mod(n," + QString::number((m_createWallpaperData.length / 5)) + "))',setpts=N/FRAME_RATE/TB,crop=in_h*16/9:in_h,scale=-2:400"); - // Disable audio - args.append("-an"); - args.append(m_createWallpaperData.exportPath + "/preview.mp4"); - QScopedPointer proConvertPreviewMP4(new QProcess()); - - proConvertPreviewMP4.data()->setArguments(args); -#ifdef Q_OS_WIN - proConvertPreviewMP4.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg.exe"); -#endif -#ifdef Q_OS_MACOS - proConvertPreviewMP4.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg"); -#endif - emit createWallpaperStateChanged(Create::State::ConvertingPreviewVideo); - - connect(this, &Create::abortCreateWallpaper, proConvertPreviewMP4.data(), &QProcess::kill); - proConvertPreviewMP4.data()->start(); - while (!proConvertPreviewMP4.data()->waitForFinished(100)) //Wake up every 100ms and check if we must exit - { - QCoreApplication::processEvents(); - } - disconnect(this, &Create::abortCreateWallpaper, proConvertPreviewMP4.data(), &QProcess::kill); - QString tmpErr = proConvertPreviewMP4.data()->readAllStandardError(); - if (!tmpErr.isEmpty()) { - QFile previewVideo(m_createWallpaperData.exportPath + "/preview.mp4"); - if (!previewVideo.exists() && !(previewVideo.size() > 0)) { - emit processOutput(tmpErr); - emit createWallpaperStateChanged(Create::State::ConvertingPreviewVideoError); - return false; - } - } - - this->processOutput(proConvertPreviewMP4.data()->readAll()); - proConvertPreviewMP4.data()->close(); - - emit createWallpaperStateChanged(Create::State::ConvertingPreviewVideoFinished); - - /* - * - * Create gif - * - */ - - emit createWallpaperStateChanged(Create::State::ConvertingPreviewGif); - args.clear(); - args.append("-y"); - args.append("-stats"); - args.append("-i"); - args.append(m_createWallpaperData.exportPath + "/preview.mp4"); - args.append("-filter_complex"); - args.append("[0:v] fps=12,scale=w=480:h=-1,split [a][b];[a] palettegen=stats_mode=single [p];[b][p] paletteuse=new=1"); - args.append(m_createWallpaperData.exportPath + "/preview.gif"); - - QScopedPointer proConvertGif(new QProcess()); - proConvertGif.data()->setArguments(args); -#ifdef Q_OS_WIN - proConvertGif.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg.exe"); -#endif -#ifdef Q_OS_MACOS - proConvertGif.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg"); -#endif - connect(this, &Create::abortCreateWallpaper, proConvertGif.data(), &QProcess::kill); - proConvertGif.data()->start(); - while (!proConvertGif.data()->waitForFinished(100)) //Wake up every 100ms and check if we must exit - { - - QCoreApplication::processEvents(); - } - disconnect(this, &Create::abortCreateWallpaper, proConvertGif.data(), &QProcess::kill); - QString tmpErrGif = proConvertGif.data()->readAllStandardError(); - if (!tmpErrGif.isEmpty()) { - QFile previewGif(m_createWallpaperData.exportPath + "/preview.gif"); - if (!previewGif.exists() && !(previewGif.size() > 0)) { - emit createWallpaperStateChanged(Create::State::ConvertingPreviewGifError); - return false; - } - } - - this->processOutput(proConvertGif.data()->readAll()); - proConvertGif.data()->close(); - emit createWallpaperStateChanged(Create::State::ConvertingPreviewGifFinished); - return true; } -bool Create::createWallpaperVideo() +bool Create::extractWallpaperAudio() { - /* - * - * Extract audio - * - */ - emit createWallpaperStateChanged(Create::State::ConvertingAudio); QStringList args; @@ -374,105 +368,6 @@ bool Create::createWallpaperVideo() proConvertAudio.data()->close(); emit createWallpaperStateChanged(Create::State::ConvertingAudioFinished); - /* - * - * Create video - * - */ - - emit createWallpaperStateChanged(Create::State::ConvertingVideo); - - args.clear(); - args.append("-hide_banner"); - args.append("-y"); - args.append("-stats"); - args.append("-i"); - args.append(m_createWallpaperData.videoPath); - args.append("-c:v"); - args.append("libvpx-vp9"); - args.append("-crf"); - args.append("30"); - args.append("-threads"); - args.append("16"); - args.append("-slices"); - args.append("16"); - args.append("-cpu-used"); - args.append("4"); - args.append("-pix_fmt"); - args.append("yuv420p"); - args.append("-b:v"); - args.append("0"); - args.append(m_createWallpaperData.exportPath + "/video.webm"); - - QScopedPointer proConvertVideo(new QProcess()); - proConvertVideo.data()->setArguments(args); - proConvertVideo.data()->setProcessChannelMode(QProcess::MergedChannels); -#ifdef Q_OS_WIN - proConvertVideo.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg.exe"); -#endif -#ifdef Q_OS_MACOS - proConvertVideo.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg"); -#endif - connect(proConvertVideo.data(), &QProcess::readyRead, this, [&]() { - // Somehow readyRead gets seldom called in the end with an - // not valid QProcess pointer.... - if (proConvertVideo.isNull()) { - qDebug() << "EROR NULL"; - return; - } - - if (!proConvertVideo.data()->isOpen()) { - qDebug() << "ERROR NOT OPEN"; - return; - } - - if (!proConvertVideo.data()->isReadable()) { - qDebug() << "ERROR CANNOT READ LINE"; - return; - } - - QString tmpOut = proConvertVideo.data()->readAll(); - - auto tmpList = tmpOut.split(QRegExp("\\s+"), QString::SkipEmptyParts); - if (tmpList.length() > 2) { - bool ok = false; - float currentFrame = QString(tmpList.at(1)).toFloat(&ok); - - if (!ok) - return; - - float progress = currentFrame / (m_createWallpaperData.length * m_createWallpaperData.framerate); - - this->setProgress(progress); - } - this->processOutput(tmpOut); - }, - Qt::QueuedConnection); - - connect(this, &Create::abortCreateWallpaper, proConvertVideo.data(), &QProcess::kill); - proConvertVideo.data()->start(QIODevice::ReadOnly); - while (!proConvertVideo.data()->waitForFinished(100)) //Wake up every 100ms and check if we must exit - { - QCoreApplication::processEvents(); - } - disconnect(proConvertVideo.data(), &QProcess::readyReadStandardOutput, nullptr, nullptr); - disconnect(this, &Create::abortCreateWallpaper, proConvertVideo.data(), &QProcess::kill); - - QString out = proConvertVideo.data()->readAllStandardOutput(); - - this->processOutput(out); - QString tmpErrVideo = proConvertVideo.data()->readAllStandardError(); - if (!tmpErrVideo.isEmpty()) { - QFile video(m_createWallpaperData.exportPath + "/video.webm"); - if (!video.exists() && !(video.size() > 0)) { - emit createWallpaperStateChanged(Create::State::ConvertingVideoError); - return false; - } - } - - proConvertVideo.data()->close(); - emit createWallpaperStateChanged(Create::State::ConvertingVideoFinished); - return true; } @@ -494,18 +389,19 @@ bool Create::createWallpaperProjectFile(const QString title, const QString descr configObj.insert("file", "video.webm"); configObj.insert("preview", "preview.png"); configObj.insert("previewGIF", "preview.gif"); - configObj.insert("previewMP4", "preview.mp4"); + configObj.insert("previewWebM", "preview.webm"); configObj.insert("type", "video"); QJsonDocument configJsonDocument(configObj); out << configJsonDocument.toJson(); configFile.close(); - return true; emit createWallpaperStateChanged(Create::State::Finished); + + return true; } -void Create::abort() +void Create::abortAndCleanup() { emit abortCreateWallpaper(); m_futureWatcher.cancel(); @@ -516,6 +412,8 @@ void Create::abort() if (!exportPath.removeRecursively()) { emit createWallpaperStateChanged(Create::State::AbortCleanupError); qWarning() << "Could not delete temp exportPath: " << exportPath; + } else { + qDebug() << "cleanup " << m_createWallpaperData.exportPath; } } } diff --git a/ScreenPlay/src/create.h b/ScreenPlay/src/create.h index dfc6911b..5c784609 100644 --- a/ScreenPlay/src/create.h +++ b/ScreenPlay/src/create.h @@ -50,21 +50,23 @@ public: AnalyseVideo, AnalyseVideoFinished, AnalyseVideoError, - ConvertingPreviewImage, - ConvertingPreviewImageFinished, - ConvertingPreviewImageError, ConvertingPreviewVideo, ConvertingPreviewVideoFinished, - ConvertingPreviewVideoError, //10 + ConvertingPreviewVideoError, ConvertingPreviewGif, ConvertingPreviewGifFinished, ConvertingPreviewGifError, + ConvertingPreviewImage, + ConvertingPreviewImageFinished, + ConvertingPreviewImageError, ConvertingAudio, ConvertingAudioFinished, ConvertingAudioError, - ConvertingVideo, - ConvertingVideoFinished, - ConvertingVideoError, +// Oh well... Due to so many patents around video codecs +// the user has to convert the video on his own :( +// ConvertingVideo, +// ConvertingVideoFinished, +// ConvertingVideoError, AbortCleanupError, Finished, ErrorUnknown, @@ -97,11 +99,11 @@ public slots: void createWallpaperStart(QString videoPath); bool createWallpaperInfo(); bool createWallpaperVideoPreview(); - bool createWallpaperVideo(); + bool createWallpaperGifPreview(); + bool createWallpaperImagePreview(); + bool extractWallpaperAudio(); bool createWallpaperProjectFile(const QString title, const QString description); - - void abort(); - + void abortAndCleanup(); void setWorkingDir(QString workingDir) {