mirror of
https://gitlab.com/kelteseth/ScreenPlay.git
synced 2024-11-07 03:22:33 +01:00
Refactor window
Refactor wallpaper convertion
This commit is contained in:
parent
f7336a4ba3
commit
31757b4e31
@ -10,6 +10,7 @@ TARGETPATH = ScreenPlay
|
|||||||
ICON = favicon.ico
|
ICON = favicon.ico
|
||||||
|
|
||||||
SOURCES += main.cpp \
|
SOURCES += main.cpp \
|
||||||
|
src/createimportvideo.cpp \
|
||||||
src/installedlistmodel.cpp \
|
src/installedlistmodel.cpp \
|
||||||
src/monitorlistmodel.cpp \
|
src/monitorlistmodel.cpp \
|
||||||
src/settings.cpp \
|
src/settings.cpp \
|
||||||
@ -30,6 +31,7 @@ TRANSLATIONS = translations/ScreenPlay_en.ts \
|
|||||||
translations/ScreenPlay_de.ts
|
translations/ScreenPlay_de.ts
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
src/createimportvideo.h \
|
||||||
src/installedlistmodel.h \
|
src/installedlistmodel.h \
|
||||||
src/monitorlistmodel.h \
|
src/monitorlistmodel.h \
|
||||||
src/settings.h \
|
src/settings.h \
|
||||||
|
@ -30,7 +30,6 @@ int main(int argc, char* argv[])
|
|||||||
QGuiApplication::setApplicationVersion("0.2.0");
|
QGuiApplication::setApplicationVersion("0.2.0");
|
||||||
|
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
app.setQuitOnLastWindowClosed(false);
|
app.setQuitOnLastWindowClosed(false);
|
||||||
app.setWindowIcon(QIcon(":/assets/icons/favicon.ico"));
|
app.setWindowIcon(QIcon(":/assets/icons/favicon.ico"));
|
||||||
|
|
||||||
@ -54,6 +53,7 @@ int main(int argc, char* argv[])
|
|||||||
ProfileListModel profileListModel;
|
ProfileListModel profileListModel;
|
||||||
SDKConnector sdkConnector;
|
SDKConnector sdkConnector;
|
||||||
|
|
||||||
|
|
||||||
// Create settings in the end because for now it depends on
|
// Create settings in the end because for now it depends on
|
||||||
// such things as the profile list model to complete
|
// such things as the profile list model to complete
|
||||||
// It will also set the m_absoluteStoragePath in profileListModel and installedListModel
|
// It will also set the m_absoluteStoragePath in profileListModel and installedListModel
|
||||||
|
@ -5,7 +5,7 @@ import Qt.labs.platform 1.0
|
|||||||
import QtQuick.Controls.Material 2.2
|
import QtQuick.Controls.Material 2.2
|
||||||
import QtQuick.Controls.Styles 1.4
|
import QtQuick.Controls.Styles 1.4
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.3
|
||||||
import RemoteWorkshopCreationStatus 1.0
|
//import RemoteWorkshopCreationStatus 1.0
|
||||||
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@ -8,6 +8,10 @@ import net.aimber.create 1.0
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: wrapperContent
|
id: wrapperContent
|
||||||
|
|
||||||
|
|
||||||
|
property string customVideoPreviewPath: ""
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: txtHeadline
|
id: txtHeadline
|
||||||
text: qsTr("Convert a video to a wallpaper")
|
text: qsTr("Convert a video to a wallpaper")
|
||||||
@ -261,7 +265,7 @@ Item {
|
|||||||
Material.background: Material.Gray
|
Material.background: Material.Gray
|
||||||
Material.foreground: "white"
|
Material.foreground: "white"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
screenPlayCreate.abort()
|
screenPlayCreate.abortAndCleanup()
|
||||||
utility.setNavigationActive(true)
|
utility.setNavigationActive(true)
|
||||||
utility.setNavigation("Create")
|
utility.setNavigation("Create")
|
||||||
}
|
}
|
||||||
@ -290,3 +294,10 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*##^## Designer {
|
||||||
|
D{i:0;autoSize:true;height:480;width:640}
|
||||||
|
}
|
||||||
|
##^##*/
|
||||||
|
@ -13,17 +13,16 @@ Item {
|
|||||||
|
|
||||||
property string filePath
|
property string filePath
|
||||||
property bool canNext: false
|
property bool canNext: false
|
||||||
property int importState: CreateWallpaperWizard.ImportState.Import
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
state = "in"
|
state = "in"
|
||||||
utility.setNavigationActive(false)
|
utility.setNavigationActive(false)
|
||||||
if (importState === CreateWallpaperWizard.ImportState.Import) {
|
loader_wrapperContent.source = "qrc:/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml"
|
||||||
loader_wrapperContent.source
|
// if (importState === CreateWallpaperWizard.ImportState.Import) {
|
||||||
= "qrc:/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImport.qml"
|
// loader_wrapperContent.source
|
||||||
} else {
|
// = "qrc:/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImport.qml"
|
||||||
loader_wrapperContent.source = "qrc:/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml"
|
// } else {
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
//Blocks some MouseArea from create page
|
//Blocks some MouseArea from create page
|
||||||
|
@ -177,23 +177,23 @@ Item {
|
|||||||
bottom: parent.bottom
|
bottom: parent.bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
// Text {
|
||||||
id: text1
|
// id: text1
|
||||||
height: 29
|
// height: 29
|
||||||
text: screenTitle
|
// text: screenTitle
|
||||||
anchors {
|
// anchors {
|
||||||
right: parent.right
|
// right: parent.right
|
||||||
left: parent.left
|
// left: parent.left
|
||||||
top: parent.top
|
// top: parent.top
|
||||||
margins: 10
|
// margins: 10
|
||||||
}
|
// }
|
||||||
wrapMode: Text.WordWrap
|
// wrapMode: Text.WordWrap
|
||||||
|
|
||||||
color: "#2F2F2F"
|
// color: "#2F2F2F"
|
||||||
font.pointSize: 9
|
// font.pointSize: 9
|
||||||
|
|
||||||
font.family: "Segoe UI, Roboto"
|
// font.family: "Segoe UI, Roboto"
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,5 @@ Theme=Light
|
|||||||
Accent=Orange
|
Accent=Orange
|
||||||
Primary=White
|
Primary=White
|
||||||
Foreground=Grey
|
Foreground=Grey
|
||||||
|
Font\Family=Roboto
|
||||||
|
Font\PixelSize=12
|
||||||
[Material\Font]
|
|
||||||
Family=Roboto
|
|
||||||
PixelSize=14
|
|
||||||
|
@ -6,9 +6,8 @@ Create::Create(Settings* st, QMLUtilities* util, QObject* parent)
|
|||||||
|
|
||||||
m_settings = st;
|
m_settings = st;
|
||||||
m_utils = util;
|
m_utils = util;
|
||||||
m_futureWatcher.setFuture(m_future);
|
|
||||||
|
|
||||||
qRegisterMetaType<Create::State>();
|
qRegisterMetaType<CreateImportVideo::State>();
|
||||||
qmlRegisterType<Create>("net.aimber.create", 1, 0, "Create");
|
qmlRegisterType<Create>("net.aimber.create", 1, 0, "Create");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,17 +32,19 @@ bool Create::copyRecursively(const QString& srcFilePath, const QString& tgtFileP
|
|||||||
targetDir.cdUp();
|
targetDir.cdUp();
|
||||||
QDir sourceDir(srcFilePath);
|
QDir sourceDir(srcFilePath);
|
||||||
QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
|
QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
|
||||||
foreach (const QString& fileName, fileNames) {
|
Q_FOREACH (const QString& fileName, fileNames) {
|
||||||
const QString newSrcFilePath
|
const QString newSrcFilePath
|
||||||
= srcFilePath + QLatin1Char('/') + fileName;
|
= srcFilePath + QLatin1Char('/') + fileName;
|
||||||
const QString newTgtFilePath
|
const QString newTgtFilePath
|
||||||
= tgtFilePath + QLatin1Char('/') + fileName;
|
= tgtFilePath + QLatin1Char('/') + fileName;
|
||||||
if (!copyRecursively(newSrcFilePath, newTgtFilePath))
|
if (!copyRecursively(newSrcFilePath, newTgtFilePath)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!QFile::copy(srcFilePath, tgtFilePath))
|
if (!QFile::copy(srcFilePath, tgtFilePath)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -52,365 +53,44 @@ void Create::createWallpaperStart(QString videoPath)
|
|||||||
{
|
{
|
||||||
videoPath.remove("file:///");
|
videoPath.remove("file:///");
|
||||||
|
|
||||||
m_future = QtConcurrent::run([=]() {
|
QDir dir;
|
||||||
QDir dir;
|
dir.cd(this->m_settings->localStoragePath().toLocalFile());
|
||||||
dir.cd(this->m_settings->localStoragePath().toLocalFile());
|
|
||||||
|
|
||||||
m_createWallpaperData.videoPath = videoPath;
|
m_createWallpaperData.videoPath = videoPath;
|
||||||
|
|
||||||
// Create a temp dir so we can later alter it to the workshop id
|
// Create a temp dir so we can later alter it to the workshop id
|
||||||
auto folderName = QString("_tmp_" + QTime::currentTime().toString()).replace(":", "");
|
auto folderName = QString("_tmp_" + QTime::currentTime().toString()).replace(":", "");
|
||||||
|
|
||||||
if (!dir.mkdir(folderName))
|
if (!dir.mkdir(folderName)) {
|
||||||
return;
|
emit abortCreateWallpaper();
|
||||||
|
return;
|
||||||
m_createWallpaperData.exportPath = dir.path() + "/" + folderName;
|
|
||||||
this->setWorkingDir(m_createWallpaperData.exportPath);
|
|
||||||
|
|
||||||
// If we return early/false this means the creation
|
|
||||||
// process did not work
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (!this->createWallpaperInfo())
|
|
||||||
ok = false;
|
|
||||||
|
|
||||||
if (ok && !this->createWallpaperVideoPreview())
|
|
||||||
ok = false;
|
|
||||||
|
|
||||||
if (ok && !this->createWallpaperGifPreview())
|
|
||||||
ok = false;
|
|
||||||
|
|
||||||
if (ok && !this->extractWallpaperAudio())
|
|
||||||
ok = false;
|
|
||||||
|
|
||||||
if (!ok)
|
|
||||||
abortAndCleanup();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Create::createWallpaperInfo()
|
|
||||||
{
|
|
||||||
// Get video info
|
|
||||||
QStringList args;
|
|
||||||
args.append("-print_format");
|
|
||||||
args.append("json");
|
|
||||||
args.append("-show_format");
|
|
||||||
args.append("-show_streams");
|
|
||||||
args.append(m_createWallpaperData.videoPath);
|
|
||||||
QScopedPointer<QProcess> pro(new QProcess());
|
|
||||||
pro.data()->setArguments(args);
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
pro.data()->setProgram(QApplication::applicationDirPath() + "/ffprobe.exe");
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
pro.data()->setProgram(QApplication::applicationDirPath() + "/ffprobe");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pro.data()->start();
|
|
||||||
emit createWallpaperStateChanged(Create::State::AnalyseVideo);
|
|
||||||
pro.data()->waitForFinished(-1);
|
|
||||||
emit createWallpaperStateChanged(Create::State::AnalyseVideoFinished);
|
|
||||||
QJsonObject obj;
|
|
||||||
QJsonParseError err;
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(pro.data()->readAll(), &err);
|
|
||||||
if (err.error != QJsonParseError::NoError) {
|
|
||||||
emit processOutput("Error parsing ffmpeg json output");
|
|
||||||
emit createWallpaperStateChanged(Create::State::AnalyseVideoError);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = doc.object();
|
m_createWallpaperData.exportPath = dir.path() + "/" + folderName;
|
||||||
pro.data()->close();
|
setWorkingDir(m_createWallpaperData.exportPath);
|
||||||
|
|
||||||
// Get video length
|
auto* thread = new QThread;
|
||||||
QJsonObject objFormat = obj.value("format").toObject();
|
m_createImportVideo = new CreateImportVideo(videoPath, m_createWallpaperData.exportPath);
|
||||||
bool okParseDuration = false;
|
connect(m_createImportVideo, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
|
||||||
auto tmpLength = objFormat.value("duration").toVariant().toFloat(&okParseDuration);
|
connect(thread, &QThread::started, m_createImportVideo, &CreateImportVideo::process);
|
||||||
|
connect(m_createImportVideo, &CreateImportVideo::finished, thread, &QThread::quit);
|
||||||
if (!okParseDuration) {
|
connect(m_createImportVideo, &CreateImportVideo::finished, m_createImportVideo, &QObject::deleteLater);
|
||||||
qDebug() << "Error parsing video length";
|
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||||
emit processOutput("Error parsing video length");
|
m_createImportVideo->moveToThread(thread);
|
||||||
emit createWallpaperStateChanged(Create::State::AnalyseVideoError);
|
thread->start();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = 0;
|
|
||||||
length = static_cast<int>(tmpLength);
|
|
||||||
m_createWallpaperData.length = length;
|
|
||||||
|
|
||||||
// Get framerate
|
|
||||||
QJsonArray arrSteams = obj.value("streams").toArray();
|
|
||||||
if (arrSteams.size() < 1) {
|
|
||||||
qDebug() << "Error container does not have any video streams";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject tmpObjStreams = arrSteams.at(0).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
|
|
||||||
QString avgFrameRate = tmpObjStreams.value("avg_frame_rate").toVariant().toString();
|
|
||||||
|
|
||||||
QStringList avgFrameRateList = avgFrameRate.split('/', QString::SkipEmptyParts);
|
|
||||||
if (avgFrameRateList.length() != 2) {
|
|
||||||
qDebug() << "Error could not parse streams with length: " << avgFrameRateList.length();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int framerate = 0;
|
|
||||||
float value1 = static_cast<float>(avgFrameRateList.at(0).toInt());
|
|
||||||
float value2 = static_cast<float>(avgFrameRateList.at(1).toInt());
|
|
||||||
|
|
||||||
framerate = qCeil(value1 / value2);
|
|
||||||
m_createWallpaperData.framerate = framerate;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Create::createWallpaperVideoPreview()
|
|
||||||
{
|
|
||||||
|
|
||||||
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<QProcess> 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<QProcess> 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);
|
|
||||||
|
|
||||||
QStringList args;
|
|
||||||
args.clear();
|
|
||||||
args.append("-y");
|
|
||||||
args.append("-stats");
|
|
||||||
args.append("-ss");
|
|
||||||
args.append("00:00:02");
|
|
||||||
args.append("-i");
|
|
||||||
args.append(m_createWallpaperData.videoPath);
|
|
||||||
args.append("-vframes");
|
|
||||||
args.append("1");
|
|
||||||
args.append("-q:v");
|
|
||||||
args.append("2");
|
|
||||||
args.append(m_createWallpaperData.exportPath + "/preview.png");
|
|
||||||
|
|
||||||
QScopedPointer<QProcess> proConvertImage(new QProcess());
|
|
||||||
proConvertImage.data()->setArguments(args);
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
proConvertImage.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg.exe");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
proConvertImage.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg");
|
|
||||||
#endif
|
|
||||||
proConvertImage.data()->start();
|
|
||||||
|
|
||||||
while (!proConvertImage.data()->waitForFinished(100)) //Wake up every 100ms and check if we must exit
|
|
||||||
{
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
QString tmpErrImg = proConvertImage.data()->readAllStandardError();
|
|
||||||
if (!tmpErrImg.isEmpty()) {
|
|
||||||
QFile previewImg(m_createWallpaperData.exportPath + "/preview.png");
|
|
||||||
if (!previewImg.exists() && !(previewImg.size() > 0)) {
|
|
||||||
emit createWallpaperStateChanged(Create::State::ConvertingPreviewImageError);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->processOutput(proConvertImage.data()->readAll());
|
|
||||||
proConvertImage.data()->close();
|
|
||||||
emit createWallpaperStateChanged(Create::State::ConvertingPreviewImageFinished);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Create::extractWallpaperAudio()
|
|
||||||
{
|
|
||||||
|
|
||||||
emit createWallpaperStateChanged(Create::State::ConvertingAudio);
|
|
||||||
|
|
||||||
QStringList args;
|
|
||||||
args.clear();
|
|
||||||
args.append("-y");
|
|
||||||
args.append("-stats");
|
|
||||||
args.append("-i");
|
|
||||||
args.append(m_createWallpaperData.videoPath);
|
|
||||||
args.append("-f");
|
|
||||||
args.append("mp3");
|
|
||||||
args.append("-ab");
|
|
||||||
args.append("192000");
|
|
||||||
args.append("-vn");
|
|
||||||
args.append(m_createWallpaperData.exportPath + "/audio.mp3");
|
|
||||||
|
|
||||||
QScopedPointer<QProcess> proConvertAudio(new QProcess());
|
|
||||||
proConvertAudio.data()->setArguments(args);
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
proConvertAudio.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg.exe");
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
pro.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
connect(this, &Create::abortCreateWallpaper, proConvertAudio.data(), &QProcess::kill);
|
|
||||||
proConvertAudio.data()->start(QIODevice::ReadOnly);
|
|
||||||
while (!proConvertAudio.data()->waitForFinished(100)) //Wake up every 100ms and check if we must exit
|
|
||||||
{
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
disconnect(this, &Create::abortCreateWallpaper, proConvertAudio.data(), &QProcess::kill);
|
|
||||||
|
|
||||||
QString tmpErrImg = proConvertAudio.data()->readAllStandardError();
|
|
||||||
if (!tmpErrImg.isEmpty()) {
|
|
||||||
QFile previewImg(m_createWallpaperData.exportPath + "/audio.mp3");
|
|
||||||
if (!previewImg.exists() && !(previewImg.size() > 0)) {
|
|
||||||
emit createWallpaperStateChanged(Create::State::ConvertingAudioError);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->processOutput(proConvertAudio.data()->readAll());
|
|
||||||
proConvertAudio.data()->close();
|
|
||||||
emit createWallpaperStateChanged(Create::State::ConvertingAudioFinished);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Create::createWallpaperProjectFile(const QString title, const QString description)
|
|
||||||
{
|
|
||||||
//Copy Project File
|
|
||||||
QFile configFile(m_createWallpaperData.exportPath + "/project.json");
|
|
||||||
|
|
||||||
if (!configFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream out(&configFile);
|
|
||||||
QJsonObject configObj;
|
|
||||||
|
|
||||||
configObj.insert("description", description);
|
|
||||||
configObj.insert("title", title);
|
|
||||||
|
|
||||||
configObj.insert("file", "video.webm");
|
|
||||||
configObj.insert("preview", "preview.png");
|
|
||||||
configObj.insert("previewGIF", "preview.gif");
|
|
||||||
configObj.insert("previewWebM", "preview.webm");
|
|
||||||
configObj.insert("type", "video");
|
|
||||||
|
|
||||||
QJsonDocument configJsonDocument(configObj);
|
|
||||||
out << configJsonDocument.toJson();
|
|
||||||
configFile.close();
|
|
||||||
|
|
||||||
emit createWallpaperStateChanged(Create::State::Finished);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Create::abortAndCleanup()
|
void Create::abortAndCleanup()
|
||||||
{
|
{
|
||||||
emit abortCreateWallpaper();
|
emit abortCreateWallpaper();
|
||||||
m_futureWatcher.cancel();
|
|
||||||
|
|
||||||
|
|
||||||
QDir exportPath(m_createWallpaperData.exportPath);
|
QDir exportPath(m_createWallpaperData.exportPath);
|
||||||
|
|
||||||
if (exportPath.exists()) {
|
if (exportPath.exists()) {
|
||||||
if (!exportPath.removeRecursively()) {
|
if (!exportPath.removeRecursively()) {
|
||||||
emit createWallpaperStateChanged(Create::State::AbortCleanupError);
|
emit createWallpaperStateChanged(CreateImportVideo::State::AbortCleanupError);
|
||||||
qWarning() << "Could not delete temp exportPath: " << exportPath;
|
qWarning() << "Could not delete temp exportPath: " << exportPath;
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "cleanup " << m_createWallpaperData.exportPath;
|
qDebug() << "cleanup " << m_createWallpaperData.exportPath;
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "createimportvideo.h"
|
||||||
#include "qmlutilities.h"
|
#include "qmlutilities.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
@ -33,6 +35,8 @@ struct CreateWallpaperData {
|
|||||||
int framerate = 0;
|
int framerate = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Create : public QObject {
|
class Create : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@ -44,35 +48,6 @@ public:
|
|||||||
Create() {}
|
Create() {}
|
||||||
~Create() {}
|
~Create() {}
|
||||||
|
|
||||||
enum class State {
|
|
||||||
Idle,
|
|
||||||
Started,
|
|
||||||
AnalyseVideo,
|
|
||||||
AnalyseVideoFinished,
|
|
||||||
AnalyseVideoError,
|
|
||||||
ConvertingPreviewVideo,
|
|
||||||
ConvertingPreviewVideoFinished,
|
|
||||||
ConvertingPreviewVideoError,
|
|
||||||
ConvertingPreviewGif,
|
|
||||||
ConvertingPreviewGifFinished,
|
|
||||||
ConvertingPreviewGifError,
|
|
||||||
ConvertingPreviewImage,
|
|
||||||
ConvertingPreviewImageFinished,
|
|
||||||
ConvertingPreviewImageError,
|
|
||||||
ConvertingAudio,
|
|
||||||
ConvertingAudioFinished,
|
|
||||||
ConvertingAudioError,
|
|
||||||
// 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,
|
|
||||||
};
|
|
||||||
Q_ENUM(State)
|
|
||||||
|
|
||||||
QString workingDir() const
|
QString workingDir() const
|
||||||
{
|
{
|
||||||
return m_workingDir;
|
return m_workingDir;
|
||||||
@ -84,7 +59,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void createWallpaperStateChanged(Create::State state);
|
void createWallpaperStateChanged(CreateImportVideo::State state);
|
||||||
void processOutput(QString text);
|
void processOutput(QString text);
|
||||||
void workingDirChanged(QString workingDir);
|
void workingDirChanged(QString workingDir);
|
||||||
void progressChanged(float progress);
|
void progressChanged(float progress);
|
||||||
@ -93,17 +68,8 @@ signals:
|
|||||||
public slots:
|
public slots:
|
||||||
void copyProject(QString relativeProjectPath, QString toPath);
|
void copyProject(QString relativeProjectPath, QString toPath);
|
||||||
bool copyRecursively(const QString& srcFilePath, const QString& tgtFilePath);
|
bool copyRecursively(const QString& srcFilePath, const QString& tgtFilePath);
|
||||||
|
|
||||||
// Steps to convert any video to a wallpaper broken down into
|
|
||||||
// several methods in this order:
|
|
||||||
void createWallpaperStart(QString videoPath);
|
|
||||||
bool createWallpaperInfo();
|
|
||||||
bool createWallpaperVideoPreview();
|
|
||||||
bool createWallpaperGifPreview();
|
|
||||||
bool createWallpaperImagePreview();
|
|
||||||
bool extractWallpaperAudio();
|
|
||||||
bool createWallpaperProjectFile(const QString title, const QString description);
|
|
||||||
void abortAndCleanup();
|
void abortAndCleanup();
|
||||||
|
void createWallpaperStart(QString videoPath);
|
||||||
|
|
||||||
void setWorkingDir(QString workingDir)
|
void setWorkingDir(QString workingDir)
|
||||||
{
|
{
|
||||||
@ -124,11 +90,11 @@ public slots:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
CreateImportVideo* m_createImportVideo;
|
||||||
Settings* m_settings;
|
Settings* m_settings;
|
||||||
QMLUtilities* m_utils;
|
QMLUtilities* m_utils;
|
||||||
CreateWallpaperData m_createWallpaperData;
|
CreateWallpaperData m_createWallpaperData;
|
||||||
QString m_workingDir;
|
QString m_workingDir;
|
||||||
float m_progress = 0.0f;
|
float m_progress = 0.0f;
|
||||||
QFuture<void> m_future;
|
|
||||||
QFutureWatcher<void> m_futureWatcher;
|
|
||||||
};
|
};
|
||||||
|
374
ScreenPlay/src/createimportvideo.cpp
Normal file
374
ScreenPlay/src/createimportvideo.cpp
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
#include "createimportvideo.h"
|
||||||
|
|
||||||
|
CreateImportVideo::CreateImportVideo(QString videoPath, QString exportPath, QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
m_videoPath = videoPath;
|
||||||
|
m_exportPath = exportPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateImportVideo::process()
|
||||||
|
{
|
||||||
|
qDebug() << "start converting video" << QThread::currentThreadId();
|
||||||
|
createWallpaperInfo();
|
||||||
|
createWallpaperVideoPreview();
|
||||||
|
createWallpaperGifPreview();
|
||||||
|
extractWallpaperAudio();
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateImportVideo::createWallpaperInfo()
|
||||||
|
{
|
||||||
|
// Get video info
|
||||||
|
QStringList args;
|
||||||
|
args.append("-print_format");
|
||||||
|
args.append("json");
|
||||||
|
args.append("-show_format");
|
||||||
|
args.append("-show_streams");
|
||||||
|
args.append(m_videoPath);
|
||||||
|
QScopedPointer<QProcess> pro(new QProcess());
|
||||||
|
pro.data()->setArguments(args);
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
pro.data()->setProgram(QApplication::applicationDirPath() + "/ffprobe.exe");
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
pro.data()->setProgram(QApplication::applicationDirPath() + "/ffprobe");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pro.data()->start();
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::AnalyseVideo);
|
||||||
|
while (!pro.data()->waitForFinished(100)) {
|
||||||
|
if (QThread::currentThread()->isInterruptionRequested()) {
|
||||||
|
qDebug() << "Interrupt thread";
|
||||||
|
pro.data()->terminate();
|
||||||
|
if (!pro.data()->waitForFinished(1000)) {
|
||||||
|
pro.data()->kill();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::AnalyseVideoFinished);
|
||||||
|
QJsonObject obj;
|
||||||
|
QJsonParseError err;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(pro.data()->readAll(), &err);
|
||||||
|
if (err.error != QJsonParseError::NoError) {
|
||||||
|
emit processOutput("Error parsing ffmpeg json output");
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::AnalyseVideoError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = doc.object();
|
||||||
|
pro.data()->close();
|
||||||
|
|
||||||
|
// Get video length
|
||||||
|
QJsonObject objFormat = obj.value("format").toObject();
|
||||||
|
bool okParseDuration = false;
|
||||||
|
auto tmpLength = objFormat.value("duration").toVariant().toFloat(&okParseDuration);
|
||||||
|
|
||||||
|
if (!okParseDuration) {
|
||||||
|
qDebug() << "Error parsing video length";
|
||||||
|
emit processOutput("Error parsing video length");
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::AnalyseVideoError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length = 0;
|
||||||
|
length = static_cast<int>(tmpLength);
|
||||||
|
m_length = length;
|
||||||
|
|
||||||
|
// Get framerate
|
||||||
|
QJsonArray arrSteams = obj.value("streams").toArray();
|
||||||
|
if (arrSteams.size() < 1) {
|
||||||
|
qDebug() << "Error container does not have any video streams";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject tmpObjStreams = arrSteams.at(0).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
|
||||||
|
QString avgFrameRate = tmpObjStreams.value("avg_frame_rate").toVariant().toString();
|
||||||
|
|
||||||
|
QStringList avgFrameRateList = avgFrameRate.split('/', QString::SkipEmptyParts);
|
||||||
|
if (avgFrameRateList.length() != 2) {
|
||||||
|
qDebug() << "Error could not parse streams with length: " << avgFrameRateList.length();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int framerate = 0;
|
||||||
|
double value1 = static_cast<double>(avgFrameRateList.at(0).toInt());
|
||||||
|
double value2 = static_cast<double>(avgFrameRateList.at(1).toInt());
|
||||||
|
|
||||||
|
framerate = qCeil(value1 / value2);
|
||||||
|
m_framerate = framerate;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateImportVideo::createWallpaperVideoPreview()
|
||||||
|
{
|
||||||
|
|
||||||
|
QStringList args;
|
||||||
|
// args.append("-loglevel");
|
||||||
|
// args.append("error");
|
||||||
|
// args.append("-y");
|
||||||
|
// args.append("-stats");
|
||||||
|
args.append("-i");
|
||||||
|
args.append(m_videoPath);
|
||||||
|
|
||||||
|
//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_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_exportPath + "/preview.webm");
|
||||||
|
QScopedPointer<QProcess> proConvertPreviewWebM(new QProcess());
|
||||||
|
|
||||||
|
qDebug() << args;
|
||||||
|
|
||||||
|
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(CreateImportVideo::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
|
||||||
|
{
|
||||||
|
if (QThread::currentThread()->isInterruptionRequested()) {
|
||||||
|
qDebug() << "Interrupt thread";
|
||||||
|
proConvertPreviewWebM.data()->terminate();
|
||||||
|
if (!proConvertPreviewWebM.data()->waitForFinished(1000)) {
|
||||||
|
proConvertPreviewWebM.data()->kill();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
//disconnect(this, &Create::abortCreateWallpaper, proConvertPreviewWebM.data(), &QProcess::kill);
|
||||||
|
QString tmpErr = proConvertPreviewWebM.data()->readAllStandardError();
|
||||||
|
if (!tmpErr.isEmpty()) {
|
||||||
|
QFile previewVideo(m_exportPath + "/preview.webm");
|
||||||
|
if (!previewVideo.exists() && !(previewVideo.size() > 0)) {
|
||||||
|
emit processOutput(tmpErr);
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingPreviewVideoError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//this->processOutput(proConvertPreviewWebM.data()->readAll());
|
||||||
|
proConvertPreviewWebM.data()->close();
|
||||||
|
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingPreviewVideoFinished);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateImportVideo::createWallpaperGifPreview()
|
||||||
|
{
|
||||||
|
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingPreviewGif);
|
||||||
|
|
||||||
|
QStringList args;
|
||||||
|
args.append("-y");
|
||||||
|
args.append("-stats");
|
||||||
|
args.append("-i");
|
||||||
|
args.append(m_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_exportPath + "/preview.gif");
|
||||||
|
|
||||||
|
QScopedPointer<QProcess> 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
|
||||||
|
{
|
||||||
|
if (QThread::currentThread()->isInterruptionRequested()) {
|
||||||
|
qDebug() << "Interrupt thread";
|
||||||
|
proConvertGif.data()->terminate();
|
||||||
|
if (!proConvertGif.data()->waitForFinished(1000)) {
|
||||||
|
proConvertGif.data()->kill();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
//disconnect(this, &Create::abortCreateWallpaper, proConvertGif.data(), &QProcess::kill);
|
||||||
|
QString tmpErrGif = proConvertGif.data()->readAllStandardError();
|
||||||
|
if (!tmpErrGif.isEmpty()) {
|
||||||
|
QFile previewGif(m_exportPath + "/preview.gif");
|
||||||
|
if (!previewGif.exists() && !(previewGif.size() > 0)) {
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingPreviewGifError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//this->processOutput(proConvertGif.data()->readAll());
|
||||||
|
proConvertGif.data()->close();
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingPreviewGifFinished);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateImportVideo::createWallpaperImagePreview()
|
||||||
|
{
|
||||||
|
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingPreviewImage);
|
||||||
|
|
||||||
|
QStringList args;
|
||||||
|
args.clear();
|
||||||
|
args.append("-y");
|
||||||
|
args.append("-stats");
|
||||||
|
args.append("-ss");
|
||||||
|
args.append("00:00:02");
|
||||||
|
args.append("-i");
|
||||||
|
args.append(m_videoPath);
|
||||||
|
args.append("-vframes");
|
||||||
|
args.append("1");
|
||||||
|
args.append("-q:v");
|
||||||
|
args.append("2");
|
||||||
|
args.append(m_exportPath + "/preview.png");
|
||||||
|
|
||||||
|
QScopedPointer<QProcess> proConvertImage(new QProcess());
|
||||||
|
proConvertImage.data()->setArguments(args);
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
proConvertImage.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg.exe");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
proConvertImage.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg");
|
||||||
|
#endif
|
||||||
|
proConvertImage.data()->start();
|
||||||
|
|
||||||
|
while (!proConvertImage.data()->waitForFinished(100)) //Wake up every 100ms and check if we must exit
|
||||||
|
{
|
||||||
|
if (QThread::currentThread()->isInterruptionRequested()) {
|
||||||
|
qDebug() << "Interrupt thread";
|
||||||
|
proConvertImage.data()->terminate();
|
||||||
|
if (!proConvertImage.data()->waitForFinished(1000)) {
|
||||||
|
proConvertImage.data()->kill();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
QString tmpErrImg = proConvertImage.data()->readAllStandardError();
|
||||||
|
if (!tmpErrImg.isEmpty()) {
|
||||||
|
QFile previewImg(m_exportPath + "/preview.png");
|
||||||
|
if (!previewImg.exists() && !(previewImg.size() > 0)) {
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingPreviewImageError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//this->processOutput(proConvertImage.data()->readAll());
|
||||||
|
proConvertImage.data()->close();
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingPreviewImageFinished);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateImportVideo::extractWallpaperAudio()
|
||||||
|
{
|
||||||
|
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingAudio);
|
||||||
|
|
||||||
|
QStringList args;
|
||||||
|
args.clear();
|
||||||
|
args.append("-y");
|
||||||
|
args.append("-stats");
|
||||||
|
args.append("-i");
|
||||||
|
args.append(m_videoPath);
|
||||||
|
args.append("-f");
|
||||||
|
args.append("mp3");
|
||||||
|
args.append("-ab");
|
||||||
|
args.append("192000");
|
||||||
|
args.append("-vn");
|
||||||
|
args.append(m_exportPath + "/audio.mp3");
|
||||||
|
|
||||||
|
QScopedPointer<QProcess> proConvertAudio(new QProcess());
|
||||||
|
proConvertAudio.data()->setArguments(args);
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
proConvertAudio.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg.exe");
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
pro.data()->setProgram(QApplication::applicationDirPath() + "/ffmpeg");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//connect(this, &Create::abortCreateWallpaper, proConvertAudio.data(), &QProcess::kill);
|
||||||
|
proConvertAudio.data()->start(QIODevice::ReadOnly);
|
||||||
|
while (!proConvertAudio.data()->waitForFinished(100)) //Wake up every 100ms and check if we must exit
|
||||||
|
{
|
||||||
|
if (QThread::currentThread()->isInterruptionRequested()) {
|
||||||
|
qDebug() << "Interrupt thread";
|
||||||
|
proConvertAudio.data()->terminate();
|
||||||
|
if (!proConvertAudio.data()->waitForFinished(1000)) {
|
||||||
|
proConvertAudio.data()->kill();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
//disconnect(this, &Create::abortCreateWallpaper, proConvertAudio.data(), &QProcess::kill);
|
||||||
|
|
||||||
|
QString tmpErrImg = proConvertAudio.data()->readAllStandardError();
|
||||||
|
if (!tmpErrImg.isEmpty()) {
|
||||||
|
QFile previewImg(m_exportPath + "/audio.mp3");
|
||||||
|
if (!previewImg.exists() && !(previewImg.size() > 0)) {
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingAudioError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//this->processOutput(proConvertAudio.data()->readAll());
|
||||||
|
proConvertAudio.data()->close();
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::ConvertingAudioFinished);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateImportVideo::createWallpaperProjectFile(const QString title, const QString description)
|
||||||
|
{
|
||||||
|
//Copy Project File
|
||||||
|
QFile configFile(m_exportPath + "/project.json");
|
||||||
|
|
||||||
|
if (!configFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream out(&configFile);
|
||||||
|
QJsonObject configObj;
|
||||||
|
|
||||||
|
configObj.insert("description", description);
|
||||||
|
configObj.insert("title", title);
|
||||||
|
|
||||||
|
configObj.insert("file", "video.webm");
|
||||||
|
configObj.insert("preview", "preview.png");
|
||||||
|
configObj.insert("previewGIF", "preview.gif");
|
||||||
|
configObj.insert("previewWebM", "preview.webm");
|
||||||
|
configObj.insert("type", "video");
|
||||||
|
|
||||||
|
QJsonDocument configJsonDocument(configObj);
|
||||||
|
out << configJsonDocument.toJson();
|
||||||
|
configFile.close();
|
||||||
|
|
||||||
|
emit createWallpaperStateChanged(CreateImportVideo::State::Finished);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
77
ScreenPlay/src/createimportvideo.h
Normal file
77
ScreenPlay/src/createimportvideo.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonParseError>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QtMath>
|
||||||
|
|
||||||
|
class CreateImportVideo : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit CreateImportVideo(QString videoPath, QString exportPath, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
enum class State {
|
||||||
|
Idle,
|
||||||
|
Started,
|
||||||
|
AnalyseVideo,
|
||||||
|
AnalyseVideoFinished,
|
||||||
|
AnalyseVideoError,
|
||||||
|
ConvertingPreviewVideo,
|
||||||
|
ConvertingPreviewVideoFinished,
|
||||||
|
ConvertingPreviewVideoError,
|
||||||
|
ConvertingPreviewGif,
|
||||||
|
ConvertingPreviewGifFinished,
|
||||||
|
ConvertingPreviewGifError,
|
||||||
|
ConvertingPreviewImage,
|
||||||
|
ConvertingPreviewImageFinished,
|
||||||
|
ConvertingPreviewImageError,
|
||||||
|
ConvertingAudio,
|
||||||
|
ConvertingAudioFinished,
|
||||||
|
ConvertingAudioError,
|
||||||
|
// 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,
|
||||||
|
};
|
||||||
|
Q_ENUM(State)
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void createWallpaperStateChanged(CreateImportVideo::State state);
|
||||||
|
void processOutput(QString text);
|
||||||
|
void finished();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void process();
|
||||||
|
void requestInterruption()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool createWallpaperInfo();
|
||||||
|
bool createWallpaperVideoPreview();
|
||||||
|
bool createWallpaperGifPreview();
|
||||||
|
bool createWallpaperImagePreview();
|
||||||
|
bool extractWallpaperAudio();
|
||||||
|
bool createWallpaperProjectFile(const QString title, const QString description);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QProcess m_process;
|
||||||
|
QString m_videoPath;
|
||||||
|
QString m_exportPath;
|
||||||
|
int m_length = 0;
|
||||||
|
int m_framerate = 0;
|
||||||
|
};
|
@ -5,6 +5,12 @@ InstalledListModel::InstalledListModel(QObject* parent)
|
|||||||
{
|
{
|
||||||
QObject::connect(this, &InstalledListModel::addInstalledItem,
|
QObject::connect(this, &InstalledListModel::addInstalledItem,
|
||||||
this, &InstalledListModel::append, Qt::QueuedConnection);
|
this, &InstalledListModel::append, Qt::QueuedConnection);
|
||||||
|
m_loadScreenWatcher.setFuture(m_loadScreenFuture);
|
||||||
|
|
||||||
|
QObject::connect(&m_loadScreenWatcher, &QFutureWatcher<void>::progressValueChanged, [](int progressValue) {
|
||||||
|
qDebug() << progressValue;
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int InstalledListModel::rowCount(const QModelIndex& parent) const
|
int InstalledListModel::rowCount(const QModelIndex& parent) const
|
||||||
@ -76,6 +82,7 @@ bool InstalledListModel::getProjectByAbsoluteStoragePath(QUrl* path, ProjectFile
|
|||||||
|
|
||||||
void InstalledListModel::append(const QJsonObject obj, const QString folderName)
|
void InstalledListModel::append(const QJsonObject obj, const QString folderName)
|
||||||
{
|
{
|
||||||
|
//qDebug() << QThread::currentThreadId();
|
||||||
beginInsertRows(QModelIndex(), m_screenPlayFiles.size(), m_screenPlayFiles.size());
|
beginInsertRows(QModelIndex(), m_screenPlayFiles.size(), m_screenPlayFiles.size());
|
||||||
|
|
||||||
ProjectFile tmpFile(obj, folderName, m_absoluteStoragePath);
|
ProjectFile tmpFile(obj, folderName, m_absoluteStoragePath);
|
||||||
@ -86,7 +93,12 @@ void InstalledListModel::append(const QJsonObject obj, const QString folderName)
|
|||||||
|
|
||||||
void InstalledListModel::loadInstalledContent()
|
void InstalledListModel::loadInstalledContent()
|
||||||
{
|
{
|
||||||
QtConcurrent::run([this]() {
|
if (m_loadScreenWatcher.isRunning())
|
||||||
|
qDebug() << "allready running";
|
||||||
|
qDebug() << QThread::currentThreadId();
|
||||||
|
|
||||||
|
m_loadScreenFuture = QtConcurrent::run([this]() {
|
||||||
|
qDebug() << QThread::currentThreadId();
|
||||||
QJsonDocument jsonProject;
|
QJsonDocument jsonProject;
|
||||||
QJsonParseError parseError;
|
QJsonParseError parseError;
|
||||||
|
|
||||||
@ -126,14 +138,14 @@ void InstalledListModel::loadInstalledContent()
|
|||||||
obj.insert("type", "video");
|
obj.insert("type", "video");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileEnding.endsWith(".webm") || (obj.value("type").toString() == "qmlScene" || fileEnding.endsWith(".mp4") ) || fileEnding.endsWith(".html"))
|
if (fileEnding.endsWith(".webm") || (obj.value("type").toString() == "qmlScene" || fileEnding.endsWith(".html")))
|
||||||
emit addInstalledItem(obj, item.baseName());
|
emit addInstalledItem(obj, item.baseName());
|
||||||
|
|
||||||
if(obj.value("type") == "qmlWidget" || obj.value("type") == "standalonewidget")
|
if (obj.value("type") == "qmlWidget" || obj.value("type") == "standalonewidget")
|
||||||
emit addInstalledItem(obj, item.baseName());
|
emit addInstalledItem(obj, item.baseName());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit installedLoadingFinished();
|
emit installedLoadingFinished();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QtConcurrent/QtConcurrent>
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
#include <QFuture>
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -81,4 +83,6 @@ signals:
|
|||||||
private:
|
private:
|
||||||
QVector<ProjectFile> m_screenPlayFiles;
|
QVector<ProjectFile> m_screenPlayFiles;
|
||||||
QUrl m_absoluteStoragePath;
|
QUrl m_absoluteStoragePath;
|
||||||
|
QFuture<void> m_loadScreenFuture;
|
||||||
|
QFutureWatcher<void> m_loadScreenWatcher;
|
||||||
};
|
};
|
||||||
|
@ -66,10 +66,11 @@ QString ScreenPlay::generateID()
|
|||||||
{
|
{
|
||||||
const QString possibleCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
const QString possibleCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
||||||
const int randomStringLength = 32;
|
const int randomStringLength = 32;
|
||||||
|
auto* radomGen = QRandomGenerator::system();
|
||||||
|
|
||||||
QString randomString;
|
QString randomString;
|
||||||
for (int i = 0; i < randomStringLength; ++i) {
|
for (int i = 0; i < randomStringLength; ++i) {
|
||||||
int index = qrand() % possibleCharacters.length();
|
int index = radomGen->bounded(possibleCharacters.length());
|
||||||
QChar nextChar = possibleCharacters.at(index);
|
QChar nextChar = possibleCharacters.at(index);
|
||||||
randomString.append(nextChar);
|
randomString.append(nextChar);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ SDKConnector::SDKConnector(QObject* parent)
|
|||||||
m_server = QSharedPointer<QLocalServer>(new QLocalServer(this));
|
m_server = QSharedPointer<QLocalServer>(new QLocalServer(this));
|
||||||
connect(m_server.data(), &QLocalServer::newConnection, this, &SDKConnector::newConnection);
|
connect(m_server.data(), &QLocalServer::newConnection, this, &SDKConnector::newConnection);
|
||||||
if (!m_server.data()->listen("ScreenPlay")) {
|
if (!m_server.data()->listen("ScreenPlay")) {
|
||||||
//TODO
|
//TODO what to do if no ScreenPlay local socket can be open
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#include "../ScreenPlaySDK/screenplaysdk.h"
|
#include "../ScreenPlaySDK/screenplaysdk.h"
|
||||||
#include "src/SPWmainwindow.h"
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
#include "src/winwindow.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@ -10,32 +14,46 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
|
||||||
QApplication a(argc, argv);
|
QApplication app(argc, argv);
|
||||||
ScreenPlaySDK sdk;
|
|
||||||
QtWebEngine::initialize();
|
QtWebEngine::initialize();
|
||||||
|
|
||||||
// 6 parameter + 1 OS working directory default paramter
|
// 6 parameter + 1 OS working directory default paramter
|
||||||
QStringList argumentList = a.arguments();
|
QStringList argumentList = app.arguments();
|
||||||
if (argumentList.length() != 7) {
|
if (argumentList.length() != 7) {
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canParseMonitorNumber = false;
|
ScreenPlaySDK sdk;
|
||||||
int monitor = argumentList.at(1).toInt(&canParseMonitorNumber);
|
sdk.setAppID(argumentList.at(3));
|
||||||
|
|
||||||
if (!canParseMonitorNumber) {
|
QString monitorNumbers = argumentList.at(1);
|
||||||
return -4;
|
QVector<int> list;
|
||||||
|
|
||||||
|
if (monitorNumbers.length() == 1) {
|
||||||
|
bool canParseMonitorNumber = false;
|
||||||
|
int monitor = monitorNumbers.toInt(&canParseMonitorNumber);
|
||||||
|
list.append(monitor);
|
||||||
|
} else {
|
||||||
|
QStringList activeScreensList = monitorNumbers.split(",");
|
||||||
|
for (QString s : activeScreensList) {
|
||||||
|
bool ok = false;
|
||||||
|
int val = s.toInt(&ok);
|
||||||
|
if (!ok) {
|
||||||
|
qFatal("Could not parse monitor id to diplay wallpaper");
|
||||||
|
}
|
||||||
|
list.append(val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Args: which monitor, (2) path to project, (3)wallpaper secret to identify the connected socket, (4) decoder, (5) volume, (6) fillmode
|
// Args: which monitor, (2) path to project, (3)wallpaper secret to identify the connected socket, (5) volume
|
||||||
// See screenplay.h @ScreenPlayWallpaper constructor how the args get created
|
// See screenplay.h @ScreenPlayWallpaper constructor how the args get created
|
||||||
//MainWindow w(0,"D:/672870/_tmp_135011","","","","");
|
|
||||||
sdk.setAppID(argumentList.at(3));
|
|
||||||
qDebug() << "Starting MainWindow: " << argumentList.at(2) << argumentList.at(3) << argumentList.at(4) << argumentList.at(5) << argumentList.at(6);
|
|
||||||
MainWindow w(monitor, argumentList.at(2), argumentList.at(3), argumentList.at(4), argumentList.at(5), argumentList.at(6));
|
|
||||||
|
|
||||||
QObject::connect(&sdk, &ScreenPlaySDK::sdkDisconnected, &w, &MainWindow::destroyThis);
|
#if defined(Q_OS_WIN)
|
||||||
QObject::connect(&sdk, &ScreenPlaySDK::incommingMessage, &w, &MainWindow::messageReceived);
|
WinWindow window = WinWindow(list, argumentList.at(2), argumentList.at(3), argumentList.at(5));
|
||||||
|
QObject::connect(&sdk, &ScreenPlaySDK::sdkDisconnected, &window, &WinWindow::destroyThis);
|
||||||
|
QObject::connect(&sdk, &ScreenPlaySDK::incommingMessage, &window, &WinWindow::messageReceived);
|
||||||
|
#endif
|
||||||
|
|
||||||
return a.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
QT += qml quick quickcontrols2 widgets core webengine
|
QT += qml quick quickcontrols2 widgets core webengine
|
||||||
CONFIG += c++17
|
CONFIG += c++17
|
||||||
#CONFIG += qtquickcompiler
|
|
||||||
msvc: LIBS += -luser32
|
msvc: LIBS += -luser32
|
||||||
TARGETPATH = ScreenPlayWindow
|
TARGETPATH = ScreenPlayWindow
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
SPWmain.cpp \
|
SPWmain.cpp \
|
||||||
src/SPWmainwindow.cpp
|
#src/SPWmainwindow.cpp \
|
||||||
|
src/basewindow.cpp \
|
||||||
|
src/windowsdesktopproperties.cpp \
|
||||||
|
src/winwindow.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/SPWmainwindow.h
|
#src/SPWmainwindow.h \
|
||||||
|
src/basewindow.h \
|
||||||
|
src/windowsdesktopproperties.h \
|
||||||
|
src/winwindow.h
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
SPWResources.qrc
|
SPWResources.qrc
|
||||||
|
@ -8,14 +8,11 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: fill;
|
object-fit: fill;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-image: linear-gradient(120deg, #f6d365 0%, #fda085 100%);
|
|
||||||
}
|
}
|
||||||
body, html{
|
body, html{
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background:orange;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#errorMsg{
|
#errorMsg{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -1,23 +1,127 @@
|
|||||||
import QtQuick 2.12
|
import QtQuick 2.13
|
||||||
import QtWebEngine 1.8
|
import QtWebEngine 1.8
|
||||||
|
import net.aimber.wallpaper 1.0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
color: desktopProperties.color
|
||||||
|
|
||||||
|
property bool canFadeIn: true
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
WebEngine.settings.allowRunningInsecureContent = true
|
||||||
|
WebEngine.settings.accelerated2dCanvasEnabled = true
|
||||||
|
WebEngine.settings.javascriptCanOpenWindows = false
|
||||||
|
WebEngine.settings.printElementBackgrounds = false
|
||||||
|
WebEngine.settings.showScrollBars = false
|
||||||
|
WebEngine.settings.playbackRequiresUserGesture = false
|
||||||
|
|
||||||
|
switch (window.type) {
|
||||||
|
case Wallpaper.WallpaperType.Video:
|
||||||
|
webView.enabled = true
|
||||||
|
webView.url = Qt.resolvedUrl("file:///" + window.getApplicationPath(
|
||||||
|
) + "/index.html")
|
||||||
|
|
||||||
|
break
|
||||||
|
case Wallpaper.WallpaperType.Html:
|
||||||
|
webView.enabled = true
|
||||||
|
webView.url = Qt.resolvedUrl("file:///" + window.fullContentPath)
|
||||||
|
break
|
||||||
|
case Wallpaper.WallpaperType.ThreeJSScene:
|
||||||
|
webView.enabled = true
|
||||||
|
break
|
||||||
|
case Wallpaper.WallpaperType.Qml:
|
||||||
|
loader.source = Qt.resolvedUrl("file:///" + window.fullContentPath)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fadeIn()
|
||||||
|
}
|
||||||
|
|
||||||
|
function fadeIn() {
|
||||||
|
window.setVisible(true)
|
||||||
|
if (canFadeIn) {
|
||||||
|
animFadeIn.start()
|
||||||
|
} else {
|
||||||
|
imgCover.opacity = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WebEngineView {
|
||||||
|
id: webView
|
||||||
|
enabled: false
|
||||||
|
anchors.fill: parent
|
||||||
|
onLoadProgressChanged: {
|
||||||
|
if (loadProgress === 100) {
|
||||||
|
|
||||||
|
var src = ""
|
||||||
|
src += "var videoPlayer = document.getElementById('videoPlayer');"
|
||||||
|
src += "var videoSource = document.getElementById('videoSource');"
|
||||||
|
src += "videoSource.src = 'file:///" + window.fullContentPath + "';"
|
||||||
|
src += "videoPlayer.load();"
|
||||||
|
src += "videoPlayer.volume = " + window.volume + ";"
|
||||||
|
src += "videoPlayer.play();"
|
||||||
|
|
||||||
|
webView.runJavaScript(src, function () {
|
||||||
|
fadeIn()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loader {
|
||||||
|
id: loader
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
OpacityAnimator {
|
||||||
|
id: animFadeIn
|
||||||
|
target: imgCover
|
||||||
|
from: 1
|
||||||
|
to: 0
|
||||||
|
duration: 300
|
||||||
|
easing.type: Easing.InCubic
|
||||||
|
running: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: imgCover
|
||||||
|
anchors.fill: parent
|
||||||
|
source: Qt.resolvedUrl("file:///" + desktopProperties.wallpaperPath)
|
||||||
|
Component.onCompleted: {
|
||||||
|
switch (desktopProperties.wallpaperStyle) {
|
||||||
|
case 10:
|
||||||
|
imgCover.fillMode = Image.PreserveAspectCrop
|
||||||
|
break
|
||||||
|
case 6:
|
||||||
|
imgCover.fillMode = Image.PreserveAspectFit
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
break
|
||||||
|
case 0:
|
||||||
|
if (desktopProperties.isTiled) {
|
||||||
|
// Tiled
|
||||||
|
imgCover.fillMode = Image.Tile
|
||||||
|
} else {
|
||||||
|
// Center
|
||||||
|
imgCover.fillMode = Image.PreserveAspectFit
|
||||||
|
imgCover.anchors.centerIn = parent
|
||||||
|
imgCover.width = sourceSize.width
|
||||||
|
imgCover.height = sourceSize.height
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 22:
|
||||||
|
canFadeIn = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: mainwindow
|
target: window
|
||||||
|
|
||||||
onQmlExit: {
|
onQmlExit: {
|
||||||
|
|
||||||
webView.runJavaScript(
|
webView.runJavaScript(
|
||||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;")
|
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;")
|
||||||
mainwindow.destroyThis()
|
window.destroyThis()
|
||||||
}
|
|
||||||
|
|
||||||
onFillModeChanged: {
|
|
||||||
|
|
||||||
//TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onQmlSceneValueReceived: {
|
onQmlSceneValueReceived: {
|
||||||
@ -60,95 +164,4 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
|
|
||||||
if (mainwindow.type === "qmlScene") {
|
|
||||||
loader.setSource(Qt.resolvedUrl(
|
|
||||||
"file:///" + mainwindow.fullContentPath))
|
|
||||||
mainwindow.init()
|
|
||||||
timer.start()
|
|
||||||
} else if (mainwindow.type === "video") {
|
|
||||||
webView.visible = true
|
|
||||||
webView.url = Qt.resolvedUrl(
|
|
||||||
"file:///" + mainwindow.getApplicationPath(
|
|
||||||
) + "/index.html")
|
|
||||||
} else if (mainwindow.type === "html") {
|
|
||||||
webView.visible = true
|
|
||||||
webView.url = Qt.resolvedUrl(
|
|
||||||
"file:///" + mainwindow.fullContentPath)
|
|
||||||
mainwindow.init()
|
|
||||||
timer.start()
|
|
||||||
}
|
|
||||||
mainwindow.init()
|
|
||||||
timer.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
WebEngineView {
|
|
||||||
id: webView
|
|
||||||
anchors.fill: parent
|
|
||||||
onLoadProgressChanged: {
|
|
||||||
if (loadProgress === 100) {
|
|
||||||
runJavaScript(("
|
|
||||||
var videoPlayer = document.getElementById('videoPlayer');
|
|
||||||
var videoSource = document.getElementById('videoSource');
|
|
||||||
videoSource.src = \"file:///" + mainwindow.fullContentPath + "\";
|
|
||||||
videoPlayer.load();
|
|
||||||
videoPlayer.volume = " + mainwindow.volume + ";" +
|
|
||||||
" videoPlayer.play();"), function (result) {
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onJavaScriptConsoleMessage: {
|
|
||||||
print(message)
|
|
||||||
// runJavaScript("
|
|
||||||
// var videoPlayer = document.getElementById('errorMsg');
|
|
||||||
// var text = document.createTextNode("+message+");
|
|
||||||
|
|
||||||
// videoPlayer.appendChild(text);
|
|
||||||
|
|
||||||
//");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.allowRunningInsecureContent: true
|
|
||||||
settings.accelerated2dCanvasEnabled: true
|
|
||||||
settings.javascriptCanOpenWindows: false
|
|
||||||
settings.printElementBackgrounds: false
|
|
||||||
settings.showScrollBars: false
|
|
||||||
settings.playbackRequiresUserGesture: false
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: loader
|
|
||||||
anchors.fill: parent
|
|
||||||
onStatusChanged: {
|
|
||||||
print(webViewWrapper.errorString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: timer
|
|
||||||
interval: 200
|
|
||||||
onTriggered: {
|
|
||||||
anim.start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: curtain
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "black"
|
|
||||||
|
|
||||||
PropertyAnimation {
|
|
||||||
id: anim
|
|
||||||
property: "opacity"
|
|
||||||
target: curtain
|
|
||||||
from: "1"
|
|
||||||
to: "0"
|
|
||||||
duration: 300
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,12 @@ BOOL WINAPI SearchForWorkerWindow(HWND hwnd, LPARAM lparam)
|
|||||||
|
|
||||||
//for mac https://github.com/silvansky/QtMacApp/search?q=myprivate&unscoped_q=myprivate
|
//for mac https://github.com/silvansky/QtMacApp/search?q=myprivate&unscoped_q=myprivate
|
||||||
|
|
||||||
MainWindow::MainWindow(int i, QString projectPath, QString id, QString decoder, QString volume, QString fillmode, QScreen* parent)
|
MainWindow::MainWindow(int screenAt, QString projectPath, QString id, QString decoder, QString volume, QString fillmode, QWindow* parent)
|
||||||
: QWindow(parent)
|
: QQuickView(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
m_appID = id;
|
m_appID = id;
|
||||||
m_screenNumber.insert(0, i);
|
m_screenNumber.append(screenAt);
|
||||||
setDecoder(decoder);
|
setDecoder(decoder);
|
||||||
setProjectPath(projectPath);
|
setProjectPath(projectPath);
|
||||||
|
|
||||||
@ -62,23 +60,23 @@ MainWindow::MainWindow(int i, QString projectPath, QString id, QString decoder,
|
|||||||
if (m_project.value("type") == "video") {
|
if (m_project.value("type") == "video") {
|
||||||
QString tmpPath = m_projectPath.toString() + "/" + m_projectFile;
|
QString tmpPath = m_projectPath.toString() + "/" + m_projectFile;
|
||||||
setFullContentPath(tmpPath);
|
setFullContentPath(tmpPath);
|
||||||
setType("video");
|
setWallpaperType("video");
|
||||||
} else if (m_project.value("type") == "scene") {
|
} else if (m_project.value("type") == "scene") {
|
||||||
return;
|
return;
|
||||||
} else if (m_project.value("type") == "qmlScene") {
|
} else if (m_project.value("type") == "qmlScene") {
|
||||||
QString tmpPath = m_projectPath.toString() + "/" + m_projectFile;
|
QString tmpPath = m_projectPath.toString() + "/" + m_projectFile;
|
||||||
setFullContentPath(tmpPath);
|
setFullContentPath(tmpPath);
|
||||||
setType("qmlScene");
|
setWallpaperType("qmlScene");
|
||||||
} else if (m_project.value("type") == "html") {
|
} else if (m_project.value("type") == "html") {
|
||||||
QString tmpPath = m_projectPath.toString() + "/" + m_projectFile;
|
QString tmpPath = m_projectPath.toString() + "/" + m_projectFile;
|
||||||
setFullContentPath(tmpPath);
|
setFullContentPath(tmpPath);
|
||||||
setType("html");
|
setWallpaperType("html");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recalculate window coordiantes because of point (0,0)
|
// Recalculate window coordiantes because of point (0,0)
|
||||||
// Is at the origin monitor or the most left
|
// Is at the origin monitor or the most left
|
||||||
QScreen* screen = QApplication::screens().at(i);
|
|
||||||
int offsetX = 0;
|
int offsetX = 0;
|
||||||
int offsetY = 0;
|
int offsetY = 0;
|
||||||
|
|
||||||
@ -92,14 +90,13 @@ MainWindow::MainWindow(int i, QString projectPath, QString id, QString decoder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|
||||||
m_hwnd = (HWND)this->winId();
|
m_hwnd = reinterpret_cast<HWND>(winId());
|
||||||
HWND progman_hwnd = FindWindowW(L"Progman", L"Program Manager");
|
HWND progman_hwnd = FindWindowW(L"Progman", L"Program Manager");
|
||||||
|
|
||||||
// Spawn new worker window below desktop (using some undocumented Win32 magic)
|
// Spawn new worker window below desktop (using some undocumented Win32 magic)
|
||||||
// See
|
// See https://www.codeproject.com/articles/856020/draw-behind-desktop-icons-in-windows
|
||||||
// https://www.codeproject.com/articles/856020/draw-behind-desktop-icons-in-windows
|
|
||||||
// for more details
|
// for more details
|
||||||
const DWORD WM_SPAWN_WORKER = 0x052C;
|
const DWORD WM_SPAWN_WORKER = 0x052C;
|
||||||
SendMessageTimeoutW(progman_hwnd, WM_SPAWN_WORKER, 0xD, 0x1, SMTO_NORMAL,
|
SendMessageTimeoutW(progman_hwnd, WM_SPAWN_WORKER, 0xD, 0x1, SMTO_NORMAL,
|
||||||
@ -113,67 +110,79 @@ MainWindow::MainWindow(int i, QString projectPath, QString id, QString decoder,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Hide first to avoid flickering
|
//Hide first to avoid flickering
|
||||||
//ShowWindow(m_worker_hwnd, SW_HIDE);
|
QScreen* screen = QApplication::screens().at(screenAt);
|
||||||
|
if (screen == nullptr) {
|
||||||
|
destroyThis();
|
||||||
|
}
|
||||||
|
|
||||||
ShowWindow(m_hwnd, SW_HIDE);
|
ShowWindow(m_hwnd, SW_HIDE);
|
||||||
MoveWindow(m_hwnd, screen->geometry().x() + offsetX, screen->geometry().y() + offsetY, screen->size().width(), screen->size().height(), true);
|
|
||||||
SetParent(m_hwnd, m_worker_hwnd);
|
SetParent(m_hwnd, m_worker_hwnd);
|
||||||
|
UpdateWindow(m_hwnd);
|
||||||
|
UpdateWindow(m_worker_hwnd);
|
||||||
|
SetWindowLongPtr(m_hwnd, GWL_STYLE, WS_CHILDWINDOW);
|
||||||
|
SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE );
|
||||||
|
// ShowWindow(m_hwnd, SW_SHOW);
|
||||||
|
//MoveWindow(m_hwnd, screen->geometry().x(), screen->geometry().y() , screen->size().width(), screen->size().height(), true);
|
||||||
|
|
||||||
SetWindowLongPtr(m_hwnd, GWL_STYLE, WS_CHILDWINDOW | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU | WS_POPUP);
|
qDebug() << "Create window: " << screenAt << ", x: " << screen->geometry().x() << "y: " << screen->geometry().y() << screen->size().width() << screen->size().height();
|
||||||
SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE | WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
|
|
||||||
//debug
|
//debug
|
||||||
this->setWidth(screen->size().width());
|
this->setWidth(screen->size().width());
|
||||||
this->setHeight(screen->size().height());
|
this->setHeight(screen->size().height());
|
||||||
int x = screen->geometry().x();
|
int x = screen->geometry().x();
|
||||||
int y = screen->geometry().y();
|
int y = screen->geometry().y();
|
||||||
this->setX(screen->geometry().x());// + offsetX);
|
this->setX(screen->geometry().x()); // );
|
||||||
this->setY(screen->geometry().y());// + offsetY);#endif
|
this->setY(screen->geometry().y()); // );
|
||||||
#endif
|
#endif
|
||||||
Qt::WindowFlags flags = this->flags();
|
Qt::WindowFlags flags = this->flags();
|
||||||
this->setFlags(flags | Qt::FramelessWindowHint | Qt::WindowStaysOnBottomHint);
|
setFlags(flags | Qt::FramelessWindowHint | Qt::WindowStaysOnBottomHint);
|
||||||
|
rootContext()->setContextProperty("mainwindow", this);
|
||||||
|
setSource(QUrl("qrc:/qml/main.qml"));
|
||||||
|
setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView);
|
||||||
|
setGeometry(screen->geometry().x() + offsetX, screen->geometry().y() + offsetY, screen->size().width(), screen->size().height());
|
||||||
|
//show();
|
||||||
|
|
||||||
m_quickRenderer = QSharedPointer<QQuickView>(new QQuickView(this));
|
UpdateWindow(m_hwnd);
|
||||||
m_quickRenderer.data()->rootContext()->setContextProperty("mainwindow", this);
|
UpdateWindow(m_worker_hwnd);
|
||||||
m_quickRenderer.data()->setSource(QUrl("qrc:/qml/main.qml"));
|
|
||||||
m_quickRenderer.data()->setGeometry(0, 0, width(), height());
|
|
||||||
m_quickRenderer.data()->setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView);
|
|
||||||
m_quickRenderer.data()->setFlags(flags | Qt::FramelessWindowHint | Qt::WindowStaysOnBottomHint);
|
|
||||||
m_quickRenderer.data()->show();
|
|
||||||
|
|
||||||
setVolume(volume.toFloat());
|
setVolume(volume.toFloat());
|
||||||
setFillMode(fillmode);
|
setFillMode(fillmode);
|
||||||
|
|
||||||
connect(m_quickRenderer.data(), &QQuickView::statusChanged, [=](QQuickView::Status status) {
|
connect(this, &QQuickView::statusChanged, [=](QQuickView::Status status) {
|
||||||
if (status == QQuickView::Error) {
|
if (status == QQuickView::Error) {
|
||||||
destroyThis();
|
destroyThis();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setVisible(true);
|
QTimer::singleShot(3000,[=](){
|
||||||
|
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
|
||||||
|
});
|
||||||
|
|
||||||
|
//setVisible(true);
|
||||||
|
//ShowWindow(m_hwnd, SW_SHOWDEFAULT);
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
MacIntegration* integration = new MacIntegration(this);
|
MacIntegration* integration = new MacIntegration(this);
|
||||||
integration->SetBackgroundLevel(this);
|
integration->SetBackgroundLevel(this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
void MainWindow::init()
|
void MainWindow::init()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
// This needs to be set in this order or
|
// This needs to be set in this order or
|
||||||
// the window will be opened as fullscreen!
|
// the window will be opened as fullscreen!
|
||||||
//ShowWindow(m_worker_hwnd, SW_SHOWDEFAULT);
|
|
||||||
ShowWindow(m_hwnd, SW_SHOWDEFAULT);
|
//ShowWindow(m_hwnd, SW_SHOWDEFAULT);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void MainWindow::destroyThis()
|
void MainWindow::destroyThis()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
ShowWindow(m_worker_hwnd, SW_HIDE);
|
|
||||||
ShowWindow(m_hwnd, SW_HIDE);
|
ShowWindow(m_hwnd, SW_HIDE);
|
||||||
#endif
|
#endif
|
||||||
QCoreApplication::quit();
|
QCoreApplication::quit();
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
#include <QTimer>
|
||||||
#include <QtQuick/QQuickView>
|
#include <QtQuick/QQuickView>
|
||||||
#include <QtQuick/QQuickWindow>
|
#include <QtQuick/QQuickWindow>
|
||||||
|
|
||||||
@ -20,18 +21,18 @@
|
|||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class MainWindow : public QWindow {
|
class MainWindow : public QQuickView {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(int i, QString projectPath, QString id, QString decoder, QString volume, QString fillmode, QScreen* parent = nullptr);
|
explicit MainWindow(int screenAt, QString projectPath, QString id, QString decoder, QString volume, QString fillmode, QWindow* parent = nullptr);
|
||||||
|
|
||||||
Q_PROPERTY(QVector<int> screenNumber READ screenNumber WRITE setScreenNumber NOTIFY screenNumberChanged)
|
Q_PROPERTY(QVector<int> screenNumber READ screenNumber WRITE setScreenNumber NOTIFY screenNumberChanged)
|
||||||
Q_PROPERTY(QString projectConfig READ projectConfig WRITE setProjectConfig NOTIFY projectConfigChanged)
|
Q_PROPERTY(QString projectConfig READ projectConfig WRITE setProjectConfig NOTIFY projectConfigChanged)
|
||||||
Q_PROPERTY(QString appID READ name WRITE setname NOTIFY nameChanged)
|
Q_PROPERTY(QString appID READ name WRITE setname NOTIFY nameChanged)
|
||||||
Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged)
|
|
||||||
Q_PROPERTY(QString fullContentPath READ fullContentPath WRITE setFullContentPath NOTIFY fullContentPathChanged)
|
|
||||||
|
|
||||||
|
Q_PROPERTY(QString fullContentPath READ fullContentPath WRITE setFullContentPath NOTIFY fullContentPathChanged)
|
||||||
|
Q_PROPERTY(QString wallpaperType READ wallpaperType WRITE setWallpaperType NOTIFY wallpaperTypeChanged)
|
||||||
Q_PROPERTY(QString fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
|
Q_PROPERTY(QString fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
|
||||||
Q_PROPERTY(bool loops READ loops WRITE setLoops NOTIFY loopsChanged)
|
Q_PROPERTY(bool loops READ loops WRITE setLoops NOTIFY loopsChanged)
|
||||||
Q_PROPERTY(float volume READ volume WRITE setVolume NOTIFY volumeChanged)
|
Q_PROPERTY(float volume READ volume WRITE setVolume NOTIFY volumeChanged)
|
||||||
@ -59,11 +60,6 @@ public:
|
|||||||
return m_projectPath;
|
return m_projectPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString type() const
|
|
||||||
{
|
|
||||||
return m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString fillMode() const
|
QString fillMode() const
|
||||||
{
|
{
|
||||||
return m_fillMode;
|
return m_fillMode;
|
||||||
@ -98,6 +94,11 @@ public:
|
|||||||
return m_decoder;
|
return m_decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString wallpaperType() const
|
||||||
|
{
|
||||||
|
return m_wallpaperType;
|
||||||
|
}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void destroyThis();
|
void destroyThis();
|
||||||
void init();
|
void init();
|
||||||
@ -126,15 +127,6 @@ public slots:
|
|||||||
emit nameChanged(m_appID);
|
emit nameChanged(m_appID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setType(QString type)
|
|
||||||
{
|
|
||||||
if (m_type == type)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_type = type;
|
|
||||||
emit typeChanged(m_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFillMode(QString fillMode)
|
void setFillMode(QString fillMode)
|
||||||
{
|
{
|
||||||
if (m_fillMode == fillMode)
|
if (m_fillMode == fillMode)
|
||||||
@ -155,7 +147,6 @@ public slots:
|
|||||||
|
|
||||||
void setVolume(float volume)
|
void setVolume(float volume)
|
||||||
{
|
{
|
||||||
qWarning("Floating point comparison needs context sanity check");
|
|
||||||
if (qFuzzyCompare(m_volume, volume))
|
if (qFuzzyCompare(m_volume, volume))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -210,13 +201,22 @@ public slots:
|
|||||||
emit decoderChanged(m_decoder);
|
emit decoderChanged(m_decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setWallpaperType(QString wallpaperType)
|
||||||
|
{
|
||||||
|
if (m_wallpaperType == wallpaperType)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_wallpaperType = wallpaperType;
|
||||||
|
emit wallpaperTypeChanged(m_wallpaperType);
|
||||||
|
}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void playVideo(QString path);
|
void playVideo(QString path);
|
||||||
void playQmlScene(QString file);
|
void playQmlScene(QString file);
|
||||||
void projectConfigChanged(QString projectConfig);
|
void projectConfigChanged(QString projectConfig);
|
||||||
void nameChanged(QString appID);
|
void nameChanged(QString appID);
|
||||||
void screenNumberChanged(QVector<int> screenNumber);
|
void screenNumberChanged(QVector<int> screenNumber);
|
||||||
void typeChanged(QString type);
|
|
||||||
void fillModeChanged(QString fillMode);
|
void fillModeChanged(QString fillMode);
|
||||||
void loopsChanged(bool loops);
|
void loopsChanged(bool loops);
|
||||||
void volumeChanged(float volume);
|
void volumeChanged(float volume);
|
||||||
@ -227,12 +227,14 @@ signals:
|
|||||||
void decoderChanged(QString decoder);
|
void decoderChanged(QString decoder);
|
||||||
void qmlExit();
|
void qmlExit();
|
||||||
|
|
||||||
|
void wallpaperTypeChanged(QString wallpaperType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
HWND m_hwnd;
|
HWND m_hwnd;
|
||||||
HWND m_worker_hwnd;
|
HWND m_worker_hwnd;
|
||||||
#endif
|
#endif
|
||||||
QSharedPointer<QQuickView> m_quickRenderer = nullptr;
|
|
||||||
QUrl m_projectPath;
|
QUrl m_projectPath;
|
||||||
QString m_projectFile;
|
QString m_projectFile;
|
||||||
QJsonObject m_project;
|
QJsonObject m_project;
|
||||||
@ -240,7 +242,7 @@ private:
|
|||||||
|
|
||||||
QString m_appID;
|
QString m_appID;
|
||||||
QVector<int> m_screenNumber;
|
QVector<int> m_screenNumber;
|
||||||
QString m_type;
|
|
||||||
QString m_fillMode;
|
QString m_fillMode;
|
||||||
bool m_loops;
|
bool m_loops;
|
||||||
float m_volume;
|
float m_volume;
|
||||||
@ -248,4 +250,5 @@ private:
|
|||||||
bool m_isPlaying;
|
bool m_isPlaying;
|
||||||
float m_playbackRate;
|
float m_playbackRate;
|
||||||
QString m_decoder;
|
QString m_decoder;
|
||||||
|
QString m_wallpaperType;
|
||||||
};
|
};
|
||||||
|
72
ScreenPlayWindow/src/basewindow.cpp
Normal file
72
ScreenPlayWindow/src/basewindow.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include "basewindow.h"
|
||||||
|
|
||||||
|
BaseWindow::BaseWindow(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseWindow::BaseWindow(QString projectFilePath, QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
qRegisterMetaType<BaseWindow::WallpaperType>();
|
||||||
|
qmlRegisterType<BaseWindow>("net.aimber.wallpaper", 1, 0, "Wallpaper");
|
||||||
|
|
||||||
|
QFile projectFile;
|
||||||
|
QJsonDocument configJsonDocument;
|
||||||
|
QJsonParseError parseError;
|
||||||
|
|
||||||
|
projectFile.setFileName(projectFilePath + "/project.json");
|
||||||
|
projectFile.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||||
|
QString projectConfig = projectFile.readAll();
|
||||||
|
configJsonDocument = QJsonDocument::fromJson(projectConfig.toUtf8(), &parseError);
|
||||||
|
|
||||||
|
/* project.json example:
|
||||||
|
*{
|
||||||
|
* "description": "",
|
||||||
|
* "file": "example.webm",
|
||||||
|
* "preview": "preview.png",
|
||||||
|
* "previewGIF": "preview.gif",
|
||||||
|
* "previewMP4": "preview.mp4",
|
||||||
|
* "title": "example title",
|
||||||
|
* "type": "video"
|
||||||
|
*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!(parseError.error == QJsonParseError::NoError)) {
|
||||||
|
qDebug() << projectConfig << "\n"
|
||||||
|
<< parseError.errorString();
|
||||||
|
qFatal("Settings Json Parse Error. Exiting now!");
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject projectObject = configJsonDocument.object();
|
||||||
|
|
||||||
|
if (!projectObject.contains("file")) {
|
||||||
|
qFatal("No file was specified inside the json object!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!projectObject.contains("type")) {
|
||||||
|
qFatal("No type was specified inside the json object!");
|
||||||
|
}
|
||||||
|
|
||||||
|
setFullContentPath(projectFilePath + "/" + projectObject.value("file").toString());
|
||||||
|
|
||||||
|
if (projectObject.value("type") == "video") {
|
||||||
|
setType(BaseWindow::WallpaperType::Video);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projectObject.value("type") == "scene") {
|
||||||
|
setType(BaseWindow::WallpaperType::ThreeJSScene);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projectObject.value("type") == "qml") {
|
||||||
|
setType(BaseWindow::WallpaperType::Qml);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projectObject.value("type") == "html") {
|
||||||
|
setType(BaseWindow::WallpaperType::Html);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
163
ScreenPlayWindow/src/basewindow.h
Normal file
163
ScreenPlayWindow/src/basewindow.h
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonParseError>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <qqml.h>
|
||||||
|
|
||||||
|
class BaseWindow : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
BaseWindow(QObject* parent = nullptr);
|
||||||
|
BaseWindow(QString projectFilePath, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
Q_PROPERTY(QString appID READ appID WRITE setAppID NOTIFY appIDChanged)
|
||||||
|
Q_PROPERTY(QString fullContentPath READ fullContentPath WRITE setFullContentPath NOTIFY fullContentPathChanged)
|
||||||
|
Q_PROPERTY(bool loops READ loops WRITE setLoops NOTIFY loopsChanged)
|
||||||
|
Q_PROPERTY(bool isPlaying READ isPlaying WRITE setIsPlaying NOTIFY isPlayingChanged)
|
||||||
|
Q_PROPERTY(float volume READ volume WRITE setVolume NOTIFY volumeChanged)
|
||||||
|
Q_PROPERTY(float playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged)
|
||||||
|
Q_PROPERTY(WallpaperType type READ type WRITE setType NOTIFY typeChanged)
|
||||||
|
|
||||||
|
enum class WallpaperType {
|
||||||
|
Video,
|
||||||
|
Html,
|
||||||
|
ThreeJSScene,
|
||||||
|
Qml,
|
||||||
|
};
|
||||||
|
Q_ENUM(WallpaperType)
|
||||||
|
|
||||||
|
bool loops() const
|
||||||
|
{
|
||||||
|
return m_loops;
|
||||||
|
}
|
||||||
|
|
||||||
|
float volume() const
|
||||||
|
{
|
||||||
|
return m_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isPlaying() const
|
||||||
|
{
|
||||||
|
return m_isPlaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
float playbackRate() const
|
||||||
|
{
|
||||||
|
return m_playbackRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
WallpaperType type() const
|
||||||
|
{
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fullContentPath() const
|
||||||
|
{
|
||||||
|
return m_fullContentPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString appID() const
|
||||||
|
{
|
||||||
|
return m_appID;
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void loopsChanged(bool loops);
|
||||||
|
void volumeChanged(float volume);
|
||||||
|
void isPlayingChanged(bool isPlaying);
|
||||||
|
void playbackRateChanged(float playbackRate);
|
||||||
|
void typeChanged(WallpaperType type);
|
||||||
|
void fullContentPathChanged(QString fullContentPath);
|
||||||
|
void appIDChanged(QString appID);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
virtual void destroyThis() {}
|
||||||
|
virtual void setVisible(bool show) {Q_UNUSED(show)}
|
||||||
|
virtual void messageReceived(QString key, QString value){Q_UNUSED(key);Q_UNUSED(value)}
|
||||||
|
|
||||||
|
QString getApplicationPath()
|
||||||
|
{
|
||||||
|
return QApplication::applicationDirPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLoops(bool loops)
|
||||||
|
{
|
||||||
|
if (m_loops == loops)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_loops = loops;
|
||||||
|
emit loopsChanged(m_loops);
|
||||||
|
}
|
||||||
|
void setVolume(float volume)
|
||||||
|
{
|
||||||
|
qWarning("Floating point comparison needs context sanity check");
|
||||||
|
if (qFuzzyCompare(m_volume, volume))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_volume = volume;
|
||||||
|
emit volumeChanged(m_volume);
|
||||||
|
}
|
||||||
|
void setIsPlaying(bool isPlaying)
|
||||||
|
{
|
||||||
|
if (m_isPlaying == isPlaying)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_isPlaying = isPlaying;
|
||||||
|
emit isPlayingChanged(m_isPlaying);
|
||||||
|
}
|
||||||
|
void setPlaybackRate(float playbackRate)
|
||||||
|
{
|
||||||
|
qWarning("Floating point comparison needs context sanity check");
|
||||||
|
if (qFuzzyCompare(m_playbackRate, playbackRate))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_playbackRate = playbackRate;
|
||||||
|
emit playbackRateChanged(m_playbackRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setType(WallpaperType type)
|
||||||
|
{
|
||||||
|
if (m_type == type)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_type = type;
|
||||||
|
emit typeChanged(m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFullContentPath(QString fullContentPath)
|
||||||
|
{
|
||||||
|
if (m_fullContentPath == fullContentPath)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_fullContentPath = fullContentPath;
|
||||||
|
emit fullContentPathChanged(m_fullContentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAppID(QString appID)
|
||||||
|
{
|
||||||
|
if (m_appID == appID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_appID = appID;
|
||||||
|
emit appIDChanged(m_appID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_loops = true;
|
||||||
|
bool m_isPlaying = true;
|
||||||
|
|
||||||
|
float m_volume = 1.0f;
|
||||||
|
float m_playbackRate = 1.0f;
|
||||||
|
|
||||||
|
QString m_fullContentPath;
|
||||||
|
QString m_appID;
|
||||||
|
|
||||||
|
WallpaperType m_type = BaseWindow::WallpaperType::Qml;
|
||||||
|
};
|
30
ScreenPlayWindow/src/windowsdesktopproperties.cpp
Normal file
30
ScreenPlayWindow/src/windowsdesktopproperties.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "windowsdesktopproperties.h"
|
||||||
|
|
||||||
|
WindowsDesktopProperties::WindowsDesktopProperties(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
qmlRegisterType<WindowsDesktopProperties>();
|
||||||
|
QSettings settings("HKEY_CURRENT_USER\\Control Panel\\Desktop", QSettings::NativeFormat);
|
||||||
|
|
||||||
|
setWallpaperPath(settings.value("WallPaper").toString());
|
||||||
|
setIsTiled(settings.value("TileWallpaper").toBool());
|
||||||
|
|
||||||
|
QPoint pos;
|
||||||
|
pos.setX(settings.value("WallpaperOriginX").toInt());
|
||||||
|
pos.setY(settings.value("WallpaperOriginY").toInt());
|
||||||
|
setPosition(pos);
|
||||||
|
|
||||||
|
setWallpaperStyle(settings.value("WallpaperStyle").toInt());
|
||||||
|
|
||||||
|
QSettings settingscolor("HKEY_CURRENT_USER\\Control Panel\\Colors", QSettings::NativeFormat);
|
||||||
|
|
||||||
|
QString colorStringRGB = settingscolor.value("Background").toString();
|
||||||
|
QStringList colorStringRGBList = colorStringRGB.split(" ");
|
||||||
|
|
||||||
|
if (colorStringRGBList.length() == 3) {
|
||||||
|
int colorR = colorStringRGBList.at(0).toInt();
|
||||||
|
int colorG = colorStringRGBList.at(1).toInt();
|
||||||
|
int colorB = colorStringRGBList.at(2).toInt();
|
||||||
|
setColor(QColor::fromRgb(colorR, colorG, colorB));
|
||||||
|
}
|
||||||
|
}
|
120
ScreenPlayWindow/src/windowsdesktopproperties.h
Normal file
120
ScreenPlayWindow/src/windowsdesktopproperties.h
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPoint>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QString>
|
||||||
|
#include <QList>
|
||||||
|
#include <qqml.h>
|
||||||
|
#include <qt_windows.h>
|
||||||
|
|
||||||
|
class WindowsDesktopProperties : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit WindowsDesktopProperties(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
Q_PROPERTY(QString wallpaperPath READ wallpaperPath WRITE setWallpaperPath NOTIFY wallpaperPathChanged)
|
||||||
|
Q_PROPERTY(QPoint position READ position WRITE setPosition NOTIFY positionChanged)
|
||||||
|
Q_PROPERTY(bool isTiled READ isTiled WRITE setIsTiled NOTIFY isTiledChanged)
|
||||||
|
Q_PROPERTY(int wallpaperStyle READ wallpaperStyle WRITE setWallpaperStyle NOTIFY wallpaperStyleChanged)
|
||||||
|
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
|
||||||
|
|
||||||
|
/* WallpaperStyle integer values in the windows registry
|
||||||
|
* 10 -> fill
|
||||||
|
* 6 -> fit
|
||||||
|
* 2 -> stretch
|
||||||
|
* 0 -> tile -> isTiled true
|
||||||
|
* 0 -> center -> isTiled false WTF Windows?
|
||||||
|
* 22 -> span
|
||||||
|
*/
|
||||||
|
|
||||||
|
QString wallpaperPath() const
|
||||||
|
{
|
||||||
|
return m_wallpaperPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint position() const
|
||||||
|
{
|
||||||
|
return m_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTiled() const
|
||||||
|
{
|
||||||
|
return m_isTiled;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wallpaperStyle() const
|
||||||
|
{
|
||||||
|
return m_wallpaperStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor color() const
|
||||||
|
{
|
||||||
|
return m_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void wallpaperPathChanged(QString wallpaperPath);
|
||||||
|
|
||||||
|
void positionChanged(QPoint position);
|
||||||
|
|
||||||
|
void isTiledChanged(bool isTiled);
|
||||||
|
|
||||||
|
void wallpaperStyleChanged(int wallpaperStyle);
|
||||||
|
|
||||||
|
void colorChanged(QColor color);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setWallpaperPath(QString wallpaperPath)
|
||||||
|
{
|
||||||
|
if (m_wallpaperPath == wallpaperPath)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_wallpaperPath = wallpaperPath;
|
||||||
|
emit wallpaperPathChanged(m_wallpaperPath);
|
||||||
|
}
|
||||||
|
void setPosition(QPoint position)
|
||||||
|
{
|
||||||
|
if (m_position == position)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_position = position;
|
||||||
|
emit positionChanged(m_position);
|
||||||
|
}
|
||||||
|
void setIsTiled(bool isTiled)
|
||||||
|
{
|
||||||
|
if (m_isTiled == isTiled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_isTiled = isTiled;
|
||||||
|
emit isTiledChanged(m_isTiled);
|
||||||
|
}
|
||||||
|
void setWallpaperStyle(int wallpaperStyle)
|
||||||
|
{
|
||||||
|
if (m_wallpaperStyle == wallpaperStyle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_wallpaperStyle = wallpaperStyle;
|
||||||
|
emit wallpaperStyleChanged(m_wallpaperStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setColor(QColor color)
|
||||||
|
{
|
||||||
|
if (m_color == color)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_color = color;
|
||||||
|
emit colorChanged(m_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_wallpaperPath;
|
||||||
|
QPoint m_position;
|
||||||
|
bool m_isTiled;
|
||||||
|
int m_wallpaperStyle;
|
||||||
|
QColor m_color;
|
||||||
|
};
|
136
ScreenPlayWindow/src/winwindow.cpp
Normal file
136
ScreenPlayWindow/src/winwindow.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#include "winwindow.h"
|
||||||
|
|
||||||
|
BOOL WINAPI SearchForWorkerWindow(HWND hwnd, LPARAM lparam)
|
||||||
|
{
|
||||||
|
// 0xXXXXXXX "" WorkerW
|
||||||
|
// ...
|
||||||
|
// 0xXXXXXXX "" SHELLDLL_DefView
|
||||||
|
// 0xXXXXXXXX "FolderView" SysListView32
|
||||||
|
// 0xXXXXXXXX "" WorkerW <---- We want this one
|
||||||
|
// 0xXXXXXXXX "Program Manager" Progman
|
||||||
|
if (FindWindowExW(hwnd, nullptr, L"SHELLDLL_DefView", nullptr))
|
||||||
|
*reinterpret_cast<HWND*>(lparam) = FindWindowExW(nullptr, hwnd, L"WorkerW", nullptr);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
WinWindow::WinWindow(QVector<int>& activeScreensList, QString projectPath, QString id, QString volume)
|
||||||
|
: BaseWindow(projectPath)
|
||||||
|
{
|
||||||
|
m_windowHandle = reinterpret_cast<HWND>(m_window.winId());
|
||||||
|
setAppID(id);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
float volumeParsed = volume.toFloat(&ok);
|
||||||
|
if (!ok) {
|
||||||
|
qFatal("Could not parse volume");
|
||||||
|
}
|
||||||
|
setVolume(volumeParsed);
|
||||||
|
|
||||||
|
if (!searchWorkerWindowToParentTo()) {
|
||||||
|
qFatal("No worker window found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// WARNING: Window flags must be called *here*!
|
||||||
|
Qt::WindowFlags flags = m_window.flags();
|
||||||
|
m_window.setFlags(flags | Qt::FramelessWindowHint);
|
||||||
|
SetWindowLongPtr(m_windowHandle, GWL_STYLE, WS_CHILDWINDOW);
|
||||||
|
SetWindowLongPtr(m_windowHandle, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE);
|
||||||
|
|
||||||
|
// Windows coordante system begins at 0x0 at the
|
||||||
|
// main monitor upper left and not at the most left top monitor
|
||||||
|
calcOffsets();
|
||||||
|
|
||||||
|
// Ether for one Screen or for all
|
||||||
|
if ((QApplication::screens().length() == activeScreensList.length()) && (activeScreensList.length() != 1)) {
|
||||||
|
setupWallpaperForAllScreens();
|
||||||
|
} else if (activeScreensList.length() == 1) {
|
||||||
|
setupWallpaperForOneScreen(activeScreensList.at(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_window.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView);
|
||||||
|
m_window.rootContext()->setContextProperty("window", this);
|
||||||
|
m_window.rootContext()->setContextProperty("desktopProperties", &m_windowsDesktopProperties);
|
||||||
|
m_window.setSource(QUrl("qrc:/main.qml"));
|
||||||
|
|
||||||
|
// Let QML decide when were are read to show the window
|
||||||
|
ShowWindow(m_windowHandle, SW_HIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinWindow::setVisible(bool show)
|
||||||
|
{
|
||||||
|
if (show) {
|
||||||
|
ShowWindow(m_windowHandle, SW_SHOW);
|
||||||
|
} else {
|
||||||
|
ShowWindow(m_windowHandle, SW_HIDE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinWindow::destroyThis()
|
||||||
|
{
|
||||||
|
ShowWindow(m_windowHandle, SW_HIDE);
|
||||||
|
|
||||||
|
QCoreApplication::quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinWindow::messageReceived(QString key, QString value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinWindow::calcOffsets()
|
||||||
|
{
|
||||||
|
// Recalculate window coordiantes because of point (0,0)
|
||||||
|
// Is at the origin monitor or the most left
|
||||||
|
|
||||||
|
for (int i = 0; i < QApplication::screens().count(); i++) {
|
||||||
|
QScreen* screen = QApplication::screens().at(i);
|
||||||
|
if (screen->availableGeometry().x() < 0) {
|
||||||
|
m_windowOffsetX += (screen->availableGeometry().x() * -1);
|
||||||
|
}
|
||||||
|
if (screen->availableGeometry().y() < 0) {
|
||||||
|
m_windowOffsetY += (screen->availableGeometry().y() * -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinWindow::setupWallpaperForOneScreen(int activeScreen)
|
||||||
|
{
|
||||||
|
QScreen* screen = QApplication::screens().at(activeScreen);
|
||||||
|
QRect screenRect = screen->geometry();
|
||||||
|
m_window.setHeight(screenRect.height());
|
||||||
|
m_window.setWidth(screenRect.width());
|
||||||
|
if (!SetWindowPos(m_windowHandle, nullptr, screenRect.x() + m_windowOffsetX, screenRect.y() + m_windowOffsetY, screenRect.width(), screenRect.height(), SWP_SHOWWINDOW)) {
|
||||||
|
qFatal("Could not set window pos: ");
|
||||||
|
}
|
||||||
|
if (SetParent(m_windowHandle, m_windowHandleWorker) == nullptr) {
|
||||||
|
qFatal("Could not attach to parent window");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinWindow::setupWallpaperForAllScreens()
|
||||||
|
{
|
||||||
|
QRect rect;
|
||||||
|
for (int i = 0; i < QApplication::screens().count(); i++) {
|
||||||
|
QScreen* screenTmp = QApplication::screens().at(i);
|
||||||
|
rect.setWidth(rect.width() + screenTmp->geometry().width());
|
||||||
|
rect.setHeight(rect.height() + screenTmp->geometry().height());
|
||||||
|
}
|
||||||
|
m_window.setHeight(rect.height());
|
||||||
|
m_window.setWidth(rect.width());
|
||||||
|
if (!SetWindowPos(m_windowHandle, nullptr, 0, 0, rect.width(), rect.height(), SWP_SHOWWINDOW)) {
|
||||||
|
qFatal("Could not set window pos: ");
|
||||||
|
}
|
||||||
|
if (SetParent(m_windowHandle, m_windowHandleWorker) == nullptr) {
|
||||||
|
qFatal("Could not attach to parent window");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinWindow::searchWorkerWindowToParentTo()
|
||||||
|
{
|
||||||
|
HWND progman_hwnd = FindWindowW(L"Progman", L"Program Manager");
|
||||||
|
const DWORD WM_SPAWN_WORKER = 0x052C;
|
||||||
|
SendMessageTimeoutW(progman_hwnd, WM_SPAWN_WORKER, 0xD, 0x1, SMTO_NORMAL,
|
||||||
|
10000, nullptr);
|
||||||
|
|
||||||
|
return EnumWindows(SearchForWorkerWindow, reinterpret_cast<LPARAM>(&m_windowHandleWorker));
|
||||||
|
}
|
45
ScreenPlayWindow/src/winwindow.h
Normal file
45
ScreenPlayWindow/src/winwindow.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQmlContext>
|
||||||
|
#include <QQmlEngine>
|
||||||
|
#include <QQuickView>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QVector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "windowsdesktopproperties.h"
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <qt_windows.h>
|
||||||
|
|
||||||
|
#include "basewindow.h"
|
||||||
|
|
||||||
|
class WinWindow : public BaseWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit WinWindow(QVector<int>& activeScreensList, QString projectPath, QString id, QString volume);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setVisible(bool show) override;
|
||||||
|
void destroyThis() override;
|
||||||
|
void messageReceived(QString key, QString value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calcOffsets();
|
||||||
|
void setupWallpaperForOneScreen(int activeScreen);
|
||||||
|
void setupWallpaperForAllScreens();
|
||||||
|
bool searchWorkerWindowToParentTo();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_windowOffsetX = 0;
|
||||||
|
int m_windowOffsetY = 0;
|
||||||
|
QQuickView m_window;
|
||||||
|
HWND m_windowHandle;
|
||||||
|
HWND m_windowHandleWorker;
|
||||||
|
WindowsDesktopProperties m_windowsDesktopProperties;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user