#include "macro-action-wait.hpp" #include "switcher-data.hpp" #include "utility.hpp" #include namespace advss { const std::string MacroActionWait::id = "wait"; bool MacroActionWait::_registered = MacroActionFactory::Register( MacroActionWait::id, {MacroActionWait::Create, MacroActionWaitEdit::Create, "AdvSceneSwitcher.action.wait"}); const static std::map waitTypes = { {WaitType::FIXED, "AdvSceneSwitcher.action.wait.type.fixed"}, {WaitType::RANDOM, "AdvSceneSwitcher.action.wait.type.random"}, }; static std::random_device rd; static std::default_random_engine re(rd()); static void waitHelper(std::unique_lock *lock, Macro *macro, std::chrono::high_resolution_clock::time_point &time) { while (!switcher->abortMacroWait && !macro->GetStop()) { if (switcher->macroWaitCv.wait_until(*lock, time) == std::cv_status::timeout) { break; } } } bool MacroActionWait::PerformAction() { double sleepDuration; if (_waitType == WaitType::FIXED) { sleepDuration = _duration.Seconds(); } else { double min = (_duration.Seconds() < _duration2.Seconds()) ? _duration.Seconds() : _duration2.Seconds(); double max = (_duration.Seconds() < _duration2.Seconds()) ? _duration2.Seconds() : _duration.Seconds(); std::uniform_real_distribution unif(min, max); sleepDuration = unif(re); } vblog(LOG_INFO, "perform action wait with duration of %f", sleepDuration); auto time = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds((int)(sleepDuration * 1000)); switcher->abortMacroWait = false; std::unique_lock lock(switcher->m); waitHelper(&lock, GetMacro(), time); return !switcher->abortMacroWait; } bool MacroActionWait::Save(obs_data_t *obj) const { MacroAction::Save(obj); _duration.Save(obj); _duration2.Save(obj, "duration2"); obs_data_set_int(obj, "waitType", static_cast(_waitType)); obs_data_set_int(obj, "version", 1); return true; } bool MacroActionWait::Load(obs_data_t *obj) { MacroAction::Load(obj); _duration.Load(obj); // TODO: remove this fallback if (obs_data_get_int(obj, "version") == 1) { _duration2.Load(obj, "duration2"); } else { _duration2.Load(obj, "seconds2"); _duration2.SetUnit(static_cast( obs_data_get_int(obj, "displayUnit2"))); } _waitType = static_cast(obs_data_get_int(obj, "waitType")); return true; } static inline void populateTypeSelection(QComboBox *list) { for (auto entry : waitTypes) { list->addItem(obs_module_text(entry.second.c_str())); } } MacroActionWaitEdit::MacroActionWaitEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent) { _duration = new DurationSelection(); _duration2 = new DurationSelection(); _waitType = new QComboBox(); populateTypeSelection(_waitType); QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)), this, SLOT(DurationChanged(const Duration &))); QWidget::connect(_duration2, SIGNAL(DurationChanged(const Duration &)), this, SLOT(Duration2Changed(const Duration &))); QWidget::connect(_waitType, SIGNAL(currentIndexChanged(int)), this, SLOT(TypeChanged(int))); _mainLayout = new QHBoxLayout; setLayout(_mainLayout); _entryData = entryData; UpdateEntryData(); _loading = false; } void MacroActionWaitEdit::UpdateEntryData() { if (!_entryData) { return; } if (_entryData->_waitType == WaitType::FIXED) { SetupFixedDurationEdit(); } else { SetupRandomDurationEdit(); } _duration->SetDuration(_entryData->_duration); _duration2->SetDuration(_entryData->_duration2); _waitType->setCurrentIndex(static_cast(_entryData->_waitType)); } void MacroActionWaitEdit::SetupFixedDurationEdit() { _mainLayout->removeWidget(_duration); _mainLayout->removeWidget(_duration2); _mainLayout->removeWidget(_waitType); ClearLayout(_mainLayout); std::unordered_map widgetPlaceholders = { {"{{duration}}", _duration}, {"{{waitType}}", _waitType}, }; PlaceWidgets( obs_module_text("AdvSceneSwitcher.action.wait.entry.fixed"), _mainLayout, widgetPlaceholders); _duration2->hide(); } void MacroActionWaitEdit::SetupRandomDurationEdit() { _mainLayout->removeWidget(_duration); _mainLayout->removeWidget(_duration2); _mainLayout->removeWidget(_waitType); ClearLayout(_mainLayout); std::unordered_map widgetPlaceholders = { {"{{duration}}", _duration}, {"{{duration2}}", _duration2}, {"{{waitType}}", _waitType}, }; PlaceWidgets( obs_module_text("AdvSceneSwitcher.action.wait.entry.random"), _mainLayout, widgetPlaceholders); _duration2->show(); } void MacroActionWaitEdit::TypeChanged(int value) { if (_loading || !_entryData) { return; } auto lock = LockContext(); WaitType type = static_cast(value); if (type == WaitType::FIXED) { SetupFixedDurationEdit(); } else { SetupRandomDurationEdit(); } _entryData->_waitType = type; } void MacroActionWaitEdit::DurationChanged(const Duration &dur) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_duration = dur; } void MacroActionWaitEdit::Duration2Changed(const Duration &dur) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_duration2 = dur; } } // namespace advss