#pragma once #include #include #include #include #include #include #include #include #include "utility.hpp" #define DEFAULT_INTERVAL 300 #define READ_FILE_FUNC "File based" #define ROUND_TRIP_FUNC "Scene Sequence" #define IDLE_FUNC "Idle detection" #define EXE_FUNC "Executable" #define SCREEN_REGION_FUNC "Screen region" #define WINDOW_TITLE_FUNC "Window title" #define DEFAULT_PRIORITY_0 READ_FILE_FUNC #define DEFAULT_PRIORITY_1 ROUND_TRIP_FUNC #define DEFAULT_PRIORITY_2 IDLE_FUNC #define DEFAULT_PRIORITY_3 EXE_FUNC #define DEFAULT_PRIORITY_4 SCREEN_REGION_FUNC #define DEFAULT_PRIORITY_5 WINDOW_TITLE_FUNC using namespace std; struct SceneSwitch { OBSWeakSource scene; string window; OBSWeakSource transition; bool fullscreen; inline SceneSwitch( OBSWeakSource scene_, const char* window_, OBSWeakSource transition_, bool fullscreen_) : scene(scene_) , window(window_) , transition(transition_) , fullscreen(fullscreen_) { } }; struct ExecutableSceneSwitch { OBSWeakSource mScene; OBSWeakSource mTransition; QString mExe; bool mInFocus; inline ExecutableSceneSwitch( OBSWeakSource scene, OBSWeakSource transition, const QString& exe, bool inFocus) : mScene(scene) , mTransition(transition) , mExe(exe) , mInFocus(inFocus) { } }; struct ScreenRegionSwitch { OBSWeakSource scene; OBSWeakSource transition; int minX, minY, maxX, maxY; string regionStr; inline ScreenRegionSwitch(OBSWeakSource scene_, OBSWeakSource transition_, int minX_, int minY_, int maxX_, int maxY_, string regionStr_) : scene(scene_) , transition(transition_) , minX(minX_) , minY(minY_) , maxX(maxX_) , maxY(maxY_) , regionStr(regionStr_) { } }; struct SceneRoundTripSwitch { OBSWeakSource scene1; OBSWeakSource scene2; OBSWeakSource transition; int delay; string sceneRoundTripStr; inline SceneRoundTripSwitch(OBSWeakSource scene1_, OBSWeakSource scene2_, OBSWeakSource transition_, int delay_, string str) : scene1(scene1_) , scene2(scene2_) , transition(transition_) , delay(delay_) , sceneRoundTripStr(str) { } }; struct SceneTransition { OBSWeakSource scene1; OBSWeakSource scene2; OBSWeakSource transition; string sceneTransitionStr; inline SceneTransition(OBSWeakSource scene1_, OBSWeakSource scene2_, OBSWeakSource transition_, string sceneTransitionStr_) : scene1(scene1_) , scene2(scene2_) , transition(transition_) , sceneTransitionStr(sceneTransitionStr_) { } }; struct DefaultSceneTransition { OBSWeakSource scene; OBSWeakSource transition; string sceneTransitionStr; inline DefaultSceneTransition(OBSWeakSource scene_, OBSWeakSource transition_, string sceneTransitionStr_) : scene(scene_) , transition(transition_) , sceneTransitionStr(sceneTransitionStr_) { } }; struct FileIOData { bool readEnabled; string readPath; bool writeEnabled; string writePath; }; struct IdleData { bool idleEnable; int time; OBSWeakSource scene; OBSWeakSource transition; }; struct SwitcherData { thread th; condition_variable cv; mutex m; mutex transitionMutex; bool transitionActive = false; bool waitForTransition = false; condition_variable transitionCv; bool stop = false; vector switches; string lastTitle; OBSWeakSource nonMatchingScene; int interval = DEFAULT_INTERVAL; bool switchIfNotMatching = false; bool startAtLaunch = false; vector screenRegionSwitches; vector pauseScenesSwitches; vector pauseWindowsSwitches; vector ignoreWindowsSwitches; vector sceneRoundTripSwitches; bool autoStopEnable = false; OBSWeakSource autoStopScene; string waitSceneName; //indicates which scene was active when we startet waiting on something vector sceneTransitions; vector defaultSceneTransitions; vector executableSwitches; FileIOData fileIO; IdleData idleData; vector ignoreIdleWindows; vector functionNamesByPriority = vector{ string(DEFAULT_PRIORITY_0), string(DEFAULT_PRIORITY_1), string(DEFAULT_PRIORITY_2), string(DEFAULT_PRIORITY_3), string(DEFAULT_PRIORITY_4), string(DEFAULT_PRIORITY_5), }; void Thread(); void Start(); void Stop(); bool sceneChangedDuringWait(); bool prioFuncsValid(); void writeSceneInfoToFile(); void setDefaultSceneTransitions(unique_lock& lock); void autoStopStreamAndRecording(); bool checkPause(); void checkSceneRoundTrip(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, unique_lock& lock); void checkIdleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition); void checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition); void checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition); void checkScreenRegionSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition); void checkSwitchInfoFromFile(bool& match, OBSWeakSource& scene, OBSWeakSource& transition); void Prune() { for (size_t i = 0; i < switches.size(); i++) { SceneSwitch& s = switches[i]; if (!WeakSourceValid(s.scene) || !WeakSourceValid(s.transition)) switches.erase(switches.begin() + i--); } if (nonMatchingScene && !WeakSourceValid(nonMatchingScene)) { switchIfNotMatching = false; nonMatchingScene = nullptr; } for (size_t i = 0; i < screenRegionSwitches.size(); i++) { ScreenRegionSwitch& s = screenRegionSwitches[i]; if (!WeakSourceValid(s.scene) || !WeakSourceValid(s.transition)) screenRegionSwitches.erase(screenRegionSwitches.begin() + i--); } for (size_t i = 0; i < pauseScenesSwitches.size(); i++) { OBSWeakSource& scene = pauseScenesSwitches[i]; if (!WeakSourceValid(scene)) pauseScenesSwitches.erase(pauseScenesSwitches.begin() + i--); } for (size_t i = 0; i < sceneRoundTripSwitches.size(); i++) { SceneRoundTripSwitch& s = sceneRoundTripSwitches[i]; if (!WeakSourceValid(s.scene1) || !WeakSourceValid(s.scene2) || !WeakSourceValid(s.transition)) sceneRoundTripSwitches.erase(sceneRoundTripSwitches.begin() + i--); } if (!WeakSourceValid(autoStopScene)) { autoStopScene = nullptr; autoStopEnable = false; } for (size_t i = 0; i < sceneTransitions.size(); i++) { SceneTransition& s = sceneTransitions[i]; if (!WeakSourceValid(s.scene1) || !WeakSourceValid(s.scene2) || !WeakSourceValid(s.transition)) sceneTransitions.erase(sceneTransitions.begin() + i--); } for (size_t i = 0; i < defaultSceneTransitions.size(); i++) { DefaultSceneTransition& s = defaultSceneTransitions[i]; if (!WeakSourceValid(s.scene) || !WeakSourceValid(s.transition)) defaultSceneTransitions.erase(defaultSceneTransitions.begin() + i--); } for (size_t i = 0; i < executableSwitches.size(); i++) { ExecutableSceneSwitch& s = executableSwitches[i]; if (!WeakSourceValid(s.mScene) || !WeakSourceValid(s.mTransition)) executableSwitches.erase(executableSwitches.begin() + i--); } if (!WeakSourceValid(idleData.scene) || !WeakSourceValid(idleData.transition)) { idleData.idleEnable = false; } } inline ~SwitcherData() { Stop(); } };