1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-10-06 09:17:07 +02:00

Add processmanager to check

if a pid is still running
This commit is contained in:
Elias Steurer 2023-12-28 10:10:12 +01:00
parent 5d3d3a905e
commit a17e7f0e78
7 changed files with 114 additions and 10 deletions

View File

@ -16,6 +16,7 @@
#include "ScreenPlay/projectsettingslistmodel.h"
#include "ScreenPlay/sdkconnection.h"
#include "ScreenPlay/settings.h"
#include "ScreenPlayUtil/processmanager.h"
namespace ScreenPlay {
@ -35,6 +36,7 @@ class ScreenPlayWallpaper : public QObject {
Q_PROPERTY(QString appID READ appID WRITE setAppID NOTIFY appIDChanged)
Q_PROPERTY(Video::FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
Q_PROPERTY(ContentTypes::InstalledType type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(qint64 processID READ processID WRITE setProcessID NOTIFY processIDChanged FINAL)
public:
explicit ScreenPlayWallpaper(
@ -79,6 +81,7 @@ public:
ProjectSettingsListModel* getProjectSettingsListModel() { return &m_projectSettingsListModel; }
float playbackRate() const { return m_playbackRate; }
bool isConnected() const { return m_isConnected; }
qint64 processID() const { return m_processID; }
signals:
void screenNumberChanged(QVector<int> screenNumber);
@ -92,13 +95,13 @@ signals:
void volumeChanged(float volume);
void isLoopingChanged(bool isLooping);
void playbackRateChanged(float playbackRate);
void isConnectedChanged(bool isConnected);
void processIDChanged(qint64 processID);
void requestSave();
void requestClose(const QString& appID);
void error(const QString& msg);
void isConnectedChanged(bool isConnected);
public slots:
void close();
void processExit(int exitCode, QProcess::ExitStatus exitStatus);
@ -206,11 +209,20 @@ public slots:
emit isConnectedChanged(m_isConnected);
}
void setProcessID(qint64 processID)
{
if (m_processID == processID)
return;
m_processID = processID;
emit processIDChanged(m_processID);
}
private:
const std::shared_ptr<GlobalVariables> m_globalVariables;
std::unique_ptr<SDKConnection> m_connection;
const std::shared_ptr<Settings> m_settings;
ProcessManager m_processManager;
ProjectSettingsListModel m_projectSettingsListModel;
QJsonObject m_projectJson;
QVector<int> m_screenNumber;
@ -230,5 +242,6 @@ private:
// There are still cases where we can access the current item
// while exiting. This flag is to ignore all setWallpaperValue calls
bool m_isExiting { false };
qint64 m_processID { 0 };
};
}

View File

@ -13,10 +13,9 @@
#include "ScreenPlay/globalvariables.h"
#include "ScreenPlay/projectsettingslistmodel.h"
#include "ScreenPlay/sdkconnection.h"
#include "ScreenPlayUtil/util.h"
#include "ScreenPlayUtil/processmanager.h"
#include <memory>
#include <utility>
namespace ScreenPlay {
@ -30,6 +29,7 @@ class ScreenPlayWidget : public QObject {
Q_PROPERTY(QPoint position READ position WRITE setPosition NOTIFY positionChanged)
Q_PROPERTY(QString appID READ appID WRITE setAppID NOTIFY appIDChanged)
Q_PROPERTY(ContentTypes::InstalledType type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(qint64 processID READ processID WRITE setProcessID NOTIFY processIDChanged FINAL)
public:
explicit ScreenPlayWidget(
@ -49,6 +49,7 @@ public:
QString absolutePath() const { return m_absolutePath; }
QString appID() const { return m_appID; }
ContentTypes::InstalledType type() const { return m_type; }
qint64 processID() const { return m_processID; }
void setSDKConnection(std::unique_ptr<SDKConnection> connection);
@ -103,6 +104,13 @@ public slots:
emit absolutePathChanged(m_absolutePath);
}
void setProcessID(qint64 processID)
{
if (m_processID == processID)
return;
m_processID = processID;
emit processIDChanged(m_processID);
}
signals:
void previewImageChanged(QString previewImage);
void positionChanged(QPoint position);
@ -114,11 +122,14 @@ signals:
void requestClose(const QString& appID);
void error(const QString& msg);
void processIDChanged(qint64 processID);
private:
const std::shared_ptr<GlobalVariables> m_globalVariables;
std::unique_ptr<SDKConnection> m_connection;
ProjectSettingsListModel m_projectSettingsListModel;
ProcessManager m_processManager;
QProcess m_process;
QString m_previewImage;
QString m_appID;
@ -127,5 +138,6 @@ private:
QString m_absolutePath;
QTimer m_pingAliveTimer;
QStringList m_appArgumentsList;
qint64 m_processID { 0 };
};
}

View File

@ -110,8 +110,6 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(
bool ScreenPlayWallpaper::start()
{
m_process.setArguments(m_appArgumentsList);
if (m_type == ContentTypes::InstalledType::GodotWallpaper) {
m_process.setProgram(m_globalVariables->godotWallpaperExecutablePath().toString());
} else {
@ -121,7 +119,9 @@ bool ScreenPlayWallpaper::start()
// We must start detatched otherwise we would instantly close the process
// and would loose the animted fade-out and the background refresh needed
// to display the original wallpaper.
const bool success = m_process.startDetached();
m_process.setArguments(m_appArgumentsList);
const bool success = m_process.startDetached(&m_processID);
emit processIDChanged(m_processID);
qInfo() << "Starting ScreenPlayWallpaper detached: " << (success ? "success" : "failed!") << m_process.program();
qInfo() << m_appArgumentsList;
if (!success) {
@ -257,6 +257,7 @@ void ScreenPlayWallpaper::setSDKConnection(std::unique_ptr<SDKConnection> connec
});
m_pingAliveTimer.start(GlobalVariables::contentPingAliveIntervalMS);
});
// Check every X seconds if the wallpaper is still alive
QObject::connect(m_connection.get(), &SDKConnection::pingAliveReceived, this, [this]() {
m_pingAliveTimer.stop();

View File

@ -69,12 +69,13 @@ bool ScreenPlayWidget::start()
QObject::connect(&m_process, &QProcess::errorOccurred, this, [](QProcess::ProcessError error) {
qDebug() << "error: " << error;
});
const bool success = m_process.startDetached();
const bool success = m_process.startDetached(&m_processID);
qInfo() << "Starting ScreenPlayWidget detached: " << (success ? "success" : "failed!");
if (!success) {
emit error(QString("Could not start Widget: " + m_process.errorString()));
return false;
}
emit processIDChanged(m_processID);
return success;
}

View File

@ -43,8 +43,8 @@ set(QML
qml/TextField.qml)
set(SOURCES
# cmake-format: sort
src/processmanager.cpp
src/archive.cpp
src/contenttypes.cpp
src/exitcodes.cpp
@ -54,8 +54,8 @@ set(SOURCES
src/util.cpp)
set(HEADER
# cmake-format: sort
inc/public/ScreenPlayUtil/processmanager.h
inc/public/ScreenPlayUtil/archive.h
inc/public/ScreenPlayUtil/contenttypes.h
inc/public/ScreenPlayUtil/exitcodes.h

View File

@ -0,0 +1,21 @@
#pragma once
#include <QDebug>
#include <QProcess>
#include <optional>
#if defined(Q_OS_WIN)
#include <Windows.h>
#elif defined(Q_OS_LINUX) || defined(Q_OS_MAC)
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#endif
namespace ScreenPlay {
class ProcessManager {
public:
std::optional<bool> isRunning(const qint64 pid);
bool terminateProcess(const qint64 pid);
};
}

View File

@ -0,0 +1,56 @@
#include "processmanager.h"
namespace ScreenPlay {
std::optional<bool> ProcessManager::isRunning(const qint64 pid)
{
if (pid <= 0)
return std::nullopt;
#if defined(Q_OS_WIN)
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (process) {
DWORD exitCode;
if (GetExitCodeProcess(process, &exitCode)) {
CloseHandle(process);
return exitCode == STILL_ACTIVE;
}
CloseHandle(process);
}
#elif defined(Q_OS_LINUX) || defined(Q_OS_MAC)
int status = kill(pid, 0);
if (status == 0)
return true;
if (errno == ESRCH)
return false;
#endif
return std::nullopt;
}
bool ProcessManager::terminateProcess(const qint64 pid)
{
if (pid <= 0)
return false;
#if defined(Q_OS_WIN)
HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (process) {
BOOL result = TerminateProcess(process, 1);
CloseHandle(process);
if (!result) {
qDebug() << "Failed to terminate process on Windows. Error code:" << GetLastError();
return false;
}
return true;
} else {
qDebug() << "Failed to open process for termination on Windows. Error code:" << GetLastError();
return false;
}
#elif defined(Q_OS_LINUX) || defined(Q_OS_MAC)
if (kill(pid, SIGTERM) == -1) {
qDebug() << "Failed to send termination signal on Linux/macOS. Error:" << strerror(errno);
return false;
}
return true;
#endif
}
}