#pragma once #include "scene-group.hpp" #include "scene-trigger.hpp" #include "switch-audio.hpp" #include "switch-executable.hpp" #include "switch-file.hpp" #include "switch-idle.hpp" #include "switch-media.hpp" #include "switch-pause.hpp" #include "switch-random.hpp" #include "switch-screen-region.hpp" #include "switch-time.hpp" #include "switch-transitions.hpp" #include "switch-window.hpp" #include "switch-sequence.hpp" #include "switch-video.hpp" #include "switch-network.hpp" #include "macro-properties.hpp" #include "duration-control.hpp" #include "connection-manager.hpp" #include "curl-helper.hpp" #include "priority-helper.hpp" #include "log-helper.hpp" #include #include #include #include #include #include #include #include namespace advss { constexpr auto default_interval = 300; constexpr auto tab_count = 18; typedef const char *(*translateFunc)(const char *); class Item; class Macro; class SwitcherThread; class SwitcherData; extern SwitcherData *switcher; SwitcherData *GetSwitcher(); std::mutex *GetSwitcherMutex(); bool VerboseLoggingEnabled(); class SwitcherData { public: void Thread(); void Start(); void Stop(); std::unique_lock *GetLock() { return mainLoopLock; } const char *Translate(const char *); obs_module_t *GetModule(); void SetWaitScene(); bool SceneChangedDuringWait(); bool AnySceneTransitionStarted(); void SetPreconditions(); void ResetForNextInterval(); void AddResetForNextIntervalFunction(std::function); bool CheckForMatch(OBSWeakSource &scene, OBSWeakSource &transition, int &linger, bool &setPreviousSceneAsMatch, bool ¯oMatch); bool CheckMacros(); bool RunMacros(); void CheckNoMatchSwitch(bool &match, OBSWeakSource &scene, OBSWeakSource &transition, int &sleep); /* --- Start of saving / loading section --- */ void SaveSettings(obs_data_t *obj); void SaveMacros(obs_data_t *obj); void SaveConnections(obs_data_t *obj); void SaveVariables(obs_data_t *obj); void SaveGeneralSettings(obs_data_t *obj); void SaveHotkeys(obs_data_t *obj); void SaveUISettings(obs_data_t *obj); void SaveVersion(obs_data_t *obj, const std::string ¤tVersion); void LoadSettings(obs_data_t *obj); void LoadMacros(obs_data_t *obj); void LoadConnections(obs_data_t *obj); void LoadVariables(obs_data_t *obj); void LoadGeneralSettings(obs_data_t *obj); void LoadHotkeys(obs_data_t *obj); void LoadUISettings(obs_data_t *obj); bool VersionChanged(obs_data_t *obj, std::string currentVersion); bool TabOrderValid(); void ResetTabOrder(); bool PrioFuncsValid(); /* --- End of saving / loading section --- */ SwitcherData(obs_module_t *m, translateFunc t); inline ~SwitcherData() { Stop(); } public: SwitcherThread *th = nullptr; std::mutex m; std::unique_lock *mainLoopLock = nullptr; bool stop = false; std::condition_variable cv; std::condition_variable macroWaitCv; std::atomic_bool abortMacroWait = {false}; std::condition_variable macroTransitionCv; std::vector> resetForNextIntervalFuncs; bool firstBoot = true; bool transitionActive = false; bool sceneColletionStop = false; bool replayBufferSaved = false; bool obsIsShuttingDown = false; bool firstInterval = true; bool firstIntervalAfterStop = true; int shutdownConditionCount = 0; bool startupLoadDone = false; obs_source_t *waitScene = nullptr; OBSWeakSource currentScene = nullptr; OBSWeakSource previousScene = nullptr; std::chrono::high_resolution_clock::time_point lastSceneChangeTime{}; std::chrono::high_resolution_clock::time_point lastTransitionEndTime{}; std::chrono::high_resolution_clock::time_point lastStreamStartingTime{}; std::chrono::high_resolution_clock::time_point lastStreamStoppingTime{}; std::chrono::high_resolution_clock::time_point lastMatchTime; /* --- Start of General tab section --- */ int interval = default_interval; OBSWeakSource nonMatchingScene; enum class NoMatch { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 }; NoMatch switchIfNotMatching = NoMatch::NO_SWITCH; Duration noMatchDelay; enum class StartupBehavior { PERSIST = 0, START = 1, STOP = 2 }; StartupBehavior startupBehavior = StartupBehavior::PERSIST; enum class AutoStart { NEVER, RECORDING, STREAMING, RECORINDG_OR_STREAMING }; AutoStart autoStartEvent = AutoStart::NEVER; Duration cooldown; bool showSystemTrayNotifications = false; bool transitionOverrideOverride = false; bool adjustActiveTransitionType = true; bool verbose = false; /* --- End of General tab section --- */ struct AudioFadeInfo { std::atomic_bool active = {false}; std::atomic_int id = {0}; }; AudioFadeInfo masterAudioFade; std::unordered_map activeAudioFades; MacroProperties macroProperties; std::deque> macros; bool macroSceneSwitched = false; Curlhelper curl; std::deque> connections; std::vector websocketMessages; std::deque> variables; std::string lastTitle; std::string currentTitle; std::string currentForegroundProcess; std::pair lastCursorPos = {0, 0}; bool cursorPosChanged = false; std::vector functionNamesByPriority = GetDefaultFunctionPriorityList(); const std::vector threadPriorities = GetThreadPrioMapping(); uint32_t threadPriority = QThread::NormalPriority; /* --- Start of hotkey section --- */ bool hotkeysRegistered = false; obs_hotkey_id startHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id stopHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id toggleHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id upMacroSegment = OBS_INVALID_HOTKEY_ID; obs_hotkey_id downMacroSegment = OBS_INVALID_HOTKEY_ID; obs_hotkey_id removeMacroSegment = OBS_INVALID_HOTKEY_ID; /* --- End of hotkey section --- */ /* --- Start of UI section --- */ bool settingsWindowOpened = false; int lastOpenedTab = -1; std::string lastImportPath; QStringList loadFailureLibs; bool warnPluginLoadFailure = true; bool disableHints = false; bool hideLegacyTabs = true; std::vector tabOrder = std::vector(tab_count); bool saveWindowGeo = false; QPoint windowPos = {}; QSize windowSize = {}; QList macroActionConditionSplitterPosition; QList macroListMacroEditSplitterPosition; /* --- End of UI section --- */ /* --- Start of legacy tab section --- */ void saveWindowTitleSwitches(obs_data_t *obj); void saveScreenRegionSwitches(obs_data_t *obj); void savePauseSwitches(obs_data_t *obj); void saveSceneSequenceSwitches(obs_data_t *obj); void saveSceneTransitions(obs_data_t *obj); void saveIdleSwitches(obs_data_t *obj); void saveExecutableSwitches(obs_data_t *obj); void saveRandomSwitches(obs_data_t *obj); void saveFileSwitches(obs_data_t *obj); void saveMediaSwitches(obs_data_t *obj); void saveTimeSwitches(obs_data_t *obj); void saveAudioSwitches(obs_data_t *obj); void saveSceneGroups(obs_data_t *obj); void saveSceneTriggers(obs_data_t *obj); void saveVideoSwitches(obs_data_t *obj); void saveNetworkSwitches(obs_data_t *obj); void loadWindowTitleSwitches(obs_data_t *obj); void loadScreenRegionSwitches(obs_data_t *obj); void loadPauseSwitches(obs_data_t *obj); void loadSceneSequenceSwitches(obs_data_t *obj); void loadSceneTransitions(obs_data_t *obj); void loadIdleSwitches(obs_data_t *obj); void loadExecutableSwitches(obs_data_t *obj); void loadRandomSwitches(obs_data_t *obj); void loadFileSwitches(obs_data_t *obj); void loadMediaSwitches(obs_data_t *obj); void loadTimeSwitches(obs_data_t *obj); void loadAudioSwitches(obs_data_t *obj); void loadSceneGroups(obs_data_t *obj); void loadSceneTriggers(obs_data_t *obj); void loadVideoSwitches(obs_data_t *obj); void loadNetworkSettings(obs_data_t *obj); void Prune(); bool checkSceneSequence(OBSWeakSource &scene, OBSWeakSource &transition, int &linger, bool &setPrevSceneAfterLinger); bool checkIdleSwitch(OBSWeakSource &scene, OBSWeakSource &transition); bool checkWindowTitleSwitch(OBSWeakSource &scene, OBSWeakSource &transition); bool checkExeSwitch(OBSWeakSource &scene, OBSWeakSource &transition); bool checkScreenRegionSwitch(OBSWeakSource &scene, OBSWeakSource &transition); bool checkSwitchInfoFromFile(OBSWeakSource &scene, OBSWeakSource &transition); bool checkFileContent(OBSWeakSource &scene, OBSWeakSource &transition); bool checkRandom(OBSWeakSource &scene, OBSWeakSource &transition, int &delay); bool checkMediaSwitch(OBSWeakSource &scene, OBSWeakSource &transition); bool checkTimeSwitch(OBSWeakSource &scene, OBSWeakSource &transition); bool checkAudioSwitch(OBSWeakSource &scene, OBSWeakSource &transition); void checkAudioSwitchFallback(OBSWeakSource &scene, OBSWeakSource &transition); bool checkVideoSwitch(OBSWeakSource &scene, OBSWeakSource &transition); void checkTriggers(); bool checkPause(); void checkDefaultSceneTransitions(); void writeSceneInfoToFile(); void writeToStatusFile(const QString &msg); void checkSwitchCooldown(bool &match); std::deque windowSwitches; std::vector ignoreWindowsSwitches; IdleData idleData; std::vector ignoreIdleWindows; bool showFrame = false; std::deque screenRegionSwitches; bool uninterruptibleSceneSequenceActive = false; std::deque sceneSequenceSwitches; std::deque randomSwitches; OBSWeakSource lastRandomScene; FileIOData fileIO; std::deque fileSwitches; std::deque executableSwitches; std::deque sceneTriggers; std::deque sceneTransitions; std::deque defaultSceneTransitions; std::deque mediaSwitches; std::deque pauseEntries; std::deque timeSwitches; QDateTime liveTime; std::deque audioSwitches; AudioSwitchFallback audioFallback; WSServer server; ServerStatus serverStatus = ServerStatus::NOT_RUNNING; WSClient client; ClientStatus clientStatus = ClientStatus::DISCONNECTED; NetworkConfig networkConfig; std::deque videoSwitches; std::deque sceneGroups; SceneGroup *lastRandomSceneGroup = nullptr; /* --- End of legacy tab section --- */ private: obs_module_t *_modulePtr = nullptr; translateFunc _translate = nullptr; }; class SwitcherThread : public QThread { public: explicit SwitcherThread(){}; void run() { switcher->Thread(); }; }; } // namespace advss