#include "duration-control.hpp" #include "mouse-wheel-guard.hpp" #include "obs-module.h" #include "utility.hpp" #include #include #include namespace advss { Duration::Duration(double initialValueInSeconds) : _value(initialValueInSeconds) { } void Duration::Save(obs_data_t *obj, const char *name) const { auto data = obs_data_create(); _value.Save(data, "value"); obs_data_set_int(data, "unit", static_cast(_unit)); obs_data_set_int(data, "version", 1); obs_data_set_obj(obj, name, data); obs_data_release(data); } static int durationUnitToMultiplier(Duration::Unit u) { switch (u) { case Duration::Unit::SECONDS: return 1; case Duration::Unit::MINUTES: return 60; case Duration::Unit::HOURS: return 3600; default: break; } return 0; } void Duration::Load(obs_data_t *obj, const char *name) { auto data = obs_data_get_obj(obj, name); // TODO: remove this fallback if (!data || !obs_data_has_user_value(data, "version") || obs_data_get_int(data, "version") != 1) { bool usingDefaultArgs = strcmp("duration", name) == 0; if (usingDefaultArgs) { _value = obs_data_get_double(obj, "seconds"); } if (_value.GetValue() == 0.0) { _value = obs_data_get_double(obj, name); } if (usingDefaultArgs) { _unit = static_cast( obs_data_get_int(obj, "displayUnit")); } else if (_value.GetValue() >= 86400) { _unit = (_value.GetValue() / 60 >= 86400) ? Duration::Unit::HOURS : Duration::Unit::MINUTES; } else { _unit = Duration::Unit::SECONDS; } _value = _value / durationUnitToMultiplier(_unit); obs_data_release(data); return; } _value.Load(data, "value"); _unit = static_cast(obs_data_get_int(data, "unit")); obs_data_release(data); } bool Duration::DurationReached() { if (IsReset()) { _startTime = std::chrono::high_resolution_clock::now(); } auto runTime = std::chrono::duration_cast( std::chrono::high_resolution_clock::now() - _startTime); return runTime.count() >= Milliseconds(); } bool Duration::IsReset() const { return _startTime.time_since_epoch().count() == 0; } double Duration::Seconds() const { return _value.GetValue() * durationUnitToMultiplier(_unit); } double Duration::Milliseconds() const { return Seconds() * 1000.0; } double Duration::TimeRemaining() const { if (IsReset()) { return Seconds(); } auto runTime = std::chrono::duration_cast( std::chrono::high_resolution_clock::now() - _startTime); if (runTime.count() >= Milliseconds()) { return 0; } return (Milliseconds() - runTime.count()) / 1000.0; } void Duration::SetTimeRemaining(double remaining) { long long msPassed = (Seconds() - remaining) * 1000; _startTime = std::chrono::high_resolution_clock::now() - std::chrono::milliseconds(msPassed); } void Duration::Reset() { _startTime = {}; } static std::string durationUnitToString(Duration::Unit u) { switch (u) { case Duration::Unit::SECONDS: return obs_module_text("AdvSceneSwitcher.unit.secends"); case Duration::Unit::MINUTES: return obs_module_text("AdvSceneSwitcher.unit.minutes"); case Duration::Unit::HOURS: return obs_module_text("AdvSceneSwitcher.unit.hours"); default: break; } return ""; } std::string Duration::ToString() const { std::ostringstream ss; ss << std::fixed << std::setprecision(2) << _value.GetValue() << " " << durationUnitToString(_unit); if (!_value.IsFixedType()) { ss << " [" << GetWeakVariableName(_value.GetVariable()) << "]"; } return ss.str(); } void Duration::SetUnit(Unit u) { double prevMultiplier = durationUnitToMultiplier(_unit); double newMultiplier = durationUnitToMultiplier(u); _unit = u; _value = _value * (prevMultiplier / newMultiplier); } static void populateUnits(QComboBox *list) { list->addItem(obs_module_text("AdvSceneSwitcher.unit.secends")); list->addItem(obs_module_text("AdvSceneSwitcher.unit.minutes")); list->addItem(obs_module_text("AdvSceneSwitcher.unit.hours")); } DurationSelection::DurationSelection(QWidget *parent, bool showUnitSelection, double minValue) : QWidget(parent), _duration(new VariableDoubleSpinBox(parent)), _unitSelection(new QComboBox()) { _duration->setMinimum(minValue); _duration->setMaximum(86400); // 24 hours PreventMouseWheelAdjustWithoutFocus(_duration); populateUnits(_unitSelection); QWidget::connect( _duration, SIGNAL(NumberVariableChanged(const NumberVariable &)), this, SLOT(_DurationChanged(const NumberVariable &))); QWidget::connect(_unitSelection, SIGNAL(currentIndexChanged(int)), this, SLOT(_UnitChanged(int))); QHBoxLayout *layout = new QHBoxLayout; layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(11); layout->addWidget(_duration); if (showUnitSelection) { layout->addWidget(_unitSelection); } setLayout(layout); } void DurationSelection::SetDuration(const Duration &d) { _current = d; _duration->SetValue(d._value); const QSignalBlocker b(_unitSelection); _unitSelection->setCurrentIndex(static_cast(d._unit)); } void DurationSelection::_DurationChanged(const NumberVariable &value) { _current._value = value; emit DurationChanged(_current); } void DurationSelection::_UnitChanged(int idx) { Duration::Unit unit = static_cast(idx); double prevMultiplier = durationUnitToMultiplier(_current._unit); double newMultiplier = durationUnitToMultiplier(unit); _current._unit = unit; const QSignalBlocker b(_duration); _duration->SetFixedValue(_duration->Value() * (prevMultiplier / newMultiplier)); emit DurationChanged(_current); } } // namespace advss