mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-04-05 00:35:46 -05:00
The "manual" attempt at restoring the docks should only be performed on scene collection change as OBS will already take care of this on starutp. Do not delete the macro dock widgets on shutdown so OBS is able to save their location and size properly.
327 lines
10 KiB
C++
327 lines
10 KiB
C++
#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 <condition_variable>
|
|
#include <vector>
|
|
#include <deque>
|
|
#include <mutex>
|
|
#include <QDateTime>
|
|
#include <QThread>
|
|
#include <curl/curl.h>
|
|
#include <unordered_map>
|
|
|
|
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<std::mutex> *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<void()>);
|
|
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<std::mutex> *mainLoopLock = nullptr;
|
|
bool stop = false;
|
|
std::condition_variable cv;
|
|
std::condition_variable macroWaitCv;
|
|
std::atomic_bool abortMacroWait = {false};
|
|
std::condition_variable macroTransitionCv;
|
|
|
|
std::vector<std::function<void()>> 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<std::string, AudioFadeInfo> activeAudioFades;
|
|
|
|
MacroProperties macroProperties;
|
|
std::deque<std::shared_ptr<Macro>> macros;
|
|
bool macroSceneSwitched = false;
|
|
|
|
Curlhelper curl;
|
|
std::deque<std::shared_ptr<Item>> connections;
|
|
std::vector<std::string> websocketMessages;
|
|
std::deque<std::shared_ptr<Item>> variables;
|
|
|
|
std::string lastTitle;
|
|
std::string currentTitle;
|
|
std::string currentForegroundProcess;
|
|
std::pair<int, int> lastCursorPos = {0, 0};
|
|
bool cursorPosChanged = false;
|
|
|
|
std::vector<int> functionNamesByPriority =
|
|
GetDefaultFunctionPriorityList();
|
|
const std::vector<ThreadPrio> 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<int> tabOrder = std::vector<int>(tab_count);
|
|
bool saveWindowGeo = false;
|
|
QPoint windowPos = {};
|
|
QSize windowSize = {};
|
|
QList<int> macroActionConditionSplitterPosition;
|
|
QList<int> 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<WindowSwitch> windowSwitches;
|
|
std::vector<std::string> ignoreWindowsSwitches;
|
|
IdleData idleData;
|
|
std::vector<std::string> ignoreIdleWindows;
|
|
bool showFrame = false;
|
|
std::deque<ScreenRegionSwitch> screenRegionSwitches;
|
|
bool uninterruptibleSceneSequenceActive = false;
|
|
std::deque<SceneSequenceSwitch> sceneSequenceSwitches;
|
|
std::deque<RandomSwitch> randomSwitches;
|
|
OBSWeakSource lastRandomScene;
|
|
FileIOData fileIO;
|
|
std::deque<FileSwitch> fileSwitches;
|
|
std::deque<ExecutableSwitch> executableSwitches;
|
|
std::deque<SceneTrigger> sceneTriggers;
|
|
std::deque<SceneTransition> sceneTransitions;
|
|
std::deque<DefaultSceneTransition> defaultSceneTransitions;
|
|
std::deque<MediaSwitch> mediaSwitches;
|
|
std::deque<PauseEntry> pauseEntries;
|
|
std::deque<TimeSwitch> timeSwitches;
|
|
QDateTime liveTime;
|
|
std::deque<AudioSwitch> audioSwitches;
|
|
AudioSwitchFallback audioFallback;
|
|
WSServer server;
|
|
ServerStatus serverStatus = ServerStatus::NOT_RUNNING;
|
|
WSClient client;
|
|
ClientStatus clientStatus = ClientStatus::DISCONNECTED;
|
|
NetworkConfig networkConfig;
|
|
std::deque<VideoSwitch> videoSwitches;
|
|
std::deque<SceneGroup> 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
|