SceneSwitcher/plugins/base/utils/process-config.cpp
WarmUpTill 7d0332dd0e Restructure library and plugins
The "core" macro conditions and actions have been extracted out to the
"base" plugin.

The library now mostly contains functionality which is required across
all plugins and (e.g. definitions for macro segments).

The goal is to reduce the complexity and cross-dependencies and group
the source files in a better way.

This should relsove the "library limit of 65535 objects exceeded" build
issue occuring in some Windows build environments.
2024-01-27 14:10:34 +01:00

189 lines
5.4 KiB
C++

#include "process-config.hpp"
#include "log-helper.hpp"
#include "name-dialog.hpp"
#include "utility.hpp"
#include <QProcess>
#include <QFileDialog>
namespace advss {
bool ProcessConfig::Save(obs_data_t *obj) const
{
auto data = obs_data_create();
_path.Save(data, "path");
_workingDirectory.Save(data, "workingDirectory");
_args.Save(data, "args", "arg");
obs_data_set_obj(obj, "processConfig", data);
obs_data_release(data);
return true;
}
bool ProcessConfig::Load(obs_data_t *obj)
{
// TODO: Remove this fallback in a future version
if (!obs_data_has_user_value(obj, "processConfig")) {
_path = obs_data_get_string(obj, "path");
_workingDirectory =
obs_data_get_string(obj, "workingDirectory");
_args.Load(obj, "args", "arg");
return true;
}
auto data = obs_data_get_obj(obj, "processConfig");
_path.Load(data, "path");
_workingDirectory.Load(data, "workingDirectory");
_args.Load(data, "args", "arg");
obs_data_release(data);
return true;
}
QStringList ProcessConfig::Args() const
{
QStringList result;
for (auto &arg : _args) {
result << QString::fromStdString(arg);
}
return result;
}
bool ProcessConfig::StartProcessDetached() const
{
return QProcess::startDetached(QString::fromStdString(Path()), Args(),
QString::fromStdString(WorkingDir()));
}
std::variant<int, ProcessConfig::ProcStartError>
ProcessConfig::StartProcessAndWait(int timeout) const
{
QProcess process;
process.setWorkingDirectory(QString::fromStdString(WorkingDir()));
process.start(QString::fromStdString(Path()), Args());
vblog(LOG_INFO, "run \"%s\" with a timeout of %d ms", Path().c_str(),
timeout);
if (!process.waitForFinished(timeout)) {
if (process.error() == QProcess::FailedToStart) {
vblog(LOG_INFO, "failed to start \"%s\"!",
Path().c_str());
return ProcStartError::FAILED_TO_START;
}
vblog(LOG_INFO,
"timeout while running \"%s\"\nAttempting to kill process!",
Path().c_str());
process.kill();
process.waitForFinished();
return ProcStartError::TIMEOUT;
}
if (process.exitStatus() == QProcess::NormalExit) {
return process.exitCode();
}
vblog(LOG_INFO, "process \"%s\" crashed!", Path().c_str());
return ProcStartError::CRASH;
}
ProcessConfigEdit::ProcessConfigEdit(QWidget *parent)
: QWidget(parent),
_filePath(new FileSelection()),
_showAdvancedSettings(new QPushButton(
obs_module_text("AdvSceneSwitcher.process.showAdvanced"))),
_advancedSettingsLayout(new QVBoxLayout()),
_argList(new StringListEdit(
this, obs_module_text("AdvSceneSwitcher.process.addArgument"),
obs_module_text(
"AdvSceneSwitcher.process.addArgumentDescription"),
4096, true)),
_workingDirectory(new FileSelection(FileSelection::Type::FOLDER))
{
_advancedSettingsLayout->setContentsMargins(0, 0, 0, 0);
QWidget::connect(_filePath, SIGNAL(PathChanged(const QString &)), this,
SLOT(PathChanged(const QString &)));
QWidget::connect(_showAdvancedSettings, SIGNAL(clicked()), this,
SLOT(ShowAdvancedSettingsClicked()));
QWidget::connect(_argList,
SIGNAL(StringListChanged(const StringList &)), this,
SLOT(ArgsChanged(const StringList &)));
QWidget::connect(_workingDirectory,
SIGNAL(PathChanged(const QString &)), this,
SLOT(WorkingDirectoryChanged(const QString &)));
auto *entryLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{filePath}}", _filePath},
{"{{workingDirectory}}", _workingDirectory},
{"{{advancedSettings}}", _showAdvancedSettings},
};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.process.entry"),
entryLayout, widgetPlaceholders, false);
auto workingDirectoryLayout = new QHBoxLayout;
PlaceWidgets(obs_module_text(
"AdvSceneSwitcher.process.entry.workingDirectory"),
workingDirectoryLayout, widgetPlaceholders, false);
_advancedSettingsLayout->addWidget(new QLabel(
obs_module_text("AdvSceneSwitcher.process.arguments")));
_advancedSettingsLayout->addWidget(_argList);
_advancedSettingsLayout->addLayout(workingDirectoryLayout);
auto mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addLayout(entryLayout);
mainLayout->addLayout(_advancedSettingsLayout);
setLayout(mainLayout);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
}
void ProcessConfigEdit::SetProcessConfig(const ProcessConfig &conf)
{
_conf = conf;
_filePath->SetPath(conf._path);
_argList->SetStringList(conf._args);
_workingDirectory->SetPath(conf._workingDirectory);
ShowAdvancedSettings(
!_conf._args.empty() ||
!_conf._workingDirectory.UnresolvedValue().empty());
}
void ProcessConfigEdit::PathChanged(const QString &text)
{
_conf._path = text.toStdString();
emit ConfigChanged(_conf);
}
void ProcessConfigEdit::ShowAdvancedSettingsClicked()
{
ShowAdvancedSettings(true);
emit ConfigChanged(_conf); // Just to make sure resizing is handled
}
void ProcessConfigEdit::WorkingDirectoryChanged(const QString &path)
{
_conf._workingDirectory = path.toStdString();
emit ConfigChanged(_conf);
}
void ProcessConfigEdit::ArgsChanged(const StringList &args)
{
_conf._args = args;
adjustSize();
updateGeometry();
emit ConfigChanged(_conf);
}
void ProcessConfigEdit::ShowAdvancedSettings(bool showAdvancedSettings)
{
SetLayoutVisible(_advancedSettingsLayout, showAdvancedSettings);
_showAdvancedSettings->setVisible(!showAdvancedSettings);
adjustSize();
updateGeometry();
if (showAdvancedSettings) {
emit AdvancedSettingsEnabled();
}
}
} // namespace advss