mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-06 16:46:11 -05:00
Refactor, fixes and maximized option for title tab (#40)
* move definitions of switcher structs to separate files * remove useless comment * cleanup and silence warnings * add generic switch * removed delay on main thread startup as it served no purpose * clean up ultility.hpp * do not save switchStr to file as it could cause issues when scenes are renamed * rename sceneRoundTrip to sceneSequence * add option to switch if window is maximized to title tab
This commit is contained in:
@@ -1,362 +1,27 @@
|
||||
#pragma once
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <regex>
|
||||
#include <mutex>
|
||||
#include <fstream>
|
||||
#include <QDateTime>
|
||||
#include <QThread>
|
||||
#include <curl/curl.h>
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "switch-audio.hpp"
|
||||
#include "switch-executable.hpp"
|
||||
#include "switch-file.hpp"
|
||||
#include "switch-idle.hpp"
|
||||
#include "switch-media.hpp"
|
||||
#include "switch-random.hpp"
|
||||
#include "switch-screen-region.hpp"
|
||||
#include "switch-time.hpp"
|
||||
#include "switch-transitions.hpp"
|
||||
#include "switch-window.hpp"
|
||||
#include "swtich-sequence.hpp"
|
||||
|
||||
constexpr auto default_interval = 300;
|
||||
|
||||
constexpr auto default_idle_time = 60;
|
||||
|
||||
constexpr auto previous_scene_name = "Previous Scene";
|
||||
|
||||
constexpr auto read_file_func = 0;
|
||||
constexpr auto round_trip_func = 1;
|
||||
constexpr auto idle_func = 2;
|
||||
constexpr auto exe_func = 3;
|
||||
constexpr auto screen_region_func = 4;
|
||||
constexpr auto window_title_func = 5;
|
||||
constexpr auto media_func = 6;
|
||||
constexpr auto time_func = 7;
|
||||
constexpr auto audio_func = 8;
|
||||
|
||||
constexpr auto default_priority_0 = read_file_func;
|
||||
constexpr auto default_priority_1 = round_trip_func;
|
||||
constexpr auto default_priority_2 = idle_func;
|
||||
constexpr auto default_priority_3 = exe_func;
|
||||
constexpr auto default_priority_4 = screen_region_func;
|
||||
constexpr auto default_priority_5 = window_title_func;
|
||||
constexpr auto default_priority_6 = media_func;
|
||||
constexpr auto default_priority_7 = time_func;
|
||||
constexpr auto default_priority_8 = audio_func;
|
||||
|
||||
/********************************************************************************
|
||||
* Data structs for each scene switching method
|
||||
********************************************************************************/
|
||||
struct WindowSceneSwitch {
|
||||
OBSWeakSource scene;
|
||||
std::string window;
|
||||
OBSWeakSource transition;
|
||||
bool fullscreen;
|
||||
bool focus;
|
||||
|
||||
inline WindowSceneSwitch(OBSWeakSource scene_, const char *window_,
|
||||
OBSWeakSource transition_, bool fullscreen_,
|
||||
bool focus_)
|
||||
: scene(scene_),
|
||||
window(window_),
|
||||
transition(transition_),
|
||||
fullscreen(fullscreen_),
|
||||
focus(focus_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
std::string regionStr;
|
||||
|
||||
inline ScreenRegionSwitch(OBSWeakSource scene_,
|
||||
OBSWeakSource transition_, int minX_,
|
||||
int minY_, int maxX_, int maxY_,
|
||||
std::string regionStr_)
|
||||
: scene(scene_),
|
||||
transition(transition_),
|
||||
minX(minX_),
|
||||
minY(minY_),
|
||||
maxX(maxX_),
|
||||
maxY(maxY_),
|
||||
regionStr(regionStr_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct SceneRoundTripSwitch {
|
||||
OBSWeakSource scene1;
|
||||
OBSWeakSource scene2;
|
||||
OBSWeakSource transition;
|
||||
double delay;
|
||||
bool usePreviousScene;
|
||||
std::string sceneRoundTripStr;
|
||||
|
||||
inline SceneRoundTripSwitch(OBSWeakSource scene1_,
|
||||
OBSWeakSource scene2_,
|
||||
OBSWeakSource transition_, double delay_,
|
||||
bool usePreviousScene_, std::string str)
|
||||
: scene1(scene1_),
|
||||
scene2(scene2_),
|
||||
transition(transition_),
|
||||
delay(delay_),
|
||||
usePreviousScene(usePreviousScene_),
|
||||
sceneRoundTripStr(str)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct RandomSwitch {
|
||||
OBSWeakSource scene;
|
||||
OBSWeakSource transition;
|
||||
double delay;
|
||||
std::string randomSwitchStr;
|
||||
|
||||
inline RandomSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
|
||||
double delay_, std::string str)
|
||||
: scene(scene_),
|
||||
transition(transition_),
|
||||
delay(delay_),
|
||||
randomSwitchStr(str)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct SceneTransition {
|
||||
OBSWeakSource scene1;
|
||||
OBSWeakSource scene2;
|
||||
OBSWeakSource transition;
|
||||
std::string sceneTransitionStr;
|
||||
|
||||
inline SceneTransition(OBSWeakSource scene1_, OBSWeakSource scene2_,
|
||||
OBSWeakSource transition_,
|
||||
std::string sceneTransitionStr_)
|
||||
: scene1(scene1_),
|
||||
scene2(scene2_),
|
||||
transition(transition_),
|
||||
sceneTransitionStr(sceneTransitionStr_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct DefaultSceneTransition {
|
||||
OBSWeakSource scene;
|
||||
OBSWeakSource transition;
|
||||
std::string sceneTransitionStr;
|
||||
|
||||
inline DefaultSceneTransition(OBSWeakSource scene_,
|
||||
OBSWeakSource transition_,
|
||||
std::string sceneTransitionStr_)
|
||||
: scene(scene_),
|
||||
transition(transition_),
|
||||
sceneTransitionStr(sceneTransitionStr_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct FileSwitch {
|
||||
OBSWeakSource scene;
|
||||
OBSWeakSource transition;
|
||||
std::string file;
|
||||
std::string text;
|
||||
bool remote = false;
|
||||
bool useRegex = false;
|
||||
bool useTime = false;
|
||||
QDateTime lastMod;
|
||||
|
||||
inline FileSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
|
||||
const char *file_, const char *text_, bool remote_,
|
||||
bool useRegex_, bool useTime_)
|
||||
: scene(scene_),
|
||||
transition(transition_),
|
||||
file(file_),
|
||||
text(text_),
|
||||
remote(remote_),
|
||||
useRegex(useRegex_),
|
||||
useTime(useTime_),
|
||||
lastMod()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct FileIOData {
|
||||
bool readEnabled = false;
|
||||
std::string readPath;
|
||||
bool writeEnabled = false;
|
||||
std::string writePath;
|
||||
};
|
||||
|
||||
struct IdleData {
|
||||
bool idleEnable = false;
|
||||
int time = default_idle_time;
|
||||
OBSWeakSource scene;
|
||||
OBSWeakSource transition;
|
||||
bool usePreviousScene;
|
||||
bool alreadySwitched = false;
|
||||
};
|
||||
|
||||
struct MediaSwitch {
|
||||
OBSWeakSource scene;
|
||||
OBSWeakSource source;
|
||||
OBSWeakSource transition;
|
||||
obs_media_state state;
|
||||
int64_t time;
|
||||
time_restriction restriction;
|
||||
bool matched;
|
||||
bool usePreviousScene;
|
||||
std::string mediaSwitchStr;
|
||||
|
||||
inline MediaSwitch(OBSWeakSource scene_, OBSWeakSource source_,
|
||||
OBSWeakSource transition_, obs_media_state state_,
|
||||
time_restriction restriction_, uint64_t time_,
|
||||
bool usePreviousScene_, std::string mediaSwitchStr_)
|
||||
: scene(scene_),
|
||||
source(source_),
|
||||
transition(transition_),
|
||||
state(state_),
|
||||
restriction(restriction_),
|
||||
time(time_),
|
||||
usePreviousScene(usePreviousScene_),
|
||||
mediaSwitchStr(mediaSwitchStr_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TimeSwitch {
|
||||
OBSWeakSource scene;
|
||||
OBSWeakSource transition;
|
||||
timeTrigger trigger;
|
||||
QTime time;
|
||||
bool usePreviousScene;
|
||||
std::string timeSwitchStr;
|
||||
|
||||
inline TimeSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
|
||||
timeTrigger trigger_, QTime time_,
|
||||
bool usePreviousScene_, std::string timeSwitchStr_)
|
||||
: scene(scene_),
|
||||
transition(transition_),
|
||||
trigger(trigger_),
|
||||
time(time_),
|
||||
usePreviousScene(usePreviousScene_),
|
||||
timeSwitchStr(timeSwitchStr_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct AudioSwitch {
|
||||
OBSWeakSource scene;
|
||||
OBSWeakSource audioSource;
|
||||
OBSWeakSource transition;
|
||||
int volumeThreshold;
|
||||
float peak;
|
||||
bool usePreviousScene;
|
||||
obs_volmeter_t *volmeter;
|
||||
std::string audioSwitchStr;
|
||||
|
||||
static void setVolumeLevel(void *data,
|
||||
const float magnitude[MAX_AUDIO_CHANNELS],
|
||||
const float peak[MAX_AUDIO_CHANNELS],
|
||||
const float inputPeak[MAX_AUDIO_CHANNELS])
|
||||
{
|
||||
UNUSED_PARAMETER(magnitude);
|
||||
UNUSED_PARAMETER(inputPeak);
|
||||
AudioSwitch *s = static_cast<AudioSwitch *>(data);
|
||||
|
||||
s->peak = peak[0];
|
||||
for (int i = 1; i < MAX_AUDIO_CHANNELS; i++)
|
||||
if (peak[i] > s->peak)
|
||||
s->peak = peak[i];
|
||||
}
|
||||
|
||||
inline AudioSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
|
||||
OBSWeakSource audioSource_, int volumeThreshold_,
|
||||
bool usePreviousScene_, std::string audioSwitchStr_)
|
||||
: scene(scene_),
|
||||
transition(transition_),
|
||||
audioSource(audioSource_),
|
||||
volumeThreshold(volumeThreshold_),
|
||||
usePreviousScene(usePreviousScene_),
|
||||
audioSwitchStr(audioSwitchStr_)
|
||||
{
|
||||
volmeter = obs_volmeter_create(OBS_FADER_LOG);
|
||||
obs_volmeter_add_callback(volmeter, setVolumeLevel, this);
|
||||
obs_source_t *as = obs_weak_source_get_source(audioSource);
|
||||
if (!obs_volmeter_attach_source(volmeter, as)) {
|
||||
const char *name = obs_source_get_name(as);
|
||||
blog(LOG_WARNING,
|
||||
"failed to attach volmeter to source %s", name);
|
||||
}
|
||||
obs_source_release(as);
|
||||
}
|
||||
|
||||
AudioSwitch(const AudioSwitch &other)
|
||||
: scene(other.scene),
|
||||
transition(other.transition),
|
||||
audioSource(other.audioSource),
|
||||
volumeThreshold(other.volumeThreshold),
|
||||
usePreviousScene(other.usePreviousScene),
|
||||
audioSwitchStr(other.audioSwitchStr)
|
||||
{
|
||||
volmeter = obs_volmeter_create(OBS_FADER_LOG);
|
||||
obs_volmeter_add_callback(volmeter, setVolumeLevel, this);
|
||||
obs_source_t *as =
|
||||
obs_weak_source_get_source(other.audioSource);
|
||||
if (!obs_volmeter_attach_source(volmeter, as)) {
|
||||
const char *name = obs_source_get_name(as);
|
||||
blog(LOG_WARNING,
|
||||
"failed to attach volmeter to source %s", name);
|
||||
}
|
||||
obs_source_release(as);
|
||||
}
|
||||
|
||||
AudioSwitch(AudioSwitch &&other)
|
||||
: scene(other.scene),
|
||||
transition(other.transition),
|
||||
audioSource(other.audioSource),
|
||||
volumeThreshold(other.volumeThreshold),
|
||||
usePreviousScene(other.usePreviousScene),
|
||||
audioSwitchStr(other.audioSwitchStr),
|
||||
volmeter(other.volmeter)
|
||||
{
|
||||
other.volmeter = nullptr;
|
||||
}
|
||||
|
||||
inline ~AudioSwitch()
|
||||
{
|
||||
obs_volmeter_remove_callback(volmeter, setVolumeLevel, this);
|
||||
obs_volmeter_destroy(volmeter);
|
||||
}
|
||||
|
||||
AudioSwitch &operator=(const AudioSwitch &other)
|
||||
{
|
||||
return *this = AudioSwitch(other);
|
||||
}
|
||||
|
||||
AudioSwitch &operator=(AudioSwitch &&other) noexcept
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
obs_volmeter_destroy(volmeter);
|
||||
volmeter = other.volmeter;
|
||||
other.volmeter = nullptr;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch;
|
||||
typedef enum { PERSIST = 0, START = 1, STOP = 2 } StartupBehavior;
|
||||
typedef enum {
|
||||
@@ -384,7 +49,7 @@ struct SwitcherData {
|
||||
|
||||
int interval = default_interval;
|
||||
|
||||
obs_source_t *waitScene = NULL; //scene during which wait started
|
||||
obs_source_t *waitScene = NULL;
|
||||
OBSWeakSource previousScene = NULL;
|
||||
OBSWeakSource PreviousScene2 = NULL;
|
||||
OBSWeakSource lastRandomScene;
|
||||
@@ -404,8 +69,8 @@ struct SwitcherData {
|
||||
|
||||
std::vector<std::string> ignoreWindowsSwitches;
|
||||
|
||||
std::vector<SceneRoundTripSwitch> sceneRoundTripSwitches;
|
||||
int sceneRoundTripUnitMultiplier = 1;
|
||||
std::vector<SceneSequenceSwitch> sceneSequenceSwitches;
|
||||
int sceneSequenceMultiplier = 1;
|
||||
|
||||
std::vector<RandomSwitch> randomSwitches;
|
||||
|
||||
@@ -479,7 +144,7 @@ struct SwitcherData {
|
||||
void autoStopStreamAndRecording();
|
||||
void autoStartStreamRecording();
|
||||
bool checkPause();
|
||||
void checkSceneRoundTrip(bool &match, OBSWeakSource &scene,
|
||||
void checkSceneSequence(bool &match, OBSWeakSource &scene,
|
||||
OBSWeakSource &transition,
|
||||
std::unique_lock<std::mutex> &lock);
|
||||
void checkIdleSwitch(bool &match, OBSWeakSource &scene,
|
||||
@@ -506,7 +171,7 @@ struct SwitcherData {
|
||||
void saveWindowTitleSwitches(obs_data_t *obj);
|
||||
void saveScreenRegionSwitches(obs_data_t *obj);
|
||||
void savePauseSwitches(obs_data_t *obj);
|
||||
void saveSceneRoundTripSwitches(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);
|
||||
@@ -520,7 +185,7 @@ struct SwitcherData {
|
||||
void loadWindowTitleSwitches(obs_data_t *obj);
|
||||
void loadScreenRegionSwitches(obs_data_t *obj);
|
||||
void loadPauseSwitches(obs_data_t *obj);
|
||||
void loadSceneRoundTripSwitches(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);
|
||||
@@ -531,124 +196,7 @@ struct SwitcherData {
|
||||
void loadAudioSwitches(obs_data_t *obj);
|
||||
void loadGeneralSettings(obs_data_t *obj);
|
||||
|
||||
void Prune()
|
||||
{
|
||||
for (size_t i = 0; i < windowSwitches.size(); i++) {
|
||||
WindowSceneSwitch &s = windowSwitches[i];
|
||||
if (!WeakSourceValid(s.scene) ||
|
||||
!WeakSourceValid(s.transition))
|
||||
windowSwitches.erase(windowSwitches.begin() +
|
||||
i--);
|
||||
}
|
||||
|
||||
if (nonMatchingScene && !WeakSourceValid(nonMatchingScene)) {
|
||||
switchIfNotMatching = NO_SWITCH;
|
||||
nonMatchingScene = nullptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < randomSwitches.size(); i++) {
|
||||
RandomSwitch &s = randomSwitches[i];
|
||||
if (!WeakSourceValid(s.scene) ||
|
||||
!WeakSourceValid(s.transition))
|
||||
randomSwitches.erase(randomSwitches.begin() +
|
||||
i--);
|
||||
}
|
||||
|
||||
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) ||
|
||||
(!s.usePreviousScene &&
|
||||
!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--);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < fileSwitches.size(); i++) {
|
||||
FileSwitch &s = fileSwitches[i];
|
||||
if (!WeakSourceValid(s.scene) ||
|
||||
!WeakSourceValid(s.transition))
|
||||
fileSwitches.erase(fileSwitches.begin() + i--);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < timeSwitches.size(); i++) {
|
||||
TimeSwitch &s = timeSwitches[i];
|
||||
if ((!s.usePreviousScene &&
|
||||
!WeakSourceValid(s.scene)) ||
|
||||
!WeakSourceValid(s.transition))
|
||||
timeSwitches.erase(timeSwitches.begin() + i--);
|
||||
}
|
||||
|
||||
if (!idleData.usePreviousScene &&
|
||||
!WeakSourceValid(idleData.scene) ||
|
||||
!WeakSourceValid(idleData.transition)) {
|
||||
idleData.idleEnable = false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mediaSwitches.size(); i++) {
|
||||
MediaSwitch &s = mediaSwitches[i];
|
||||
if ((!s.usePreviousScene &&
|
||||
!WeakSourceValid(s.scene)) ||
|
||||
!WeakSourceValid(s.source) ||
|
||||
!WeakSourceValid(s.transition))
|
||||
mediaSwitches.erase(mediaSwitches.begin() +
|
||||
i--);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < audioSwitches.size(); i++) {
|
||||
AudioSwitch &s = audioSwitches[i];
|
||||
if ((!s.usePreviousScene &&
|
||||
!WeakSourceValid(s.scene)) ||
|
||||
!WeakSourceValid(s.transition))
|
||||
audioSwitches.erase(audioSwitches.begin() +
|
||||
i--);
|
||||
}
|
||||
}
|
||||
void Prune();
|
||||
inline ~SwitcherData() { Stop(); }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user