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:
WarmUpTill
2020-09-25 21:42:58 +02:00
committed by GitHub
parent 1559d437ec
commit dd63ff846c
40 changed files with 1266 additions and 981 deletions

View File

@@ -36,26 +36,40 @@ if(BUILD_OUT_OF_TREE)
src/headers/switcher-data-structs.hpp
src/headers/utility.hpp
src/headers/curl-helper.hpp
src/headers/switch-audio.hpp
src/headers/switch-executable.hpp
src/headers/switch-file.hpp
src/headers/switch-idle.hpp
src/headers/switch-media.hpp
src/headers/switch-random.hpp
src/headers/switch-screen-region.hpp
src/headers/switch-time.hpp
src/headers/switch-transitions.hpp
src/headers/switch-window.hpp
src/headers/swtich-sequence.hpp
src/headers/switch-generic.hpp
)
set(advanced-scene-switcher_SOURCES
${advanced-scene-switcher_SOURCES}
src/advanced-scene-switcher.cpp
src/advanced-scene-switcher-module.c
src/scene-transitions.cpp
src/screen-region-switch.cpp
src/priority.cpp
src/executable-switch.cpp
src/idle-switch.cpp
src/scene-round-trip.cpp
src/file-switch.cpp
src/window-title-switch.cpp
src/media-switch.cpp
src/switcher-data-structs.cpp
src/switch-transitions.cpp
src/switch-screen-region.cpp
src/switch-priority.cpp
src/switch-executable.cpp
src/switch-idle.cpp
src/switch-sequence.cpp
src/switch-file.cpp
src/switch-window.cpp
src/switch-media.cpp
src/hotkey.cpp
src/general.cpp
src/pause-switch.cpp
src/random.cpp
src/time-switch.cpp
src/switch-pause.cpp
src/switch-random.cpp
src/switch-time.cpp
src/switch-audio.cpp
src/curl-helper.cpp
)
@@ -170,27 +184,40 @@ else ()
src/headers/utility.hpp
src/headers/curl-helper.hpp
src/headers/volume-control.hpp
src/headers/switch-audio.hpp
src/headers/switch-executable.hpp
src/headers/switch-file.hpp
src/headers/switch-idle.hpp
src/headers/switch-media.hpp
src/headers/switch-random.hpp
src/headers/switch-screen-region.hpp
src/headers/switch-time.hpp
src/headers/switch-transitions.hpp
src/headers/switch-window.hpp
src/headers/swtich-sequence.hpp
src/headers/switch-generic.hpp
)
set(advanced-scene-switcher_SOURCES
${advanced-scene-switcher_SOURCES}
src/advanced-scene-switcher.cpp
src/advanced-scene-switcher-module.c
src/scene-transitions.cpp
src/screen-region-switch.cpp
src/priority.cpp
src/executable-switch.cpp
src/idle-switch.cpp
src/scene-round-trip.cpp
src/file-switch.cpp
src/window-title-switch.cpp
src/media-switch.cpp
src/switcher-data-structs.cpp
src/switch-transitions.cpp
src/switch-screen-region.cpp
src/switch-priority.cpp
src/switch-executable.cpp
src/switch-idle.cpp
src/switch-sequence.cpp
src/switch-file.cpp
src/switch-window.cpp
src/switch-media.cpp
src/hotkey.cpp
src/general.cpp
src/pause-switch.cpp
src/random.cpp
src/time-switch.cpp
src/audio-switch.cpp
src/switch-pause.cpp
src/switch-random.cpp
src/switch-time.cpp
src/switch-audio.cpp
src/curl-helper.cpp
src/volume-control.cpp
)

View File

@@ -1246,14 +1246,21 @@
<item>
<widget class="QCheckBox" name="fullscreenCheckBox">
<property name="text">
<string>only if fullscreen</string>
<string>if fullscreen</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="maximizedCheckBox">
<property name="text">
<string>if maximized</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="focusCheckBox">
<property name="text">
<string>only if focused</string>
<string>if focused</string>
</property>
</widget>
</item>
@@ -3359,7 +3366,7 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="sceneRoundTripTab">
<widget class="QWidget" name="sceneSequenceTab">
<attribute name="title">
<string notr="true">Sequence</string>
</attribute>
@@ -3374,7 +3381,7 @@
</widget>
</item>
<item>
<widget class="QComboBox" name="sceneRoundTripScenes1">
<widget class="QComboBox" name="sceneSequenceScenes1">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -3397,7 +3404,7 @@
</widget>
</item>
<item>
<widget class="QComboBox" name="sceneRoundTripScenes2">
<widget class="QComboBox" name="sceneSequenceScenes2">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -3420,7 +3427,7 @@
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="sceneRoundTripSpinBox">
<widget class="QDoubleSpinBox" name="sceneSequenceSpinBox">
<property name="suffix">
<string/>
</property>
@@ -3430,7 +3437,7 @@
</widget>
</item>
<item>
<widget class="QComboBox" name="sceneRoundTripDelayUnits"/>
<widget class="QComboBox" name="sceneSequenceDelayUnits"/>
</item>
<item>
<widget class="QLabel" name="label_17">
@@ -3440,7 +3447,7 @@
</widget>
</item>
<item>
<widget class="QComboBox" name="sceneRoundTripTransitions"/>
<widget class="QComboBox" name="sceneSequenceTransitions"/>
</item>
<item>
<spacer name="horizontalSpacer_9">
@@ -3465,7 +3472,7 @@
</widget>
</item>
<item>
<widget class="QListWidget" name="sceneRoundTrips">
<widget class="QListWidget" name="sceneSequences">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
@@ -3480,7 +3487,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QPushButton" name="sceneRoundTripAdd">
<widget class="QPushButton" name="sceneSequenceAdd">
<property name="maximumSize">
<size>
<width>22</width>
@@ -3496,7 +3503,7 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="sceneRoundTripRemove">
<widget class="QPushButton" name="sceneSequenceRemove">
<property name="maximumSize">
<size>
<width>22</width>
@@ -3551,7 +3558,7 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="sceneRoundTripUp">
<widget class="QPushButton" name="sceneSequenceUp">
<property name="maximumSize">
<size>
<width>22</width>
@@ -3574,7 +3581,7 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="sceneRoundTripDown">
<widget class="QPushButton" name="sceneSequenceDown">
<property name="maximumSize">
<size>
<width>22</width>
@@ -3627,14 +3634,14 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_28">
<item>
<widget class="QPushButton" name="sceneRoundTripSave">
<widget class="QPushButton" name="sceneSequenceSave">
<property name="text">
<string>Save Round Trips to file</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="sceneRoundTripLoad">
<widget class="QPushButton" name="sceneSequenceLoad">
<property name="text">
<string>Load Round Trips from file</string>
</property>

View File

@@ -112,7 +112,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
switcher->saveWindowTitleSwitches(obj);
switcher->saveScreenRegionSwitches(obj);
switcher->savePauseSwitches(obj);
switcher->saveSceneRoundTripSwitches(obj);
switcher->saveSceneSequenceSwitches(obj);
switcher->saveSceneTransitions(obj);
switcher->saveIdleSwitches(obj);
switcher->saveExecutableSwitches(obj);
@@ -138,7 +138,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
switcher->loadWindowTitleSwitches(obj);
switcher->loadScreenRegionSwitches(obj);
switcher->loadPauseSwitches(obj);
switcher->loadSceneRoundTripSwitches(obj);
switcher->loadSceneSequenceSwitches(obj);
switcher->loadSceneTransitions(obj);
switcher->loadIdleSwitches(obj);
switcher->loadExecutableSwitches(obj);
@@ -153,9 +153,11 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
switcher->m.unlock();
if (switcher->stop)
switcher->Stop();
else
// stop the scene switcher at least once
// to avoid issues with scene collection changes
bool start = !switcher->stop;
switcher->Stop();
if (start)
switcher->Start();
}
}
@@ -166,9 +168,6 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
void SwitcherData::Thread()
{
blog(LOG_INFO, "Advanced Scene Switcher started");
//to avoid scene duplication when rapidly switching scene collection
std::this_thread::sleep_for(std::chrono::seconds(2));
int sleep = 0;
while (true) {
@@ -237,7 +236,7 @@ void SwitcherData::Thread()
transition);
break;
case round_trip_func:
checkSceneRoundTrip(match, scene, transition,
checkSceneSequence(match, scene, transition,
lock);
if (sceneChangedDuringWait()) //scene might have changed during the sleep
{

View File

@@ -15,7 +15,8 @@ QLibrary *loaded_curl_lib = nullptr;
bool resolveCurl()
{
f_curl_init = (initFunction)loaded_curl_lib->resolve("curl_easy_init");
f_curl_setopt = (setOptFunction)loaded_curl_lib->resolve("curl_easy_setopt");
f_curl_setopt =
(setOptFunction)loaded_curl_lib->resolve("curl_easy_setopt");
f_curl_perform =
(performFunction)loaded_curl_lib->resolve("curl_easy_perform");
f_curl_cleanup =
@@ -43,7 +44,8 @@ bool loadCurl()
for (QString path : locations) {
blog(LOG_INFO, "trying '%s'", path.toUtf8().constData());
QFileInfo libPath(QDir(path).absoluteFilePath(CURL_LIBRARY_NAME));
QFileInfo libPath(
QDir(path).absoluteFilePath(curl_library_name));
if (libPath.exists() && libPath.isFile()) {
QString libFilePath = libPath.absoluteFilePath();

View File

@@ -257,7 +257,7 @@ void SceneSwitcher::on_exportSettings_clicked()
switcher->saveWindowTitleSwitches(obj);
switcher->saveScreenRegionSwitches(obj);
switcher->savePauseSwitches(obj);
switcher->saveSceneRoundTripSwitches(obj);
switcher->saveSceneSequenceSwitches(obj);
switcher->saveSceneTransitions(obj);
switcher->saveIdleSwitches(obj);
switcher->saveExecutableSwitches(obj);
@@ -302,7 +302,7 @@ void SceneSwitcher::on_importSettings_clicked()
switcher->loadWindowTitleSwitches(obj);
switcher->loadScreenRegionSwitches(obj);
switcher->loadPauseSwitches(obj);
switcher->loadSceneRoundTripSwitches(obj);
switcher->loadSceneSequenceSwitches(obj);
switcher->loadSceneTransitions(obj);
switcher->loadIdleSwitches(obj);
switcher->loadExecutableSwitches(obj);
@@ -674,7 +674,7 @@ void SceneSwitcher::setupGeneralTab()
item->setData(Qt::UserRole, text);
}
for (int i = 0; i < switcher->threadPriorities.size(); ++i) {
for (int i = 0; i < (int)switcher->threadPriorities.size(); ++i) {
ui->threadPriority->addItem(
switcher->threadPriorities[i].name.c_str());
ui->threadPriority->setItemData(

View File

@@ -37,7 +37,7 @@ public:
int PauseScenesFindByData(const QString &scene);
int PauseWindowsFindByData(const QString &window);
int IgnoreWindowsFindByData(const QString &window);
int SceneRoundTripFindByData(const QString &scene1);
int SceneSequenceFindByData(const QString &scene1);
int SceneTransitionsFindByData(const QString &scene1,
const QString &scene2);
int DefaultTransitionsFindByData(const QString &scene);
@@ -106,14 +106,14 @@ public slots:
void on_ignoreWindowsAdd_clicked();
void on_ignoreWindowsRemove_clicked();
void on_sceneRoundTrips_currentRowChanged(int idx);
void on_sceneRoundTripAdd_clicked();
void on_sceneRoundTripRemove_clicked();
void on_sceneRoundTripSave_clicked();
void on_sceneRoundTripLoad_clicked();
void on_sceneRoundTripUp_clicked();
void on_sceneRoundTripDown_clicked();
void on_sceneRoundTripDelayUnits_currentIndexChanged(int index);
void on_sceneSequences_currentRowChanged(int idx);
void on_sceneSequenceAdd_clicked();
void on_sceneSequenceRemove_clicked();
void on_sceneSequenceSave_clicked();
void on_sceneSequenceLoad_clicked();
void on_sceneSequenceUp_clicked();
void on_sceneSequenceDown_clicked();
void on_sceneSequenceDelayUnits_currentIndexChanged(int index);
void on_autoStopSceneCheckBox_stateChanged(int state);
void on_autoStopScenes_currentTextChanged(const QString &text);
@@ -205,6 +205,7 @@ void GetWindowList(std::vector<std::string> &windows);
void GetWindowList(QStringList &windows); // Overloaded
void GetCurrentWindowTitle(std::string &title);
bool isFullscreen(std::string &title);
bool isMaximized(std::string &title);
/********************************************************************************
* Screenregion helper

View File

@@ -3,11 +3,11 @@
#include <QLibrary>
#if defined(WIN32)
#define CURL_LIBRARY_NAME "libcurl.dll"
constexpr auto curl_library_name = "libcurl.dll";
#elif __APPLE__
#define CURL_LIBRARY_NAME "libcurl.4.dylib"
#define curl_library_name "libcurl.4.dylib"
#else
#define CURL_LIBRARY_NAME "libcurl.so.4"
#define curl_library_name "libcurl.so.4"
#endif
typedef CURL *(*initFunction)(void);

View File

@@ -0,0 +1,115 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
constexpr auto audio_func = 8;
constexpr auto default_priority_8 = audio_func;
struct AudioSwitch : virtual SceneSwitcherEntry {
OBSWeakSource audioSource;
int volumeThreshold;
float peak;
std::string audioSwitchStr;
obs_volmeter_t *volmeter;
const char *getType() { return "audio"; }
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];
}
bool valid()
{
return (usePreviousScene || WeakSourceValid(scene)) &&
WeakSourceValid(audioSource) &&
WeakSourceValid(transition);
}
inline AudioSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
OBSWeakSource audioSource_, int volumeThreshold_,
bool usePreviousScene_, std::string audioSwitchStr_)
: SceneSwitcherEntry(scene_, transition_, usePreviousScene_),
audioSource(audioSource_),
volumeThreshold(volumeThreshold_),
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)
: SceneSwitcherEntry(other.scene, other.transition,
other.usePreviousScene),
audioSource(other.audioSource),
volumeThreshold(other.volumeThreshold),
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)
: SceneSwitcherEntry(other.scene, other.transition,
other.usePreviousScene),
audioSource(other.audioSource),
volumeThreshold(other.volumeThreshold),
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;
}
};
static inline QString MakeAudioSwitchName(const QString &scene,
const QString &transition,
const QString &audioSrouce,
const int &volume);

View File

@@ -0,0 +1,28 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
constexpr auto exe_func = 3;
constexpr auto default_priority_3 = exe_func;
struct ExecutableSceneSwitch : SceneSwitcherEntry {
QString exe;
bool inFocus;
const char *getType() { return "exec"; }
inline ExecutableSceneSwitch(OBSWeakSource scene_,
OBSWeakSource transition_,
const QString &exe_, bool inFocus_)
: SceneSwitcherEntry(scene_, transition_),
exe(exe_),
inFocus(inFocus_)
{
}
};
static inline QString MakeSwitchNameExecutable(const QString &scene,
const QString &value,
const QString &transition,
bool inFocus);

View File

@@ -0,0 +1,44 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
constexpr auto read_file_func = 0;
constexpr auto default_priority_0 = read_file_func;
struct FileSwitch : SceneSwitcherEntry {
std::string file;
std::string text;
bool remote = false;
bool useRegex = false;
bool useTime = false;
QDateTime lastMod;
const char *getType() { return "file"; }
inline FileSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
const char *file_, const char *text_, bool remote_,
bool useRegex_, bool useTime_)
: SceneSwitcherEntry(scene_, 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;
};
static inline QString MakeFileSwitchName(const QString &scene,
const QString &transition,
const QString &fileName,
const QString &text, bool useRegex,
bool useTime);

View File

@@ -0,0 +1,48 @@
#pragma once
#include <string>
#include <obs.hpp>
struct SceneSwitcherEntry {
OBSWeakSource scene;
OBSWeakSource transition;
bool usePreviousScene;
virtual bool valid()
{
return (usePreviousScene || WeakSourceValid(scene)) &&
WeakSourceValid(transition);
}
virtual const char *getType() = 0;
// TODO
//virtual bool checkMatch() = 0;
virtual void logMatch()
{
obs_source_t *s = obs_weak_source_get_source(scene);
const char *sceneName = obs_source_get_name(s);
obs_source_release(s);
blog(LOG_INFO,
"Advanced Scene Switcher match for '%s' - switch to scene '%s'",
getType(), sceneName);
}
inline SceneSwitcherEntry() : usePreviousScene(false) {}
inline SceneSwitcherEntry(OBSWeakSource scene_,
OBSWeakSource transition_,
bool usePreviousScene_)
: scene(scene_),
transition(transition_),
usePreviousScene(usePreviousScene_)
{
}
inline SceneSwitcherEntry(OBSWeakSource scene_,
OBSWeakSource transition_)
: scene(scene_),
transition(transition_),
usePreviousScene(false)
{
}
};

View File

@@ -0,0 +1,16 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
constexpr auto default_idle_time = 60;
constexpr auto idle_func = 2;
constexpr auto default_priority_2 = idle_func;
struct IdleData : SceneSwitcherEntry {
bool idleEnable = false;
int time = default_idle_time;
bool alreadySwitched = false;
const char *getType() { return "idle"; }
};

View File

@@ -0,0 +1,50 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
constexpr auto media_func = 6;
constexpr auto default_priority_6 = media_func;
typedef enum {
TIME_RESTRICTION_NONE,
TIME_RESTRICTION_SHORTER,
TIME_RESTRICTION_LONGER,
TIME_RESTRICTION_REMAINING_SHORTER,
TIME_RESTRICTION_REMAINING_LONGER,
} time_restriction;
struct MediaSwitch : SceneSwitcherEntry {
OBSWeakSource source;
obs_media_state state;
time_restriction restriction;
int64_t time;
bool matched;
std::string mediaSwitchStr;
const char *getType() { return "meida"; }
bool valid()
{
return (usePreviousScene || WeakSourceValid(scene)) &&
WeakSourceValid(source) && WeakSourceValid(transition);
}
inline MediaSwitch(OBSWeakSource scene_, OBSWeakSource source_,
OBSWeakSource transition_, obs_media_state state_,
time_restriction restriction_, uint64_t time_,
bool usePreviousScene_, std::string mediaSwitchStr_)
: SceneSwitcherEntry(scene_, transition_, usePreviousScene_),
source(source_),
state(state_),
restriction(restriction_),
time(time_),
mediaSwitchStr(mediaSwitchStr_)
{
}
};
static inline QString
MakeMediaSwitchName(const QString &source, const QString &scene,
const QString &transition, obs_media_state state,
time_restriction restriction, uint64_t time);

View File

@@ -0,0 +1,23 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
struct RandomSwitch : SceneSwitcherEntry {
double delay;
std::string randomSwitchStr;
const char *getType() { return "random"; }
inline RandomSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
double delay_, std::string str)
: SceneSwitcherEntry(scene_, transition_),
delay(delay_),
randomSwitchStr(str)
{
}
};
static inline QString MakeRandomSwitchName(const QString &scene,
const QString &transition,
double &delay);

View File

@@ -0,0 +1,32 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
constexpr auto screen_region_func = 4;
constexpr auto default_priority_4 = screen_region_func;
struct ScreenRegionSwitch : SceneSwitcherEntry {
int minX, minY, maxX, maxY;
std::string regionStr;
const char *getType() { return "region"; }
inline ScreenRegionSwitch(OBSWeakSource scene_,
OBSWeakSource transition_, int minX_,
int minY_, int maxX_, int maxY_,
std::string regionStr_)
: SceneSwitcherEntry(scene_, transition_),
minX(minX_),
minY(minY_),
maxX(maxX_),
maxY(maxY_),
regionStr(regionStr_)
{
}
};
static inline QString MakeScreenRegionSwitchName(const QString &scene,
const QString &transition,
int minX, int minY, int maxX,
int maxY);

View File

@@ -0,0 +1,43 @@
#pragma once
#include <string>
#include <QDateTime>
#include "utility.hpp"
#include "switch-generic.hpp"
constexpr auto time_func = 7;
constexpr auto default_priority_7 = time_func;
typedef enum {
ANY_DAY = 0,
MONDAY = 1,
TUSEDAY = 2,
WEDNESDAY = 3,
THURSDAY = 4,
FRIDAY = 5,
SATURDAY = 6,
SUNDAY = 7,
LIVE = 8
} timeTrigger;
struct TimeSwitch : SceneSwitcherEntry {
timeTrigger trigger;
QTime time;
std::string timeSwitchStr;
const char *getType() { return "time"; }
inline TimeSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
timeTrigger trigger_, QTime time_,
bool usePreviousScene_, std::string timeSwitchStr_)
: SceneSwitcherEntry(scene_, transition_, usePreviousScene_),
trigger(trigger_),
time(time_),
timeSwitchStr(timeSwitchStr_)
{
}
};
static inline QString MakeTimeSwitchName(const QString &scene,
const QString &transition,
const timeTrigger &trigger,
const QTime &time);

View File

@@ -0,0 +1,47 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
struct SceneTransition : SceneSwitcherEntry {
OBSWeakSource scene2;
std::string sceneTransitionStr;
const char *getType() { return "transition"; }
bool valid()
{
return (WeakSourceValid(scene) && WeakSourceValid(scene2)) &&
WeakSourceValid(transition);
}
inline SceneTransition(OBSWeakSource scene_, OBSWeakSource scene2_,
OBSWeakSource transition_,
std::string sceneTransitionStr_)
: SceneSwitcherEntry(scene_, transition_),
scene2(scene2_),
sceneTransitionStr(sceneTransitionStr_)
{
}
};
static inline QString MakeSceneTransitionName(const QString &scene1,
const QString &scene2,
const QString &transition);
struct DefaultSceneTransition : SceneSwitcherEntry {
std::string sceneTransitionStr;
const char *getType() { return "def_transition"; }
inline DefaultSceneTransition(OBSWeakSource scene_,
OBSWeakSource transition_,
std::string sceneTransitionStr_)
: SceneSwitcherEntry(scene_, transition_),
sceneTransitionStr(sceneTransitionStr_)
{
}
};
static inline QString MakeDefaultSceneTransitionName(const QString &scene,
const QString &transition);

View File

@@ -0,0 +1,33 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
constexpr auto window_title_func = 5;
constexpr auto default_priority_5 = window_title_func;
struct WindowSceneSwitch : SceneSwitcherEntry {
std::string window;
bool fullscreen;
bool maximized;
bool focus;
const char *getType() { return "window"; }
inline WindowSceneSwitch(OBSWeakSource scene_, const char *window_,
OBSWeakSource transition_, bool fullscreen_,
bool maximized_, bool focus_)
: SceneSwitcherEntry(scene_, transition_),
window(window_),
fullscreen(fullscreen_),
maximized(maximized_),
focus(focus_)
{
}
};
static inline QString MakeWindowSwitchName(const QString &scene,
const QString &value,
const QString &transition,
bool fullscreen, bool maximized,
bool focus);

View File

@@ -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(); }
};

View File

@@ -0,0 +1,44 @@
#pragma once
#include <string>
#include "utility.hpp"
#include "switch-generic.hpp"
constexpr auto round_trip_func = 1;
constexpr auto default_priority_1 = round_trip_func;
struct SceneSequenceSwitch : SceneSwitcherEntry {
OBSWeakSource startScene;
double delay;
std::string sceneSequenceStr;
const char *getType() { return "sequence"; }
bool valid()
{
return WeakSourceValid(startScene) &&
(usePreviousScene || WeakSourceValid(scene)) &&
WeakSourceValid(transition);
}
void logSleep(int dur)
{
blog(LOG_INFO, "Advanced Scene Switcher sequence sleep %d",
dur);
}
inline SceneSequenceSwitch(OBSWeakSource startScene_,
OBSWeakSource scene_,
OBSWeakSource transition_, double delay_,
bool usePreviousScene_, std::string str)
: SceneSwitcherEntry(scene_, transition_, usePreviousScene_),
startScene(startScene_),
delay(delay_),
sceneSequenceStr(str)
{
}
};
static inline QString MakeSceneSequenceSwitchName(const QString &scene1,
const QString &scene2,
const QString &transition,
double delay);

View File

@@ -11,232 +11,6 @@ static inline bool WeakSourceValid(obs_weak_source_t *ws)
return !!source;
}
static inline QString MakeSwitchName(const QString &scene, const QString &value,
const QString &transition, bool fullscreen,
bool focus)
{
QString name = QStringLiteral("[") + scene + QStringLiteral(", ") +
transition + QStringLiteral("]: ") + value;
if (fullscreen || focus) {
name += QStringLiteral(" (only if");
if (fullscreen)
name += QStringLiteral(" fullscreen");
if (fullscreen && focus)
name += QStringLiteral(" and");
if (focus)
name += QStringLiteral(" focused");
name += QStringLiteral(")");
}
return name;
}
static inline QString MakeSwitchNameExecutable(const QString &scene,
const QString &value,
const QString &transition,
bool inFocus)
{
if (!inFocus)
return QStringLiteral("[") + scene + QStringLiteral(", ") +
transition + QStringLiteral("]: ") + value;
return QStringLiteral("[") + scene + QStringLiteral(", ") + transition +
QStringLiteral("]: ") + value +
QStringLiteral(" (only if focused)");
}
static inline QString MakeScreenRegionSwitchName(const QString &scene,
const QString &transition,
int minX, int minY, int maxX,
int maxY)
{
return QStringLiteral("[") + scene + QStringLiteral(", ") + transition +
QStringLiteral("]: ") + QString::number(minX) +
QStringLiteral(", ") + QString::number(minY) +
QStringLiteral(" x ") + QString::number(maxX) +
QStringLiteral(", ") + QString::number(maxY);
}
static inline QString MakeSceneRoundTripSwitchName(const QString &scene1,
const QString &scene2,
const QString &transition,
double delay)
{
return scene1 + QStringLiteral(" -> wait for ") +
QString::number(delay) + QStringLiteral(" seconds -> ") +
scene2 + QStringLiteral(" (using ") + transition +
QStringLiteral(" transition)");
}
static inline QString MakeSceneTransitionName(const QString &scene1,
const QString &scene2,
const QString &transition)
{
return scene1 + QStringLiteral(" --- ") + transition +
QStringLiteral(" --> ") + scene2;
}
static inline QString MakeDefaultSceneTransitionName(const QString &scene,
const QString &transition)
{
return scene + QStringLiteral(" --> ") + transition;
}
static inline QString MakeRandomSwitchName(const QString &scene,
const QString &transition,
double &delay)
{
return QStringLiteral("[") + scene + QStringLiteral(", ") + transition +
QStringLiteral("]: ") + QString::number(delay) +
QStringLiteral(" seconds");
}
static inline QString MakeFileSwitchName(const QString &scene,
const QString &transition,
const QString &fileName,
const QString &text, bool useRegex,
bool useTime)
{
QString switchName = QStringLiteral("Switch to ") + scene +
QStringLiteral(" using ") + transition +
QStringLiteral(" if ") + fileName;
if (useTime)
switchName += QStringLiteral(" was modified and");
switchName += QStringLiteral(" contains");
if (useRegex)
switchName += QStringLiteral(" (RegEx): \n\"");
else
switchName += QStringLiteral(": \n\"");
if (text.length() > 30)
switchName += text.left(27) + QStringLiteral("...\"");
else
switchName += text + QStringLiteral("\"");
return switchName;
}
typedef enum {
TIME_RESTRICTION_NONE,
TIME_RESTRICTION_SHORTER,
TIME_RESTRICTION_LONGER,
TIME_RESTRICTION_REMAINING_SHORTER,
TIME_RESTRICTION_REMAINING_LONGER,
} time_restriction;
static inline QString
MakeMediaSwitchName(const QString &source, const QString &scene,
const QString &transition, obs_media_state state,
time_restriction restriction, uint64_t time)
{
QString switchName = QStringLiteral("Switch to ") + scene +
QStringLiteral(" using ") + transition +
QStringLiteral(" if ") + source +
QStringLiteral(" state is ");
if (state == OBS_MEDIA_STATE_NONE) {
switchName += QStringLiteral("none");
} else if (state == OBS_MEDIA_STATE_PLAYING) {
switchName += QStringLiteral("playing");
} else if (state == OBS_MEDIA_STATE_OPENING) {
switchName += QStringLiteral("opening");
} else if (state == OBS_MEDIA_STATE_BUFFERING) {
switchName += QStringLiteral("buffering");
} else if (state == OBS_MEDIA_STATE_PAUSED) {
switchName += QStringLiteral("paused");
} else if (state == OBS_MEDIA_STATE_STOPPED) {
switchName += QStringLiteral("stopped");
} else if (state == OBS_MEDIA_STATE_ENDED) {
switchName += QStringLiteral("ended");
} else if (state == OBS_MEDIA_STATE_ERROR) {
switchName += QStringLiteral("error");
}
if (restriction == TIME_RESTRICTION_SHORTER) {
switchName += QStringLiteral(" and time shorter than ");
} else if (restriction == TIME_RESTRICTION_LONGER) {
switchName += QStringLiteral(" and time longer than ");
} else if (restriction == TIME_RESTRICTION_REMAINING_SHORTER) {
switchName +=
QStringLiteral(" and time remaining shorter than ");
} else if (restriction == TIME_RESTRICTION_REMAINING_LONGER) {
switchName +=
QStringLiteral(" and time remaining longer than ");
}
if (restriction != TIME_RESTRICTION_NONE) {
switchName += std::to_string(time).c_str();
switchName += QStringLiteral(" ms");
}
return switchName;
}
typedef enum {
ANY_DAY = 0,
MONDAY = 1,
TUSEDAY = 2,
WEDNESDAY = 3,
THURSDAY = 4,
FRIDAY = 5,
SATURDAY = 6,
SUNDAY = 7,
LIVE = 8
} timeTrigger;
static inline QString MakeTimeSwitchName(const QString &scene,
const QString &transition,
const timeTrigger &trigger,
const QTime &time)
{
QString switchName;
switch (trigger) {
case ANY_DAY:
switchName = QStringLiteral("On any weekday");
break;
case MONDAY:
switchName = QStringLiteral("Mondays");
break;
case TUSEDAY:
switchName = QStringLiteral("Tusedays");
break;
case WEDNESDAY:
switchName = QStringLiteral("Wednesdays");
break;
case THURSDAY:
switchName = QStringLiteral("Thursdays");
break;
case FRIDAY:
switchName = QStringLiteral("Fridays");
break;
case SATURDAY:
switchName = QStringLiteral("Saturdays");
break;
case SUNDAY:
switchName = QStringLiteral("Sundays");
break;
case LIVE:
switchName = QStringLiteral(
"Relative to starting streaming / recording");
break;
}
switchName += QStringLiteral(" at ") + time.toString() +
QStringLiteral(" switch to ") + scene +
QStringLiteral(" using ") + transition;
return switchName;
}
static inline QString MakeAudioSwitchName(const QString &scene,
const QString &transition,
const QString &audioSrouce,
const int &volume)
{
QString switchName = QStringLiteral("When volume of ") + audioSrouce +
QStringLiteral(" is above ") +
QString::number(volume) +
QStringLiteral("% switch to ") + scene +
QStringLiteral(" using ") + transition;
return switchName;
}
static inline std::string GetWeakSourceName(obs_weak_source_t *weak_source)
{
std::string name;

View File

@@ -1,4 +1,6 @@
#include <obs-module.h>
#include <fstream>
#include <regex>
#include "headers/advanced-scene-switcher.hpp"
void startHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,

View File

@@ -247,6 +247,55 @@ std::pair<int, int> getCursorPos()
return pos;
}
bool isMaximized(std::string &title)
{
if (!ewmhIsSupported())
return false;
// Find switch in top level windows
std::vector<Window> windows = getTopLevelWindows();
for (auto &window : windows) {
XTextProperty text;
int status = XGetTextProperty(
disp(), window, &text,
XInternAtom(disp(), "_NET_WM_NAME", true));
if (status == 0)
status = XGetTextProperty(disp(), window, &text,
XInternAtom(disp(), "WM_NAME",
true));
char *name = reinterpret_cast<char *>(text.value);
if (status == 0 || name == nullptr)
continue;
// True if switch equals window
bool equals = (title == name);
// True if switch matches window
bool matches = QString::fromStdString(name).contains(
QRegularExpression(QString::fromStdString(title)));
// If found, check if switch is maximized
if (equals || matches) {
QStringList states = getStates(window);
if (!states.isEmpty()) {
// True if window is maximized vertically
bool vertical = states.contains(
"_NET_WM_STATE_MAXIMIZED_VERT");
// True if window is maximized horizontally
bool horizontal = states.contains(
"_NET_WM_STATE_MAXIMIZED_HORZ");
return (vertical && horizontal);
}
break;
}
}
return false;
}
bool isFullscreen(std::string &title)
{
if (!ewmhIsSupported())
@@ -282,14 +331,8 @@ bool isFullscreen(std::string &title)
// True if window is fullscreen
bool fullscreen = states.contains(
"_NET_WM_STATE_FULLSCREEN");
// True if window is maximized vertically
bool vertical = states.contains(
"_NET_WM_STATE_MAXIMIZED_VERT");
// True if window is maximized horizontally
bool horizontal = states.contains(
"_NET_WM_STATE_MAXIMIZED_HORZ");
return (fullscreen || (vertical && horizontal));
return (fullscreen);
}
break;
@@ -343,4 +386,4 @@ int secondsSinceLastInput()
XCloseDisplay(display);
return idle_time;
}
}

View File

@@ -126,6 +126,13 @@ std::pair<int, int> getCursorPos()
return pos;
}
// TODO:
// not implemented on MacOS as I cannot test it
bool isMaximized(std::string &title)
{
return false;
}
bool isFullscreen(std::string &title)
{
// Check for match

View File

@@ -1,5 +1,4 @@
#include "headers/advanced-scene-switcher.hpp"
#include "headers/volume-control.hpp"
void SceneSwitcher::on_audioSwitches_currentRowChanged(int idx)
@@ -193,7 +192,6 @@ void SwitcherData::checkAudioSwitch(bool &match, OBSWeakSource &scene,
for (AudioSwitch &s : audioSwitches) {
obs_source_t *as = obs_weak_source_get_source(s.audioSource);
const char *name = obs_source_get_name(as);
bool audioActive = obs_source_active(as);
obs_source_release(as);
@@ -207,10 +205,7 @@ void SwitcherData::checkAudioSwitch(bool &match, OBSWeakSource &scene,
match = true;
if (verbose)
blog(LOG_INFO,
"Advanced Scene Switcher audio match for %s",
name);
s.logMatch();
break;
}
}
@@ -325,3 +320,16 @@ void SceneSwitcher::setupAudioTab()
item->setData(Qt::UserRole, listText);
}
}
static inline QString MakeAudioSwitchName(const QString &scene,
const QString &transition,
const QString &audioSrouce,
const int &volume)
{
QString switchName = QStringLiteral("When volume of ") + audioSrouce +
QStringLiteral(" is above ") +
QString::number(volume) +
QStringLiteral("% switch to ") + scene +
QStringLiteral(" using ") + transition;
return switchName;
}

View File

@@ -28,15 +28,15 @@ void SceneSwitcher::on_executables_currentRowChanged(int idx)
std::lock_guard<std::mutex> lock(switcher->m);
for (auto &s : switcher->executableSwitches) {
if (exec.compare(s.mExe) == 0) {
QString sceneName = GetWeakSourceName(s.mScene).c_str();
if (exec.compare(s.exe) == 0) {
QString sceneName = GetWeakSourceName(s.scene).c_str();
QString transitionName =
GetWeakSourceName(s.mTransition).c_str();
GetWeakSourceName(s.transition).c_str();
ui->executableScenes->setCurrentText(sceneName);
ui->executable->setCurrentText(exec);
ui->executableTransitions->setCurrentText(
transitionName);
ui->requiresFocusCheckBox->setChecked(s.mInFocus);
ui->requiresFocusCheckBox->setChecked(s.inFocus);
break;
}
}
@@ -107,10 +107,10 @@ void SceneSwitcher::on_executableAdd_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
for (auto &s : switcher->executableSwitches) {
if (s.mExe == exeName) {
s.mScene = source;
s.mTransition = transition;
s.mInFocus = inFocus;
if (s.exe == exeName) {
s.scene = source;
s.transition = transition;
s.inFocus = inFocus;
break;
}
}
@@ -133,7 +133,7 @@ void SceneSwitcher::on_executableRemove_clicked()
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.mExe == exe) {
if (s.exe == exe) {
switches.erase(it);
break;
}
@@ -172,27 +172,25 @@ void SwitcherData::checkExeSwitch(bool &match, OBSWeakSource &scene,
GetProcessList(runningProcesses);
for (ExecutableSceneSwitch &s : executableSwitches) {
// True if executable switch is running (direct)
bool equals = runningProcesses.contains(s.mExe);
bool equals = runningProcesses.contains(s.exe);
// True if executable switch is running (regex)
bool matches = (runningProcesses.indexOf(
QRegularExpression(s.mExe)) != -1);
QRegularExpression(s.exe)) != -1);
// True if focus is disabled OR switch is focused
bool focus = (!s.mInFocus || isInFocus(s.mExe));
bool focus = (!s.inFocus || isInFocus(s.exe));
// True if current window is ignored AND switch equals OR matches last window
bool ignore =
(ignored && (title == s.mExe.toStdString() ||
(ignored && (title == s.exe.toStdString() ||
QString::fromStdString(title).contains(
QRegularExpression(s.mExe))));
QRegularExpression(s.exe))));
if ((equals || matches) && (focus || ignore)) {
match = true;
scene = s.mScene;
transition = s.mTransition;
scene = s.scene;
transition = s.transition;
if (verbose)
blog(LOG_INFO,
"Advanced Scene Switcher exec match");
s.logMatch();
break;
}
}
@@ -204,9 +202,9 @@ void SwitcherData::saveExecutableSwitches(obs_data_t *obj)
for (ExecutableSceneSwitch &s : switcher->executableSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source = obs_weak_source_get_source(s.mScene);
obs_source_t *source = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.mTransition);
obs_weak_source_get_source(s.transition);
if (source && transition) {
const char *sceneName = obs_source_get_name(source);
@@ -216,8 +214,8 @@ void SwitcherData::saveExecutableSwitches(obs_data_t *obj)
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_string(array_obj, "exefile",
s.mExe.toUtf8());
obs_data_set_bool(array_obj, "infocus", s.mInFocus);
s.exe.toUtf8());
obs_data_set_bool(array_obj, "infocus", s.inFocus);
obs_data_array_push_back(executableArray, array_obj);
obs_source_release(source);
obs_source_release(transition);
@@ -266,15 +264,28 @@ void SceneSwitcher::setupExecutableTab()
ui->executable->addItem(process);
for (auto &s : switcher->executableSwitches) {
std::string sceneName = GetWeakSourceName(s.mScene);
std::string transitionName = GetWeakSourceName(s.mTransition);
std::string sceneName = GetWeakSourceName(s.scene);
std::string transitionName = GetWeakSourceName(s.transition);
QString text = MakeSwitchNameExecutable(sceneName.c_str(),
s.mExe,
s.exe,
transitionName.c_str(),
s.mInFocus);
s.inFocus);
QListWidgetItem *item =
new QListWidgetItem(text, ui->executables);
item->setData(Qt::UserRole, s.mExe);
item->setData(Qt::UserRole, s.exe);
}
}
static inline QString MakeSwitchNameExecutable(const QString &scene,
const QString &value,
const QString &transition,
bool inFocus)
{
if (!inFocus)
return QStringLiteral("[") + scene + QStringLiteral(", ") +
transition + QStringLiteral("]: ") + value;
return QStringLiteral("[") + scene + QStringLiteral(", ") + transition +
QStringLiteral("]: ") + value +
QStringLiteral(" (only if focused)");
}

View File

@@ -1,7 +1,6 @@
#include <QFileDialog>
#include <QTextStream>
#include <QDateTime>
#include <obs.hpp>
#include <curl/curl.h>
#include "headers/advanced-scene-switcher.hpp"
@@ -129,7 +128,8 @@ std::string getRemoteData(std::string &url)
if (switcher->curl && f_curl_setopt && f_curl_perform) {
f_curl_setopt(switcher->curl, CURLOPT_URL, url.c_str());
f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION, WriteCallback);
f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION,
WriteCallback);
f_curl_setopt(switcher->curl, CURLOPT_WRITEDATA, &readBuffer);
f_curl_perform(switcher->curl);
}
@@ -217,9 +217,7 @@ void SwitcherData::checkFileContent(bool &match, OBSWeakSource &scene,
match = true;
if (verbose)
blog(LOG_INFO,
"Advanced Scene Switcher file match");
s.logMatch();
break;
}
}
@@ -310,7 +308,7 @@ void SceneSwitcher::on_fileScenesList_currentRowChanged(int idx)
std::lock_guard<std::mutex> lock(switcher->m);
if (switcher->fileSwitches.size() <= idx)
if ((int)switcher->fileSwitches.size() <= idx)
return;
FileSwitch s = switcher->fileSwitches[idx];
@@ -473,3 +471,27 @@ void SceneSwitcher::setupFileTab()
ui->readPathLineEdit->setDisabled(true);
}
}
static inline QString MakeFileSwitchName(const QString &scene,
const QString &transition,
const QString &fileName,
const QString &text, bool useRegex,
bool useTime)
{
QString switchName = QStringLiteral("Switch to ") + scene +
QStringLiteral(" using ") + transition +
QStringLiteral(" if ") + fileName;
if (useTime)
switchName += QStringLiteral(" was modified and");
switchName += QStringLiteral(" contains");
if (useRegex)
switchName += QStringLiteral(" (RegEx): \n\"");
else
switchName += QStringLiteral(": \n\"");
if (text.length() > 30)
switchName += text.left(27) + QStringLiteral("...\"");
else
switchName += text + QStringLiteral("\"");
return switchName;
}

View File

@@ -1,3 +1,5 @@
#include <regex>
#include "headers/advanced-scene-switcher.hpp"
void SwitcherData::checkIdleSwitch(bool &match, OBSWeakSource &scene,
@@ -43,7 +45,7 @@ void SwitcherData::checkIdleSwitch(bool &match, OBSWeakSource &scene,
idleData.alreadySwitched = true;
if (verbose)
blog(LOG_INFO, "Advanced Scene Switcher idle match");
idleData.logMatch();
} else
idleData.alreadySwitched = false;
}

View File

@@ -1,4 +1,3 @@
#include <obs-module.h>
#include "headers/advanced-scene-switcher.hpp"
void SceneSwitcher::on_mediaSwitches_currentRowChanged(int idx)
@@ -167,8 +166,7 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
transition = mediaSwitch.transition;
if (verbose)
blog(LOG_INFO,
"Advanced Scene Switcher meida match");
mediaSwitch.logMatch();
}
mediaSwitch.matched = matched;
obs_source_release(source);
@@ -299,3 +297,47 @@ void SceneSwitcher::setupMediaTab()
item->setData(Qt::UserRole, listText);
}
}
static inline QString
MakeMediaSwitchName(const QString &source, const QString &scene,
const QString &transition, obs_media_state state,
time_restriction restriction, uint64_t time)
{
QString switchName = QStringLiteral("Switch to ") + scene +
QStringLiteral(" using ") + transition +
QStringLiteral(" if ") + source +
QStringLiteral(" state is ");
if (state == OBS_MEDIA_STATE_NONE) {
switchName += QStringLiteral("none");
} else if (state == OBS_MEDIA_STATE_PLAYING) {
switchName += QStringLiteral("playing");
} else if (state == OBS_MEDIA_STATE_OPENING) {
switchName += QStringLiteral("opening");
} else if (state == OBS_MEDIA_STATE_BUFFERING) {
switchName += QStringLiteral("buffering");
} else if (state == OBS_MEDIA_STATE_PAUSED) {
switchName += QStringLiteral("paused");
} else if (state == OBS_MEDIA_STATE_STOPPED) {
switchName += QStringLiteral("stopped");
} else if (state == OBS_MEDIA_STATE_ENDED) {
switchName += QStringLiteral("ended");
} else if (state == OBS_MEDIA_STATE_ERROR) {
switchName += QStringLiteral("error");
}
if (restriction == TIME_RESTRICTION_SHORTER) {
switchName += QStringLiteral(" and time shorter than ");
} else if (restriction == TIME_RESTRICTION_LONGER) {
switchName += QStringLiteral(" and time longer than ");
} else if (restriction == TIME_RESTRICTION_REMAINING_SHORTER) {
switchName +=
QStringLiteral(" and time remaining shorter than ");
} else if (restriction == TIME_RESTRICTION_REMAINING_LONGER) {
switchName +=
QStringLiteral(" and time remaining longer than ");
}
if (restriction != TIME_RESTRICTION_NONE) {
switchName += std::to_string(time).c_str();
switchName += QStringLiteral(" ms");
}
return switchName;
}

View File

@@ -1,3 +1,5 @@
#include <regex>
#include "headers/advanced-scene-switcher.hpp"
void SceneSwitcher::on_pauseScenesAdd_clicked()

View File

@@ -1,10 +1,11 @@
#include <algorithm>
#include "headers/advanced-scene-switcher.hpp"
void SceneSwitcher::on_threadPriority_currentTextChanged(const QString &text)
{
if (loading ||
ui->threadPriority->count() != switcher->threadPriorities.size())
if (loading || ui->threadPriority->count() !=
(int)switcher->threadPriorities.size())
return;
std::lock_guard<std::mutex> lock(switcher->m);

View File

@@ -1,6 +1,7 @@
#include "headers/advanced-scene-switcher.hpp"
#include <random>
#include "headers/advanced-scene-switcher.hpp"
void SceneSwitcher::on_randomScenesList_currentRowChanged(int idx)
{
if (loading)
@@ -134,8 +135,7 @@ void SwitcherData::checkRandom(bool &match, OBSWeakSource &scene,
lastRandomScene = r.scene;
if (verbose)
blog(LOG_INFO, "Advanced Scene Switcher random match");
r.logMatch();
break;
}
}
@@ -158,8 +158,6 @@ void SwitcherData::saveRandomSwitches(obs_data_t *obj)
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_double(array_obj, "delay", s.delay);
obs_data_set_string(array_obj, "str",
s.randomSwitchStr.c_str());
obs_data_array_push_back(randomArray, array_obj);
obs_source_release(source);
obs_source_release(transition);
@@ -186,11 +184,16 @@ void SwitcherData::loadRandomSwitches(obs_data_t *obj)
const char *transition =
obs_data_get_string(array_obj, "transition");
double delay = obs_data_get_double(array_obj, "delay");
const char *str = obs_data_get_string(array_obj, "str");
std::string randomSwitchStr =
MakeRandomSwitchName(scene, transition, delay)
.toUtf8()
.constData();
switcher->randomSwitches.emplace_back(
GetWeakSourceByName(scene),
GetWeakTransitionByName(transition), delay, str);
GetWeakTransitionByName(transition), delay,
randomSwitchStr);
obs_data_release(array_obj);
}
@@ -213,3 +216,12 @@ void SceneSwitcher::setupRandomTab()
item->setData(Qt::UserRole, text);
}
}
static inline QString MakeRandomSwitchName(const QString &scene,
const QString &transition,
double &delay)
{
return QStringLiteral("[") + scene + QStringLiteral(", ") + transition +
QStringLiteral("]: ") + QString::number(delay) +
QStringLiteral(" seconds");
}

View File

@@ -19,9 +19,7 @@ void SwitcherData::checkScreenRegionSwitch(bool &match, OBSWeakSource &scene,
minRegionSize = regionSize;
if (verbose)
blog(LOG_INFO,
"Advanced Scene Switcher region match");
s.logMatch();
break;
}
}
@@ -213,8 +211,6 @@ void SwitcherData::saveScreenRegionSwitches(obs_data_t *obj)
obs_data_set_int(array_obj, "minY", s.minY);
obs_data_set_int(array_obj, "maxX", s.maxX);
obs_data_set_int(array_obj, "maxY", s.maxY);
obs_data_set_string(array_obj, "screenRegionStr",
s.regionStr.c_str());
obs_data_array_push_back(screenRegionArray, array_obj);
obs_source_release(source);
obs_source_release(transition);
@@ -246,8 +242,12 @@ void SwitcherData::loadScreenRegionSwitches(obs_data_t *obj)
int minY = obs_data_get_int(array_obj, "minY");
int maxX = obs_data_get_int(array_obj, "maxX");
int maxY = obs_data_get_int(array_obj, "maxY");
std::string regionStr =
obs_data_get_string(array_obj, "screenRegionStr");
MakeScreenRegionSwitchName(scene, transition, minX,
minY, maxX, maxY)
.toUtf8()
.constData();
switcher->screenRegionSwitches.emplace_back(
GetWeakSourceByName(scene),
@@ -282,3 +282,15 @@ void SceneSwitcher::setupRegionTab()
SLOT(updateScreenRegionCursorPos()));
screenRegionTimer->start(1000);
}
static inline QString MakeScreenRegionSwitchName(const QString &scene,
const QString &transition,
int minX, int minY, int maxX,
int maxY)
{
return QStringLiteral("[") + scene + QStringLiteral(", ") + transition +
QStringLiteral("]: ") + QString::number(minX) +
QStringLiteral(", ") + QString::number(minY) +
QStringLiteral(" x ") + QString::number(maxX) +
QStringLiteral(", ") + QString::number(maxY);
}

View File

@@ -1,24 +1,23 @@
#include <QFileDialog>
#include <QTextStream>
#include <QMessageBox>
#include <obs.hpp>
#include "headers/advanced-scene-switcher.hpp"
#define SECONDS_INDEX 0
#define MINUTES_INDEX 1
#define HOURS_INDEX 2
constexpr auto seconds_index = 0;
constexpr auto minutes_index = 1;
constexpr auto hours_index = 2;
void SceneSwitcher::on_sceneRoundTripDelayUnits_currentIndexChanged(int index)
void SceneSwitcher::on_sceneSequenceDelayUnits_currentIndexChanged(int index)
{
if (loading)
return;
std::lock_guard<std::mutex> lock(switcher->m);
double val = ui->sceneRoundTripSpinBox->value();
double val = ui->sceneSequenceSpinBox->value();
switch (switcher->sceneRoundTripUnitMultiplier) {
switch (switcher->sceneSequenceMultiplier) {
case 1:
val /= pow(60, index);
break;
@@ -30,32 +29,32 @@ void SceneSwitcher::on_sceneRoundTripDelayUnits_currentIndexChanged(int index)
break;
}
ui->sceneRoundTripSpinBox->setValue(val);
ui->sceneSequenceSpinBox->setValue(val);
switch (index) {
case SECONDS_INDEX:
switcher->sceneRoundTripUnitMultiplier = 1;
case seconds_index:
switcher->sceneSequenceMultiplier = 1;
break;
case MINUTES_INDEX:
switcher->sceneRoundTripUnitMultiplier = 60;
case minutes_index:
switcher->sceneSequenceMultiplier = 60;
break;
case HOURS_INDEX:
switcher->sceneRoundTripUnitMultiplier = 3600;
case hours_index:
switcher->sceneSequenceMultiplier = 3600;
break;
}
}
void SceneSwitcher::on_sceneRoundTripAdd_clicked()
void SceneSwitcher::on_sceneSequenceAdd_clicked()
{
QString scene1Name = ui->sceneRoundTripScenes1->currentText();
QString scene2Name = ui->sceneRoundTripScenes2->currentText();
QString transitionName = ui->sceneRoundTripTransitions->currentText();
QString scene1Name = ui->sceneSequenceScenes1->currentText();
QString scene2Name = ui->sceneSequenceScenes2->currentText();
QString transitionName = ui->sceneSequenceTransitions->currentText();
if (scene1Name.isEmpty() || scene2Name.isEmpty())
return;
double delay = ui->sceneRoundTripSpinBox->value() *
switcher->sceneRoundTripUnitMultiplier;
double delay = ui->sceneSequenceSpinBox->value() *
switcher->sceneSequenceMultiplier;
if (scene1Name == scene2Name)
return;
@@ -64,37 +63,37 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
OBSWeakSource source2 = GetWeakSourceByQString(scene2Name);
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QString text = MakeSceneRoundTripSwitchName(scene1Name, scene2Name,
QString text = MakeSceneSequenceSwitchName(scene1Name, scene2Name,
transitionName, delay);
QVariant v = QVariant::fromValue(text);
int idx = SceneRoundTripFindByData(scene1Name);
int idx = SceneSequenceFindByData(scene1Name);
if (idx == -1) {
QListWidgetItem *item =
new QListWidgetItem(text, ui->sceneRoundTrips);
new QListWidgetItem(text, ui->sceneSequences);
item->setData(Qt::UserRole, v);
std::lock_guard<std::mutex> lock(switcher->m);
switcher->sceneRoundTripSwitches.emplace_back(
switcher->sceneSequenceSwitches.emplace_back(
source1, source2, transition, delay,
(scene2Name == QString(previous_scene_name)),
text.toUtf8().constData());
} else {
QListWidgetItem *item = ui->sceneRoundTrips->item(idx);
QListWidgetItem *item = ui->sceneSequences->item(idx);
item->setText(text);
{
std::lock_guard<std::mutex> lock(switcher->m);
for (auto &s : switcher->sceneRoundTripSwitches) {
if (s.scene1 == source1) {
s.scene2 = source2;
for (auto &s : switcher->sceneSequenceSwitches) {
if (s.startScene == source1) {
s.scene = source2;
s.delay = delay;
s.transition = transition;
s.usePreviousScene =
(scene2Name ==
QString(previous_scene_name));
s.sceneRoundTripStr =
s.sceneSequenceStr =
text.toUtf8().constData();
break;
}
@@ -103,9 +102,9 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
}
}
void SceneSwitcher::on_sceneRoundTripRemove_clicked()
void SceneSwitcher::on_sceneSequenceRemove_clicked()
{
QListWidgetItem *item = ui->sceneRoundTrips->currentItem();
QListWidgetItem *item = ui->sceneSequences->currentItem();
if (!item)
return;
@@ -114,12 +113,12 @@ void SceneSwitcher::on_sceneRoundTripRemove_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
auto &switches = switcher->sceneRoundTripSwitches;
auto &switches = switcher->sceneSequenceSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.sceneRoundTripStr == text) {
if (s.sceneSequenceStr == text) {
switches.erase(it);
break;
}
@@ -129,10 +128,10 @@ void SceneSwitcher::on_sceneRoundTripRemove_clicked()
delete item;
}
void SceneSwitcher::on_sceneRoundTripSave_clicked()
void SceneSwitcher::on_sceneSequenceSave_clicked()
{
QString directory = QFileDialog::getSaveFileName(
this, tr("Save Scene Round Trip to file ..."),
this, tr("Save Scene Sequence to file ..."),
QDir::currentPath(), tr("Text files (*.txt)"));
if (directory.isEmpty())
return;
@@ -141,7 +140,7 @@ void SceneSwitcher::on_sceneRoundTripSave_clicked()
return;
obs_data_t *obj = obs_data_create();
switcher->saveSceneRoundTripSwitches(obj);
switcher->saveSceneSequenceSwitches(obj);
obs_data_save_json(obj, file.fileName().toUtf8().constData());
obs_data_release(obj);
}
@@ -152,7 +151,7 @@ bool oldSceneRoundTripLoad(QFile *file)
QTextStream in(file);
std::vector<QString> lines;
std::vector<SceneRoundTripSwitch> newSceneRoundTripSwitch;
std::vector<SceneSequenceSwitch> newSceneRoundTripSwitch;
while (!in.atEnd()) {
QString line = in.readLine();
@@ -168,7 +167,7 @@ bool oldSceneRoundTripLoad(QFile *file)
(WeakSourceValid(scene2))) &&
WeakSourceValid(transition)) {
newSceneRoundTripSwitch.emplace_back(
SceneRoundTripSwitch(
SceneSequenceSwitch(
GetWeakSourceByQString(lines[0]),
GetWeakSourceByQString(lines[1]),
GetWeakTransitionByQString(
@@ -185,17 +184,17 @@ bool oldSceneRoundTripLoad(QFile *file)
if (lines.size() != 0 || newSceneRoundTripSwitch.size() == 0)
return false;
switcher->sceneRoundTripSwitches.clear();
switcher->sceneRoundTripSwitches = newSceneRoundTripSwitch;
switcher->sceneSequenceSwitches.clear();
switcher->sceneSequenceSwitches = newSceneRoundTripSwitch;
return true;
}
void SceneSwitcher::on_sceneRoundTripLoad_clicked()
void SceneSwitcher::on_sceneSequenceLoad_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
QString directory = QFileDialog::getOpenFileName(
this, tr("Select a file to read Scene Round Trip from ..."),
this, tr("Select a file to read Scene Sequence from ..."),
QDir::currentPath(), tr("Text files (*.txt)"));
if (directory.isEmpty())
return;
@@ -228,7 +227,7 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked()
}
return;
}
switcher->loadSceneRoundTripSwitches(obj);
switcher->loadSceneSequenceSwitches(obj);
obs_data_release(obj);
QMessageBox Msgbox;
@@ -238,25 +237,21 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked()
close();
}
void SwitcherData::checkSceneRoundTrip(bool &match, OBSWeakSource &scene,
void SwitcherData::checkSceneSequence(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition,
std::unique_lock<std::mutex> &lock)
{
bool sceneRoundTripActive = false;
obs_source_t *currentSource = obs_frontend_get_current_scene();
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
for (SceneRoundTripSwitch &s : sceneRoundTripSwitches) {
if (s.scene1 == ws) {
sceneRoundTripActive = true;
for (SceneSequenceSwitch &s : sceneSequenceSwitches) {
if (s.startScene == ws) {
int dur = s.delay * 1000 - interval;
if (dur > 0) {
waitScene = currentSource;
if (verbose)
blog(LOG_INFO,
"Advanced Scene Switcher sequence sleep %d",
dur);
s.logSleep(dur);
cv.wait_for(lock,
std::chrono::milliseconds(dur));
@@ -269,8 +264,10 @@ void SwitcherData::checkSceneRoundTrip(bool &match, OBSWeakSource &scene,
if (currentSource == currentSource2) {
match = true;
scene = (s.usePreviousScene) ? previousScene
: s.scene2;
: s.scene;
transition = s.transition;
if (verbose)
s.logMatch();
}
obs_source_release(currentSource2);
break;
@@ -280,46 +277,46 @@ void SwitcherData::checkSceneRoundTrip(bool &match, OBSWeakSource &scene,
obs_weak_source_release(ws);
}
void SceneSwitcher::on_sceneRoundTrips_currentRowChanged(int idx)
void SceneSwitcher::on_sceneSequences_currentRowChanged(int idx)
{
if (loading)
return;
if (idx == -1)
return;
QListWidgetItem *item = ui->sceneRoundTrips->item(idx);
QListWidgetItem *item = ui->sceneSequences->item(idx);
QString sceneRoundTrip = item->text();
QString sceneSequence = item->text();
std::lock_guard<std::mutex> lock(switcher->m);
for (auto &s : switcher->sceneRoundTripSwitches) {
if (sceneRoundTrip.compare(s.sceneRoundTripStr.c_str()) == 0) {
std::string scene1 = GetWeakSourceName(s.scene1);
std::string scene2 = GetWeakSourceName(s.scene2);
for (auto &s : switcher->sceneSequenceSwitches) {
if (sceneSequence.compare(s.sceneSequenceStr.c_str()) == 0) {
std::string scene1 = GetWeakSourceName(s.startScene);
std::string scene2 = GetWeakSourceName(s.scene);
std::string transitionName =
GetWeakSourceName(s.transition);
double delay = s.delay /
switcher->sceneRoundTripUnitMultiplier;
ui->sceneRoundTripScenes1->setCurrentText(
switcher->sceneSequenceMultiplier;
ui->sceneSequenceScenes1->setCurrentText(
scene1.c_str());
ui->sceneRoundTripScenes2->setCurrentText(
ui->sceneSequenceScenes2->setCurrentText(
scene2.c_str());
ui->sceneRoundTripTransitions->setCurrentText(
ui->sceneSequenceTransitions->setCurrentText(
transitionName.c_str());
ui->sceneRoundTripSpinBox->setValue(delay);
ui->sceneSequenceSpinBox->setValue(delay);
break;
}
}
}
int SceneSwitcher::SceneRoundTripFindByData(const QString &scene1)
int SceneSwitcher::SceneSequenceFindByData(const QString &scene1)
{
QRegExp rx(scene1 + " ->.*");
int count = ui->sceneRoundTrips->count();
int count = ui->sceneSequences->count();
int idx = -1;
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->sceneRoundTrips->item(i);
QListWidgetItem *item = ui->sceneSequences->item(i);
QString itemString = item->data(Qt::UserRole).toString();
if (rx.exactMatch(itemString)) {
@@ -331,44 +328,45 @@ int SceneSwitcher::SceneRoundTripFindByData(const QString &scene1)
return idx;
}
void SceneSwitcher::on_sceneRoundTripUp_clicked()
void SceneSwitcher::on_sceneSequenceUp_clicked()
{
int index = ui->sceneRoundTrips->currentRow();
int index = ui->sceneSequences->currentRow();
if (index != -1 && index != 0) {
ui->sceneRoundTrips->insertItem(
index - 1, ui->sceneRoundTrips->takeItem(index));
ui->sceneRoundTrips->setCurrentRow(index - 1);
ui->sceneSequences->insertItem(
index - 1, ui->sceneSequences->takeItem(index));
ui->sceneSequences->setCurrentRow(index - 1);
std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(switcher->sceneRoundTripSwitches.begin() + index,
switcher->sceneRoundTripSwitches.begin() + index - 1);
iter_swap(switcher->sceneSequenceSwitches.begin() + index,
switcher->sceneSequenceSwitches.begin() + index - 1);
}
}
void SceneSwitcher::on_sceneRoundTripDown_clicked()
void SceneSwitcher::on_sceneSequenceDown_clicked()
{
int index = ui->sceneRoundTrips->currentRow();
if (index != -1 && index != ui->sceneRoundTrips->count() - 1) {
ui->sceneRoundTrips->insertItem(
index + 1, ui->sceneRoundTrips->takeItem(index));
ui->sceneRoundTrips->setCurrentRow(index + 1);
int index = ui->sceneSequences->currentRow();
if (index != -1 && index != ui->sceneSequences->count() - 1) {
ui->sceneSequences->insertItem(
index + 1, ui->sceneSequences->takeItem(index));
ui->sceneSequences->setCurrentRow(index + 1);
std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(switcher->sceneRoundTripSwitches.begin() + index,
switcher->sceneRoundTripSwitches.begin() + index + 1);
iter_swap(switcher->sceneSequenceSwitches.begin() + index,
switcher->sceneSequenceSwitches.begin() + index + 1);
}
}
void SwitcherData::saveSceneRoundTripSwitches(obs_data_t *obj)
void SwitcherData::saveSceneSequenceSwitches(obs_data_t *obj)
{
obs_data_array_t *sceneRoundTripArray = obs_data_array_create();
for (SceneRoundTripSwitch &s : switcher->sceneRoundTripSwitches) {
obs_data_array_t *sceneSequenceArray = obs_data_array_create();
for (SceneSequenceSwitch &s : switcher->sceneSequenceSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source1 = obs_weak_source_get_source(s.scene1);
obs_source_t *source2 = obs_weak_source_get_source(s.scene2);
obs_source_t *source1 =
obs_weak_source_get_source(s.startScene);
obs_source_t *source2 = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
if (source1 && (s.usePreviousScene || source2) && transition) {
@@ -385,9 +383,7 @@ void SwitcherData::saveSceneRoundTripSwitches(obs_data_t *obj)
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_double(array_obj, "delay", s.delay);
obs_data_set_string(array_obj, "sceneRoundTripStr",
s.sceneRoundTripStr.c_str());
obs_data_array_push_back(sceneRoundTripArray,
obs_data_array_push_back(sceneSequenceArray,
array_obj);
obs_source_release(source1);
obs_source_release(source2);
@@ -396,21 +392,21 @@ void SwitcherData::saveSceneRoundTripSwitches(obs_data_t *obj)
obs_data_release(array_obj);
}
obs_data_set_array(obj, "sceneRoundTrip", sceneRoundTripArray);
obs_data_array_release(sceneRoundTripArray);
obs_data_set_array(obj, "sceneRoundTrip", sceneSequenceArray);
obs_data_array_release(sceneSequenceArray);
}
void SwitcherData::loadSceneRoundTripSwitches(obs_data_t *obj)
void SwitcherData::loadSceneSequenceSwitches(obs_data_t *obj)
{
switcher->sceneRoundTripSwitches.clear();
switcher->sceneSequenceSwitches.clear();
obs_data_array_t *sceneRoundTripArray =
obs_data_array_t *sceneSequenceArray =
obs_data_get_array(obj, "sceneRoundTrip");
size_t count = obs_data_array_count(sceneRoundTripArray);
size_t count = obs_data_array_count(sceneSequenceArray);
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj =
obs_data_array_item(sceneRoundTripArray, i);
obs_data_array_item(sceneSequenceArray, i);
const char *scene1 =
obs_data_get_string(array_obj, "sceneRoundTripScene1");
@@ -434,43 +430,43 @@ void SwitcherData::loadSceneRoundTripSwitches(obs_data_t *obj)
delay = obs_data_get_double(array_obj, "delay");
}
std::string str = MakeSceneRoundTripSwitchName(
std::string str = MakeSceneSequenceSwitchName(
scene1, scene2, transition, delay)
.toUtf8()
.constData();
const char *sceneRoundTripStr = str.c_str();
const char *sceneSequenceStr = str.c_str();
switcher->sceneRoundTripSwitches.emplace_back(
switcher->sceneSequenceSwitches.emplace_back(
GetWeakSourceByName(scene1),
GetWeakSourceByName(scene2),
GetWeakTransitionByName(transition), delay,
(strcmp(scene2, previous_scene_name) == 0),
sceneRoundTripStr);
sceneSequenceStr);
obs_data_release(array_obj);
}
obs_data_array_release(sceneRoundTripArray);
obs_data_array_release(sceneSequenceArray);
}
void SceneSwitcher::setupSequenceTab()
{
populateSceneSelection(ui->sceneRoundTripScenes1, false);
populateSceneSelection(ui->sceneRoundTripScenes2, true);
populateTransitionSelection(ui->sceneRoundTripTransitions);
populateSceneSelection(ui->sceneSequenceScenes1, false);
populateSceneSelection(ui->sceneSequenceScenes2, true);
populateTransitionSelection(ui->sceneSequenceTransitions);
double smallestDelay = double(switcher->interval) / 1000;
for (auto &s : switcher->sceneRoundTripSwitches) {
std::string sceneName1 = GetWeakSourceName(s.scene1);
for (auto &s : switcher->sceneSequenceSwitches) {
std::string sceneName1 = GetWeakSourceName(s.startScene);
std::string sceneName2 = (s.usePreviousScene)
? previous_scene_name
: GetWeakSourceName(s.scene2);
: GetWeakSourceName(s.scene);
std::string transitionName = GetWeakSourceName(s.transition);
QString text = MakeSceneRoundTripSwitchName(
QString text = MakeSceneSequenceSwitchName(
sceneName1.c_str(), sceneName2.c_str(),
transitionName.c_str(), s.delay);
QListWidgetItem *item =
new QListWidgetItem(text, ui->sceneRoundTrips);
new QListWidgetItem(text, ui->sceneSequences);
item->setData(Qt::UserRole, text);
if (s.delay < smallestDelay)
@@ -480,21 +476,32 @@ void SceneSwitcher::setupSequenceTab()
? ui->intervalWarning->setVisible(true)
: ui->intervalWarning->setVisible(false);
ui->sceneRoundTripDelayUnits->addItem("seconds");
ui->sceneRoundTripDelayUnits->addItem("minutes");
ui->sceneRoundTripDelayUnits->addItem("hours");
ui->sceneSequenceDelayUnits->addItem("seconds");
ui->sceneSequenceDelayUnits->addItem("minutes");
ui->sceneSequenceDelayUnits->addItem("hours");
switch (switcher->sceneRoundTripUnitMultiplier) {
switch (switcher->sceneSequenceMultiplier) {
case 1:
ui->sceneRoundTripDelayUnits->setCurrentIndex(0);
ui->sceneSequenceDelayUnits->setCurrentIndex(0);
break;
case 60:
ui->sceneRoundTripDelayUnits->setCurrentIndex(1);
ui->sceneSequenceDelayUnits->setCurrentIndex(1);
break;
case 3600:
ui->sceneRoundTripDelayUnits->setCurrentIndex(2);
ui->sceneSequenceDelayUnits->setCurrentIndex(2);
break;
default:
break;
}
}
static inline QString MakeSceneSequenceSwitchName(const QString &scene1,
const QString &scene2,
const QString &transition,
double delay)
{
return scene1 + QStringLiteral(" -> wait for ") +
QString::number(delay) + QStringLiteral(" seconds -> ") +
scene2 + QStringLiteral(" (using ") + transition +
QStringLiteral(" transition)");
}

View File

@@ -223,9 +223,7 @@ void SwitcherData::checkTimeSwitch(bool &match, OBSWeakSource &scene,
match = true;
if (verbose)
blog(LOG_INFO,
"Advanced Scene Switcher time match");
s.logMatch();
break;
}
}
@@ -329,3 +327,46 @@ void SceneSwitcher::setupTimeTab()
item->setData(Qt::UserRole, listText);
}
}
static inline QString MakeTimeSwitchName(const QString &scene,
const QString &transition,
const timeTrigger &trigger,
const QTime &time)
{
QString switchName;
switch (trigger) {
case ANY_DAY:
switchName = QStringLiteral("On any weekday");
break;
case MONDAY:
switchName = QStringLiteral("Mondays");
break;
case TUSEDAY:
switchName = QStringLiteral("Tusedays");
break;
case WEDNESDAY:
switchName = QStringLiteral("Wednesdays");
break;
case THURSDAY:
switchName = QStringLiteral("Thursdays");
break;
case FRIDAY:
switchName = QStringLiteral("Fridays");
break;
case SATURDAY:
switchName = QStringLiteral("Saturdays");
break;
case SUNDAY:
switchName = QStringLiteral("Sundays");
break;
case LIVE:
switchName = QStringLiteral(
"Relative to starting streaming / recording");
break;
}
switchName += QStringLiteral(" at ") + time.toString() +
QStringLiteral(" switch to ") + scene +
QStringLiteral(" using ") + transition;
return switchName;
}

View File

@@ -38,8 +38,7 @@ void SceneSwitcher::on_transitionsAdd_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
for (auto &s : switcher->sceneTransitions) {
if (s.scene1 == source1 &&
s.scene2 == source2) {
if (s.scene == source1 && s.scene2 == source2) {
s.transition = transition;
s.sceneTransitionStr =
text.toUtf8().constData();
@@ -164,8 +163,8 @@ void SwitcherData::setDefaultSceneTransitions()
obs_frontend_set_current_transition(transition);
if (verbose)
blog(LOG_INFO,
"Advanced Scene Switcher default transition set");
if (verbose)
s.logMatch();
obs_source_release(transition);
break;
@@ -229,7 +228,7 @@ void SceneSwitcher::on_sceneTransitions_currentRowChanged(int idx)
for (auto &s : switcher->sceneTransitions) {
if (sceneTransition.compare(s.sceneTransitionStr.c_str()) ==
0) {
std::string scene1 = GetWeakSourceName(s.scene1);
std::string scene1 = GetWeakSourceName(s.scene);
std::string scene2 = GetWeakSourceName(s.scene2);
std::string transitionName =
GetWeakSourceName(s.transition);
@@ -288,7 +287,7 @@ obs_weak_source_t *getNextTransition(obs_weak_source_t *scene1,
obs_weak_source_t *ws = nullptr;
if (scene1 && scene2) {
for (SceneTransition &t : switcher->sceneTransitions) {
if (t.scene1 == scene1 && t.scene2 == scene2)
if (t.scene == scene1 && t.scene2 == scene2)
ws = t.transition;
}
obs_weak_source_addref(ws);
@@ -359,7 +358,7 @@ void SwitcherData::saveSceneTransitions(obs_data_t *obj)
for (SceneTransition &s : switcher->sceneTransitions) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source1 = obs_weak_source_get_source(s.scene1);
obs_source_t *source1 = obs_weak_source_get_source(s.scene);
obs_source_t *source2 = obs_weak_source_get_source(s.scene2);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
@@ -372,8 +371,6 @@ void SwitcherData::saveSceneTransitions(obs_data_t *obj)
obs_data_set_string(array_obj, "Scene2", sceneName2);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_string(array_obj, "Str",
s.sceneTransitionStr.c_str());
obs_data_array_push_back(sceneTransitionsArray,
array_obj);
obs_source_release(source1);
@@ -400,8 +397,6 @@ void SwitcherData::saveSceneTransitions(obs_data_t *obj)
obs_data_set_string(array_obj, "Scene", sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_string(array_obj, "Str",
s.sceneTransitionStr.c_str());
obs_data_array_push_back(defaultTransitionsArray,
array_obj);
obs_source_release(source);
@@ -433,8 +428,11 @@ void SwitcherData::loadSceneTransitions(obs_data_t *obj)
const char *scene2 = obs_data_get_string(array_obj, "Scene2");
const char *transition =
obs_data_get_string(array_obj, "transition");
const char *sceneTransitionsStr =
obs_data_get_string(array_obj, "Str");
std::string sceneTransitionsStr =
MakeSceneTransitionName(scene1, scene2, transition)
.toUtf8()
.constData();
switcher->sceneTransitions.emplace_back(
GetWeakSourceByName(scene1),
@@ -459,8 +457,11 @@ void SwitcherData::loadSceneTransitions(obs_data_t *obj)
const char *scene = obs_data_get_string(array_obj, "Scene");
const char *transition =
obs_data_get_string(array_obj, "transition");
const char *sceneTransitionsStr =
obs_data_get_string(array_obj, "Str");
std::string sceneTransitionsStr =
MakeDefaultSceneTransitionName(scene, transition)
.toUtf8()
.constData();
switcher->defaultSceneTransitions.emplace_back(
GetWeakSourceByName(scene),
@@ -484,7 +485,7 @@ void SceneSwitcher::setupTransitionsTab()
populateTransitionSelection(ui->defaultTransitionsTransitions);
for (auto &s : switcher->sceneTransitions) {
std::string sceneName1 = GetWeakSourceName(s.scene1);
std::string sceneName1 = GetWeakSourceName(s.scene);
std::string sceneName2 = GetWeakSourceName(s.scene2);
std::string transitionName = GetWeakSourceName(s.transition);
QString text = MakeSceneTransitionName(sceneName1.c_str(),
@@ -495,9 +496,6 @@ void SceneSwitcher::setupTransitionsTab()
new QListWidgetItem(text, ui->sceneTransitions);
item->setData(Qt::UserRole, text);
}
//(transitionDurationLongerThanInterval(switcher->interval))
// ? ui->transitionWarning->setVisible(true)
// : ui->transitionWarning->setVisible(false);
for (auto &s : switcher->defaultSceneTransitions) {
std::string sceneName = GetWeakSourceName(s.scene);
@@ -513,3 +511,17 @@ void SceneSwitcher::setupTransitionsTab()
ui->transitionOverridecheckBox->setChecked(
switcher->tansitionOverrideOverride);
}
static inline QString MakeSceneTransitionName(const QString &scene1,
const QString &scene2,
const QString &transition)
{
return scene1 + QStringLiteral(" --- ") + transition +
QStringLiteral(" --> ") + scene2;
}
static inline QString MakeDefaultSceneTransitionName(const QString &scene,
const QString &transition)
{
return scene + QStringLiteral(" --> ") + transition;
}

View File

@@ -1,4 +1,3 @@
#include <obs-module.h>
#include "headers/advanced-scene-switcher.hpp"
bool isRunning(std::string &title)
@@ -65,6 +64,7 @@ void SceneSwitcher::on_add_clicked()
QString windowName = ui->windows->currentText();
QString transitionName = ui->transitions->currentText();
bool fullscreen = ui->fullscreenCheckBox->isChecked();
bool maximized = ui->maximizedCheckBox->isChecked();
bool focus = ui->focusCheckBox->isChecked();
if (windowName.isEmpty() || sceneName.isEmpty())
@@ -74,8 +74,9 @@ void SceneSwitcher::on_add_clicked()
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QVariant v = QVariant::fromValue(windowName);
QString text = MakeSwitchName(sceneName, windowName, transitionName,
fullscreen, focus);
QString text = MakeWindowSwitchName(sceneName, windowName,
transitionName, fullscreen,
maximized, focus);
int idx = FindByData(windowName);
@@ -83,7 +84,7 @@ void SceneSwitcher::on_add_clicked()
std::lock_guard<std::mutex> lock(switcher->m);
switcher->windowSwitches.emplace_back(
source, windowName.toUtf8().constData(), transition,
fullscreen, focus);
fullscreen, maximized, focus);
QListWidgetItem *item = new QListWidgetItem(text, ui->switches);
item->setData(Qt::UserRole, v);
@@ -100,6 +101,7 @@ void SceneSwitcher::on_add_clicked()
s.scene = source;
s.transition = transition;
s.fullscreen = fullscreen;
s.maximized = maximized;
s.focus = focus;
break;
}
@@ -239,6 +241,7 @@ void SceneSwitcher::on_switches_currentRowChanged(int idx)
ui->windows->setCurrentText(window);
ui->transitions->setCurrentText(transitionName.c_str());
ui->fullscreenCheckBox->setChecked(s.fullscreen);
ui->maximizedCheckBox->setChecked(s.maximized);
ui->focusCheckBox->setChecked(s.focus);
break;
}
@@ -293,6 +296,8 @@ void SwitcherData::checkWindowTitleSwitch(bool &match, OBSWeakSource &scene,
for (WindowSceneSwitch &s : windowSwitches) {
// True if fullscreen is disabled OR current window is fullscreen
bool fullscreen = (!s.fullscreen || isFullscreen(s.window));
// True if maximized is disabled OR current window is maximized
bool max = (!s.maximized || isMaximized(s.window));
// True if focus is disabled OR switch is focused
bool focus = (!s.focus || isFocused(s.window));
// True if current window is ignored AND switch equals OR matches last window
@@ -303,11 +308,14 @@ void SwitcherData::checkWindowTitleSwitch(bool &match, OBSWeakSource &scene,
QRegularExpression(
QString::fromStdString(s.window)))));
if (isRunning(s.window) && (fullscreen && (focus || ignore))) {
if (isRunning(s.window) &&
(fullscreen && (max && (focus || ignore)))) {
match = true;
scene = s.scene;
transition = s.transition;
if (verbose)
s.logMatch();
break;
}
}
@@ -333,6 +341,7 @@ void SwitcherData::saveWindowTitleSwitches(obs_data_t *obj)
s.window.c_str());
obs_data_set_bool(array_obj, "fullscreen",
s.fullscreen);
obs_data_set_bool(array_obj, "maximized", s.maximized);
obs_data_set_bool(array_obj, "focus", s.focus);
obs_data_array_push_back(windowTitleArray, array_obj);
obs_source_release(source);
@@ -372,12 +381,20 @@ void SwitcherData::loadWindowTitleSwitches(obs_data_t *obj)
const char *window =
obs_data_get_string(array_obj, "window_title");
bool fullscreen = obs_data_get_bool(array_obj, "fullscreen");
#if __APPLE__
// TODO:
// not implemented on MacOS as I cannot test it
bool maximized = false;
#else
bool maximized = obs_data_get_bool(array_obj, "maximized");
#endif
bool focus = obs_data_get_bool(array_obj, "focus") ||
!obs_data_has_user_value(array_obj, "focus");
switcher->windowSwitches.emplace_back(
GetWeakSourceByName(scene), window,
GetWeakTransitionByName(transition), fullscreen, focus);
GetWeakTransitionByName(transition), fullscreen,
maximized, focus);
obs_data_release(array_obj);
}
@@ -413,10 +430,11 @@ void SceneSwitcher::setupTitleTab()
for (auto &s : switcher->windowSwitches) {
std::string sceneName = GetWeakSourceName(s.scene);
std::string transitionName = GetWeakSourceName(s.transition);
QString text = MakeSwitchName(sceneName.c_str(),
s.window.c_str(),
transitionName.c_str(),
s.fullscreen, s.focus);
QString text = MakeWindowSwitchName(sceneName.c_str(),
s.window.c_str(),
transitionName.c_str(),
s.fullscreen, s.maximized,
s.focus);
QListWidgetItem *item = new QListWidgetItem(text, ui->switches);
item->setData(Qt::UserRole, s.window.c_str());
@@ -429,4 +447,36 @@ void SceneSwitcher::setupTitleTab()
new QListWidgetItem(text, ui->ignoreWindows);
item->setData(Qt::UserRole, text);
}
#if __APPLE__
// TODO:
// not implemented on MacOS as I cannot test it
ui->maximizedCheckBox->setDisabled(true);
ui->maximizedCheckBox->setVisible(false);
#endif
}
static inline QString MakeWindowSwitchName(const QString &scene,
const QString &value,
const QString &transition,
bool fullscreen, bool maximized,
bool focus)
{
QString name = QStringLiteral("[") + scene + QStringLiteral(", ") +
transition + QStringLiteral("]: ") + value;
if (fullscreen || maximized || focus) {
name += QStringLiteral(" (only if");
if (fullscreen)
name += QStringLiteral(" fullscreen ");
if (maximized)
name += QStringLiteral(" maximized ");
if (focus)
name += QStringLiteral(" focused");
name += QStringLiteral(")");
}
return name;
}

View File

@@ -0,0 +1,96 @@
#include "headers/switcher-data-structs.hpp"
#include "headers/utility.hpp"
void SwitcherData::Prune()
{
for (size_t i = 0; i < windowSwitches.size(); i++) {
WindowSceneSwitch &s = windowSwitches[i];
if (!s.valid())
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 (!s.valid())
randomSwitches.erase(randomSwitches.begin() + i--);
}
for (size_t i = 0; i < screenRegionSwitches.size(); i++) {
ScreenRegionSwitch &s = screenRegionSwitches[i];
if (!s.valid())
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 < sceneSequenceSwitches.size(); i++) {
SceneSequenceSwitch &s = sceneSequenceSwitches[i];
if (!s.valid())
sceneSequenceSwitches.erase(
sceneSequenceSwitches.begin() + i--);
}
if (!WeakSourceValid(autoStopScene)) {
autoStopScene = nullptr;
autoStopEnable = false;
}
for (size_t i = 0; i < sceneTransitions.size(); i++) {
SceneTransition &s = sceneTransitions[i];
if (!s.valid())
sceneTransitions.erase(sceneTransitions.begin() + i--);
}
for (size_t i = 0; i < defaultSceneTransitions.size(); i++) {
DefaultSceneTransition &s = defaultSceneTransitions[i];
if (!s.valid())
defaultSceneTransitions.erase(
defaultSceneTransitions.begin() + i--);
}
for (size_t i = 0; i < executableSwitches.size(); i++) {
ExecutableSceneSwitch &s = executableSwitches[i];
if (!s.valid())
executableSwitches.erase(executableSwitches.begin() +
i--);
}
for (size_t i = 0; i < fileSwitches.size(); i++) {
FileSwitch &s = fileSwitches[i];
if (!s.valid())
fileSwitches.erase(fileSwitches.begin() + i--);
}
for (size_t i = 0; i < timeSwitches.size(); i++) {
TimeSwitch &s = timeSwitches[i];
if (!s.valid())
timeSwitches.erase(timeSwitches.begin() + i--);
}
if (!idleData.valid()) {
idleData.idleEnable = false;
}
for (size_t i = 0; i < mediaSwitches.size(); i++) {
MediaSwitch &s = mediaSwitches[i];
if (!s.valid())
mediaSwitches.erase(mediaSwitches.begin() + i--);
}
for (size_t i = 0; i < audioSwitches.size(); i++) {
AudioSwitch &s = audioSwitches[i];
if (!s.valid())
audioSwitches.erase(audioSwitches.begin() + i--);
}
}

View File

@@ -20,7 +20,7 @@ QWeakPointer<VolumeMeterTimer> VolumeMeter::updateTimer;
void VolControl::OBSVolumeChanged(void *data, float db)
{
Q_UNUSED(db);
VolControl *volControl = static_cast<VolControl *>(data);
Q_UNUSED(data);
}
void VolControl::OBSVolumeLevel(void *data,
@@ -35,6 +35,7 @@ void VolControl::OBSVolumeLevel(void *data,
void VolControl::SliderChanged(int vol)
{
Q_UNUSED(vol);
updateText();
}

View File

@@ -102,7 +102,7 @@ std::pair<int, int> getCursorPos()
return pos;
}
bool isFullscreen(std::string &title)
bool isMaximized(std::string &title)
{
RECT appBounds;
MONITORINFO monitorInfo = {0};
@@ -135,6 +135,39 @@ bool isFullscreen(std::string &title)
return true;
}
}
return false;
}
bool isFullscreen(std::string &title)
{
RECT appBounds;
MONITORINFO monitorInfo = {0};
HWND hwnd = GetWindow(GetDesktopWindow(), GW_CHILD);
while (hwnd) {
string wtitle;
if (WindowValid(hwnd) && GetWindowTitle(hwnd, wtitle) &&
(wtitle == title ||
QString::fromStdString(wtitle).contains(QRegularExpression(
QString::fromStdString(title)))))
break;
hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
}
monitorInfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST),
&monitorInfo);
if (hwnd && hwnd != GetDesktopWindow() && hwnd != GetShellWindow()) {
GetWindowRect(hwnd, &appBounds);
if (monitorInfo.rcMonitor.bottom == appBounds.bottom &&
monitorInfo.rcMonitor.top == appBounds.top &&
monitorInfo.rcMonitor.left == appBounds.left &&
monitorInfo.rcMonitor.right == appBounds.right) {
return true;
}
}
return false;
}