From 428850306f4392303a6a64e0da893bf4cd660226 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Wed, 20 Dec 2023 21:42:15 +0100 Subject: [PATCH] Add option to wait for spawned process to exit --- data/locale/en-US.ini | 1 + src/macro-core/macro-action-run.cpp | 65 ++++++++++++++++++++++++++--- src/macro-core/macro-action-run.hpp | 16 +++++-- 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 5dc3cdc1..a768f921 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -610,6 +610,7 @@ AdvSceneSwitcher.action.streaming.type.username="Set username" AdvSceneSwitcher.action.streaming.type.password="Set password" AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}" AdvSceneSwitcher.action.run="Run" +AdvSceneSwitcher.action.run.entry.wait="{{wait}}Wait for process exit or at most {{timeout}}" AdvSceneSwitcher.action.sceneVisibility="Scene item visibility" AdvSceneSwitcher.action.sceneVisibility.type.show="Show" AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide" diff --git a/src/macro-core/macro-action-run.cpp b/src/macro-core/macro-action-run.cpp index 5348c543..be9e979f 100644 --- a/src/macro-core/macro-action-run.cpp +++ b/src/macro-core/macro-action-run.cpp @@ -14,9 +14,14 @@ bool MacroActionRun::_registered = MacroActionFactory::Register( bool MacroActionRun::PerformAction() { - bool procStarted = QProcess::startDetached( - QString::fromStdString(_procConfig.Path()), _procConfig.Args(), - QString::fromStdString(_procConfig.WorkingDir())); + if (_wait) { + _procConfig.StartProcessAndWait(_timeout.Milliseconds()); + return true; + } + + bool procStarted = _procConfig.StartProcessDetached(); + + // Fall back to using default application to open given file if (!procStarted && _procConfig.Args().empty()) { vblog(LOG_INFO, "run \"%s\" using QDesktopServices", _procConfig.Path().c_str()); @@ -35,6 +40,9 @@ bool MacroActionRun::Save(obs_data_t *obj) const { MacroAction::Save(obj); _procConfig.Save(obj); + _timeout.Save(obj); + obs_data_set_bool(obj, "wait", _wait); + obs_data_set_int(obj, "version", 1); return true; } @@ -42,6 +50,12 @@ bool MacroActionRun::Load(obs_data_t *obj) { MacroAction::Load(obj); _procConfig.Load(obj); + // TODO: Remove this fallback in a future version + if (!obs_data_has_user_value(obj, "version")) { + return true; + } + _timeout.Load(obj); + _wait = obs_data_get_bool(obj, "wait"); return true; } @@ -52,14 +66,30 @@ std::string MacroActionRun::GetShortDesc() const MacroActionRunEdit::MacroActionRunEdit( QWidget *parent, std::shared_ptr entryData) - : QWidget(parent), _procConfig(new ProcessConfigEdit(this)) + : QWidget(parent), + _procConfig(new ProcessConfigEdit(this)), + _waitLayout(new QHBoxLayout()), + _wait(new QCheckBox()), + _timeout(new DurationSelection(this, true, 0.1)) { QWidget::connect(_procConfig, SIGNAL(ConfigChanged(const ProcessConfig &)), this, SLOT(ProcessConfigChanged(const ProcessConfig &))); + QWidget::connect(_procConfig, SIGNAL(AdvancedSettingsEnabled()), this, + SLOT(ProcessConfigAdvancedSettingsShown())); + QWidget::connect(_wait, SIGNAL(stateChanged(int)), this, + SLOT(WaitChanged(int))); + QWidget::connect(_timeout, SIGNAL(DurationChanged(const Duration &)), + this, SLOT(TimeoutChanged(const Duration &))); - auto *layout = new QVBoxLayout; + PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry.wait"), + _waitLayout, + {{"{{wait}}", _wait}, {"{{timeout}}", _timeout}}); + SetLayoutVisible(_waitLayout, false); + + auto layout = new QVBoxLayout; layout->addWidget(_procConfig); + layout->addLayout(_waitLayout); setLayout(layout); _entryData = entryData; @@ -73,6 +103,31 @@ void MacroActionRunEdit::UpdateEntryData() return; } _procConfig->SetProcessConfig(_entryData->_procConfig); + _wait->setChecked(_entryData->_wait); + _timeout->SetDuration(_entryData->_timeout); +} + +void MacroActionRunEdit::ProcessConfigAdvancedSettingsShown() +{ + SetLayoutVisible(_waitLayout, true); +} + +void MacroActionRunEdit::WaitChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + auto lock = LockContext(); + _entryData->_wait = value; +} + +void MacroActionRunEdit::TimeoutChanged(const Duration &timeout) +{ + if (_loading || !_entryData) { + return; + } + auto lock = LockContext(); + _entryData->_timeout = timeout; } void MacroActionRunEdit::ProcessConfigChanged(const ProcessConfig &conf) diff --git a/src/macro-core/macro-action-run.hpp b/src/macro-core/macro-action-run.hpp index ca94a2cf..a17f5065 100644 --- a/src/macro-core/macro-action-run.hpp +++ b/src/macro-core/macro-action-run.hpp @@ -1,6 +1,9 @@ #pragma once #include "macro-action-edit.hpp" #include "process-config.hpp" +#include "duration-control.hpp" + +#include namespace advss { @@ -19,6 +22,8 @@ public: } ProcessConfig _procConfig; + bool _wait = false; + Duration _timeout = 1; private: static bool _registered; @@ -42,14 +47,19 @@ public: private slots: void ProcessConfigChanged(const ProcessConfig &); + void ProcessConfigAdvancedSettingsShown(); + void WaitChanged(int); + void TimeoutChanged(const Duration &); signals: void HeaderInfoChanged(const QString &); -protected: - std::shared_ptr _entryData; - private: ProcessConfigEdit *_procConfig; + QHBoxLayout *_waitLayout; + QCheckBox *_wait; + DurationSelection *_timeout; + + std::shared_ptr _entryData; bool _loading = true; };