Add macro condition "timer" (previously known as "interval")

This commit is contained in:
WarmUpTill 2021-06-14 11:39:36 +02:00 committed by WarmUpTill
parent 5e4258968a
commit 311ee5d0a0
7 changed files with 198 additions and 101 deletions

View File

@ -101,7 +101,6 @@ set(advanced-scene-switcher_HEADERS
src/headers/macro-condition-file.hpp
src/headers/macro-condition-filter.hpp
src/headers/macro-condition-idle.hpp
src/headers/macro-condition-interval.hpp
src/headers/macro-condition-media.hpp
src/headers/macro-condition-plugin-state.hpp
src/headers/macro-condition-process.hpp
@ -110,6 +109,7 @@ set(advanced-scene-switcher_HEADERS
src/headers/macro-condition-scene.hpp
src/headers/macro-condition-source.hpp
src/headers/macro-condition-streaming.hpp
src/headers/macro-condition-timer.hpp
src/headers/macro-condition-video.hpp
src/headers/macro-condition-virtual-cam.hpp
src/headers/macro-condition-window.hpp
@ -174,7 +174,6 @@ set(advanced-scene-switcher_SOURCES
src/macro-condition-file.cpp
src/macro-condition-filter.cpp
src/macro-condition-idle.cpp
src/macro-condition-interval.cpp
src/macro-condition-media.cpp
src/macro-condition-plugin-state.cpp
src/macro-condition-process.cpp
@ -183,6 +182,7 @@ set(advanced-scene-switcher_SOURCES
src/macro-condition-scene.cpp
src/macro-condition-source.cpp
src/macro-condition-streaming.cpp
src/macro-condition-timer.cpp
src/macro-condition-video.cpp
src/macro-condition-virtual-cam.cpp
src/macro-condition-window.cpp

View File

@ -124,8 +124,11 @@ AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for {{duratio
AdvSceneSwitcher.condition.pluginState="Plugin state"
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene change was triggered in this interval"
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
AdvSceneSwitcher.condition.interval="Interval"
AdvSceneSwitcher.condition.interval.entry="{{duration}} have passed"
AdvSceneSwitcher.condition.timer="Timer"
AdvSceneSwitcher.condition.timer.entry.line1="{{duration}} have passed"
AdvSceneSwitcher.condition.timer.entry.line2="Time remaining: {{remaining}} seconds"
AdvSceneSwitcher.condition.timer.entry.line3="{{reset}} {{autoReset}} Automatically reset timer after duration was reached"
AdvSceneSwitcher.condition.timer.reset="Reset"
AdvSceneSwitcher.condition.macro="Macro"
AdvSceneSwitcher.condition.macro.type.count="Count"
AdvSceneSwitcher.condition.macro.type.state="State"

View File

@ -32,6 +32,20 @@ bool Duration::DurationReached()
return runTime.count() >= seconds * 1000;
}
double Duration::TimeRemaining()
{
if (_startTime.time_since_epoch().count() == 0) {
return seconds;
}
auto runTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - _startTime);
if (runTime.count() >= seconds * 1000) {
return 0;
}
return (seconds * 1000 - runTime.count()) / 1000.;
}
void Duration::Reset()
{
_startTime = {};

View File

@ -21,6 +21,7 @@ public:
const char *unitName = "displayUnit");
bool DurationReached();
double TimeRemaining();
void Reset();
std::string ToString();

View File

@ -2,9 +2,10 @@
#include "macro.hpp"
#include <QWidget>
#include <QComboBox>
#include <QTimer>
#include "duration-control.hpp"
class MacroConditionInterval : public MacroCondition {
class MacroConditionTimer : public MacroCondition {
public:
bool CheckCondition();
bool Save(obs_data_t *obj);
@ -12,41 +13,48 @@ public:
std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create()
{
return std::make_shared<MacroConditionInterval>();
return std::make_shared<MacroConditionTimer>();
}
Duration _duration;
bool _oneshot = false;
private:
static bool _registered;
static const std::string id;
};
class MacroConditionIntervalEdit : public QWidget {
class MacroConditionTimerEdit : public QWidget {
Q_OBJECT
public:
MacroConditionIntervalEdit(
MacroConditionTimerEdit(
QWidget *parent,
std::shared_ptr<MacroConditionInterval> cond = nullptr);
std::shared_ptr<MacroConditionTimer> cond = nullptr);
void UpdateEntryData();
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroCondition> cond)
{
return new MacroConditionIntervalEdit(
return new MacroConditionTimerEdit(
parent,
std::dynamic_pointer_cast<MacroConditionInterval>(
cond));
std::dynamic_pointer_cast<MacroConditionTimer>(cond));
}
private slots:
void DurationChanged(double seconds);
void DurationUnitChanged(DurationUnit unit);
void AutoResetChanged(int state);
void ResetClicked();
void UpdateTimeRemaining();
protected:
DurationSelection *_duration;
std::shared_ptr<MacroConditionInterval> _entryData;
QCheckBox *_autoReset;
QPushButton *_reset;
QLabel *_remaining;
std::shared_ptr<MacroConditionTimer> _entryData;
private:
QTimer timer;
bool _loading = true;
};

View File

@ -1,88 +0,0 @@
#include "headers/macro-condition-edit.hpp"
#include "headers/macro-condition-interval.hpp"
#include "headers/utility.hpp"
#include "headers/advanced-scene-switcher.hpp"
const std::string MacroConditionInterval::id = "interval";
bool MacroConditionInterval::_registered = MacroConditionFactory::Register(
MacroConditionInterval::id,
{MacroConditionInterval::Create, MacroConditionIntervalEdit::Create,
"AdvSceneSwitcher.condition.interval", false});
bool MacroConditionInterval::CheckCondition()
{
if (_duration.DurationReached()) {
_duration.Reset();
return true;
}
return false;
}
bool MacroConditionInterval::Save(obs_data_t *obj)
{
MacroCondition::Save(obj);
_duration.Save(obj);
return true;
}
bool MacroConditionInterval::Load(obs_data_t *obj)
{
MacroCondition::Load(obj);
_duration.Load(obj);
return true;
}
MacroConditionIntervalEdit::MacroConditionIntervalEdit(
QWidget *parent, std::shared_ptr<MacroConditionInterval> entryData)
: QWidget(parent)
{
_duration = new DurationSelection();
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
SLOT(DurationChanged(double)));
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
SLOT(DurationUnitChanged(DurationUnit)));
QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{duration}}", _duration},
};
placeWidgets(
obs_module_text("AdvSceneSwitcher.condition.interval.entry"),
mainLayout, widgetPlaceholders);
setLayout(mainLayout);
_entryData = entryData;
UpdateEntryData();
_loading = false;
}
void MacroConditionIntervalEdit::DurationChanged(double seconds)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_duration.seconds = seconds;
}
void MacroConditionIntervalEdit::DurationUnitChanged(DurationUnit unit)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_duration.displayUnit = unit;
}
void MacroConditionIntervalEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}
_duration->SetDuration(_entryData->_duration);
}

View File

@ -0,0 +1,159 @@
#include "headers/macro-condition-edit.hpp"
#include "headers/macro-condition-timer.hpp"
#include "headers/utility.hpp"
#include "headers/advanced-scene-switcher.hpp"
const std::string MacroConditionTimer::id = "timer";
bool MacroConditionTimer::_registered = MacroConditionFactory::Register(
MacroConditionTimer::id,
{MacroConditionTimer::Create, MacroConditionTimerEdit::Create,
"AdvSceneSwitcher.condition.timer", false});
// TODO: Remove in future version - just added for backward compatibility
static const std::string idOld = "interval";
static bool oldRegisterd = MacroConditionFactory::Register(
idOld, {MacroConditionTimer::Create, MacroConditionTimerEdit::Create,
"AdvSceneSwitcher.condition.timer", false});
bool MacroConditionTimer::CheckCondition()
{
if (_duration.DurationReached()) {
if (!_oneshot) {
_duration.Reset();
}
return true;
}
return false;
}
bool MacroConditionTimer::Save(obs_data_t *obj)
{
MacroCondition::Save(obj);
_duration.Save(obj);
obs_data_set_bool(obj, "oneshot", _oneshot);
return true;
}
bool MacroConditionTimer::Load(obs_data_t *obj)
{
MacroCondition::Load(obj);
_duration.Load(obj);
if (!obs_data_has_user_value(obj, "oneshot")) {
_oneshot = false;
} else {
_oneshot = obs_data_get_bool(obj, "oneshot");
}
return true;
}
MacroConditionTimerEdit::MacroConditionTimerEdit(
QWidget *parent, std::shared_ptr<MacroConditionTimer> entryData)
: QWidget(parent)
{
_duration = new DurationSelection();
_autoReset = new QCheckBox();
_reset = new QPushButton(
obs_module_text("AdvSceneSwitcher.condition.timer.reset"));
_remaining = new QLabel();
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
SLOT(DurationChanged(double)));
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
SLOT(DurationUnitChanged(DurationUnit)));
QWidget::connect(_reset, SIGNAL(clicked()), this, SLOT(ResetClicked()));
QWidget::connect(_autoReset, SIGNAL(stateChanged(int)), this,
SLOT(AutoResetChanged(int)));
auto line1Layout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{duration}}", _duration},
{"{{autoReset}}", _autoReset},
{"{{remaining}}", _remaining},
{"{{reset}}", _reset},
};
placeWidgets(
obs_module_text("AdvSceneSwitcher.condition.timer.entry.line1"),
line1Layout, widgetPlaceholders);
auto line2Layout = new QHBoxLayout;
placeWidgets(
obs_module_text("AdvSceneSwitcher.condition.timer.entry.line2"),
line2Layout, widgetPlaceholders);
auto line3Layout = new QHBoxLayout;
placeWidgets(
obs_module_text("AdvSceneSwitcher.condition.timer.entry.line3"),
line3Layout, widgetPlaceholders);
auto *mainLayout = new QVBoxLayout;
mainLayout->addLayout(line1Layout);
mainLayout->addLayout(line2Layout);
mainLayout->addLayout(line3Layout);
setLayout(mainLayout);
_entryData = entryData;
UpdateEntryData();
_loading = false;
connect(&timer, SIGNAL(timeout()), this, SLOT(UpdateTimeRemaining()));
timer.start(1000);
}
void MacroConditionTimerEdit::DurationChanged(double seconds)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_duration.seconds = seconds;
}
void MacroConditionTimerEdit::DurationUnitChanged(DurationUnit unit)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_duration.displayUnit = unit;
}
void MacroConditionTimerEdit::AutoResetChanged(int state)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_oneshot = !state;
}
void MacroConditionTimerEdit::ResetClicked()
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_duration.Reset();
}
void MacroConditionTimerEdit::UpdateTimeRemaining()
{
if (!_entryData) {
_remaining->setText("-");
return;
}
_remaining->setText(
QString::number(_entryData->_duration.TimeRemaining()));
}
void MacroConditionTimerEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}
_duration->SetDuration(_entryData->_duration);
_autoReset->setChecked(!_entryData->_oneshot);
}