#pragma once #include "macro-action.hpp" #include "macro-condition.hpp" #include "macro-dock-settings.hpp" #include "macro-helpers.hpp" #include "macro-input.hpp" #include "macro-ref.hpp" #include "variable-string.hpp" #include "temp-variable.hpp" #include #include #include #include #include #include #include #include namespace advss { class GlobalMacroSettings; class Macro { using TimePoint = std::chrono::high_resolution_clock::time_point; public: enum class PauseStateSaveBehavior { PERSIST, PAUSE, UNPAUSE }; enum class ActionTriggerMode { // Trigger always ALWAYS, // Trigger when macro match result flips MACRO_RESULT_CHANGED, // Trigger when any individual condition changes ANY_CONDITION_CHANGED, // Trigger when any individual condition evaluates to true ANY_CONDITION_TRIGGERED, }; Macro(const std::string &name = ""); Macro(const std::string &name, const GlobalMacroSettings &settings); ~Macro(); std::string Name() const { return _name; } void SetName(const std::string &name); bool CheckConditions(bool ignorePause = false); bool ConditionsMatched() const { return _matched; } TimePoint LastConditionCheckTime() const { return _lastCheckTime; } bool ConditionsShouldBeChecked() const; bool ShouldRunActions() const; bool PerformActions(bool match, bool forceParallel = false, bool ignorePause = false); void SetPaused(bool pause = true); bool Paused() const { return _paused; } bool WasPausedSince(const TimePoint &) const; void SetPauseStateSaveBehavior(PauseStateSaveBehavior); PauseStateSaveBehavior GetPauseStateSaveBehavior() const; void Stop(); bool GetStop() const { return _stop; } void ResetTimers(); void SetActionTriggerMode(ActionTriggerMode); ActionTriggerMode GetActionTriggerMode() const; void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; } bool SkipExecOnStart() const { return _skipExecOnStart; } void SetStopActionsIfNotDone(bool stopActionsIfNotDone); bool StopActionsIfNotDone() const { return _stopActionsIfNotDone; } void SetShortCircuitEvaluation(bool useShortCircuitEvaluation); bool ShortCircuitEvaluationEnabled() const; void SetCustomConditionCheckIntervalEnabled(bool enable); bool CustomConditionCheckIntervalEnabled() const; void SetCustomConditionCheckInterval(const Duration &); Duration GetCustomConditionCheckInterval() const; int RunCount() const { return _runCount; }; void ResetRunCount() { _runCount = 0; }; void AddHelperThread(std::thread &&); void SetRunInParallel(bool parallel) { _runInParallel = parallel; } bool RunInParallel() const { return _runInParallel; } bool CheckInParallel() const { return _checkInParallel; } void SetCheckInParallel(bool parallel); bool ParallelTasksCompleted() const; // Input variables MacroInputVariables GetInputVariables() const; void SetInputVariables(const MacroInputVariables &); // Temporary variable helpers std::vector GetTempVars(const MacroSegment *filter) const; std::optional GetTempVar(const MacroSegment *, const std::string &id) const; void InvalidateTempVarValues() const; // Macro segments std::deque> &Conditions(); const std::deque> &Conditions() const; std::deque> &Actions(); const std::deque> &Actions() const; std::deque> &ElseActions(); const std::deque> &ElseActions() const; void UpdateActionIndices(); void UpdateElseActionIndices(); void UpdateConditionIndices(); // Group controls static std::shared_ptr CreateGroup(const std::string &name, std::vector> &children); static void RemoveGroup(std::shared_ptr); static void PrepareMoveToGroup(Macro *group, std::shared_ptr item); static void PrepareMoveToGroup(std::shared_ptr group, std::shared_ptr item); bool IsGroup() const { return _isGroup; } uint32_t GroupSize() const { return _groupSize; } void ResetGroupSize() { _groupSize = 0; } bool IsSubitem() const { return !_parent.expired(); } void SetCollapsed(bool val) { _isCollapsed = val; } bool IsCollapsed() const { return _isCollapsed; } void SetParent(std::shared_ptr m) { _parent = m; } std::shared_ptr Parent() const; // Saving and loading bool Save(obs_data_t *obj, bool saveForCopy = false) const; bool Load(obs_data_t *obj); // Some macros can refer to other macros, which are not yet loaded. // Use this function to set these references after loading is complete. bool PostLoad(); // Helper function for plugin state condition regarding scene change bool SwitchesScene() const; // UI helpers void SetActionConditionSplitterPosition(const QList); const QList &GetActionConditionSplitterPosition() const; void SetElseActionSplitterPosition(const QList); const QList &GetElseActionSplitterPosition() const; bool HasValidSplitterPositions() const; bool WasExecutedSince(const TimePoint &) const; bool ActionTriggerModePreventedActionsSince(const TimePoint &) const; TimePoint GetLastExecutionTime() const; void ResetUIHelpers(); // Hotkeys void EnablePauseHotkeys(bool); bool PauseHotkeysEnabled() const; // Docks MacroDockSettings &GetDockSettings() { return _dockSettings; } private: void SetupHotkeys(); void ClearHotkeys() const; void SetHotkeysDesc() const; bool CheckConditionHelper(const std::shared_ptr &) const; bool RunActionsHelper( const std::deque> &actions, bool ignorePause); bool RunActions(bool ignorePause); bool RunElseActions(bool ignorePause); std::string _name = ""; bool _die = false; bool _stop = false; std::future _actionRunFuture; TimePoint _lastCheckTime{}; TimePoint _lastUnpauseTime{}; TimePoint _lastExecutionTime{}; TimePoint _lastActionRunModePreventTime{}; std::vector _helperThreads; std::deque> _conditions; std::deque> _actions; std::deque> _elseActions; std::weak_ptr _parent; uint32_t _groupSize = 0; bool _isGroup = false; bool _isCollapsed = false; bool _useShortCircuitEvaluation = false; bool _useCustomConditionCheckInterval = false; Duration _customConditionCheckInterval = 0.3; bool _actionModeMatch = false; bool _runInParallel = false; bool _checkInParallel = false; bool _matched = false; std::future _conditionCheckFuture; bool _lastMatched = false; bool _skipExecOnStart = false; bool _stopActionsIfNotDone = false; bool _paused = false; int _runCount = 0; bool _registerHotkeys = true; obs_hotkey_id _pauseHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID; ActionTriggerMode _actionTriggerMode = ActionTriggerMode::MACRO_RESULT_CHANGED; PauseStateSaveBehavior _pauseSaveBehavior = PauseStateSaveBehavior::PERSIST; MacroInputVariables _inputVariables; QList _actionConditionSplitterPosition; QList _elseActionSplitterPosition; MacroDockSettings _dockSettings; }; void LoadMacros(obs_data_t *obj); void SaveMacros(obs_data_t *obj); bool CheckMacros(); bool RunMacros(); void StopAllMacros(); void InvalidateMacroTempVarValues(); std::shared_ptr GetMacroWithInvalidConditionInterval(); } // namespace advss