This commit is contained in:
WarmUpTill 2018-07-13 22:29:01 +02:00
parent 3381e6d62f
commit d41868c660
18 changed files with 4336 additions and 4290 deletions

View File

@ -68,10 +68,6 @@ void GetCurrentWindowTitle(string& title)
It does not directly read the control.Instead,
it waits for the thread that created the control to process a WM_GETTEXT message.
So if that thread is frozen in a WaitFor... call you have a deadlock.*/
DWORD this_thid = GetCurrentThreadId();
//wstring message = L"\nUI id " + to_wstring(thid) + L", this_th_id " + to_wstring(this_thid) + L"\n";
//OutputDebugString(message.c_str());
//if (this_thid == thid) {
if (GetCurrentProcessId() == pid) {
title = "OBS";
return;

View File

@ -27,6 +27,10 @@
SwitcherData* switcher = nullptr;
/********************************************************************************
* Create the Advanced Scene Switcher settings window
********************************************************************************/
SceneSwitcher::SceneSwitcher(QWidget* parent)
: QDialog(parent)
, ui(new Ui_SceneSwitcher)
@ -125,7 +129,7 @@ SceneSwitcher::SceneSwitcher(QWidget* parent)
item->setData(Qt::UserRole, s.mExe);
}
for (auto& s : switcher->switches)
for (auto& s : switcher->windowSwitches)
{
string sceneName = GetWeakSourceName(s.scene);
string transitionName = GetWeakSourceName(s.transition);
@ -330,7 +334,9 @@ SceneSwitcher::SceneSwitcher(QWidget* parent)
}
/********************************************************************************
* Saving and loading
********************************************************************************/
static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
{
if (saving)
@ -352,7 +358,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
switcher->Prune();
for (SceneSwitch& s : switcher->switches)
for (WindowSceneSwitch& s : switcher->windowSwitches)
{
obs_data_t* array_obj = obs_data_create();
@ -446,8 +452,8 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_set_string(array_obj, "sceneRoundTripScene1", sceneName1);
obs_data_set_string(array_obj, "sceneRoundTripScene2", sceneName2);
obs_data_set_string(array_obj, "transition", transitionName);
obs_data_set_int(array_obj, "sceneRoundTripDelay", s.delay / 1000);
obs_data_set_int(array_obj, "sceneRoundTripDelayMs", s.delay % 1000); //extra value for ms to not destroy settings of old versions
obs_data_set_int(array_obj, "sceneRoundTripDelay", s.delay / 1000); //delay stored in two separate values
obs_data_set_int(array_obj, "sceneRoundTripDelayMs", s.delay % 1000); //to be compatible with older versions
obs_data_set_string(array_obj, "sceneRoundTripStr", s.sceneRoundTripStr.c_str());
obs_data_array_push_back(sceneRoundTripArray, array_obj);
obs_source_release(source1);
@ -675,7 +681,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
switcher->nonMatchingScene = GetWeakSourceByName(nonMatchingScene.c_str());
switcher->switches.clear();
switcher->windowSwitches.clear();
size_t count = obs_data_array_count(array);
for (size_t i = 0; i < count; i++)
@ -687,7 +693,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
const char* window = obs_data_get_string(array_obj, "window_title");
bool fullscreen = obs_data_get_bool(array_obj, "fullscreen");
switcher->switches.emplace_back(GetWeakSourceByName(scene), window,
switcher->windowSwitches.emplace_back(GetWeakSourceByName(scene), window,
GetWeakTransitionByName(transition), fullscreen);
obs_data_release(array_obj);
@ -768,9 +774,9 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
const char* scene1 = obs_data_get_string(array_obj, "sceneRoundTripScene1");
const char* scene2 = obs_data_get_string(array_obj, "sceneRoundTripScene2");
const char* transition = obs_data_get_string(array_obj, "transition");
int delay = obs_data_get_int(array_obj, "sceneRoundTripDelay");
delay = delay * 1000 + obs_data_get_int(array_obj, "sceneRoundTripDelayMs"); //extra value for ms to not destroy settings of old versions
string str = MakeSceneRoundTripSwitchName(scene1, scene2, transition, ((double)delay)/1000.0).toUtf8().constData(); //aaaand i broke it
int delay = obs_data_get_int(array_obj, "sceneRoundTripDelay"); //delay stored in two separate values
delay = delay * 1000 + obs_data_get_int(array_obj, "sceneRoundTripDelayMs"); //to be compatible with older versions
string str = MakeSceneRoundTripSwitchName(scene1, scene2, transition, ((double)delay)/1000.0).toUtf8().constData();
const char* sceneRoundTripStr = str.c_str();
switcher->sceneRoundTripSwitches.emplace_back(GetWeakSourceByName(scene1),
@ -953,57 +959,10 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
}
}
bool SwitcherData::sceneChangedDuringWait(){
bool r = false;
obs_source_t* currentSource = obs_frontend_get_current_scene();
if (!currentSource)
return true;
string curName = (obs_source_get_name(currentSource));
obs_source_release(currentSource);
if (!waitSceneName.empty() && curName != waitSceneName)
r = true;
waitSceneName = "";
return r;
}
obs_weak_source_t* getNextTransition(obs_weak_source_t* scene1, obs_weak_source_t* scene2);
void switchScene(OBSWeakSource scene, OBSWeakSource transition)
{
obs_source_t* source = obs_weak_source_get_source(scene);
obs_source_t* currentSource = obs_frontend_get_current_scene();
if (source && source != currentSource)
{
obs_weak_source_t* currentScene = obs_source_get_weak_source(currentSource);
obs_weak_source_t* nextTransitionWs = getNextTransition(currentScene, scene);
obs_weak_source_release(currentScene);
if (nextTransitionWs)
{
obs_source_t* nextTransition = obs_weak_source_get_source(nextTransitionWs);
//lock.unlock();
//transitionCv.wait(transitionLock, transitionActiveCheck);
//lock.lock();
obs_frontend_set_current_transition(nextTransition);
obs_source_release(nextTransition);
}
else if (transition)
{
obs_source_t* nextTransition = obs_weak_source_get_source(transition);
//lock.unlock();
//transitionCv.wait(transitionLock, transitionActiveCheck);
//lock.lock();
obs_frontend_set_current_transition(nextTransition);
obs_source_release(nextTransition);
}
obs_frontend_set_current_scene(source);
obs_weak_source_release(nextTransitionWs);
}
obs_source_release(currentSource);
obs_source_release(source);
}
/********************************************************************************
* Main switcher thread
********************************************************************************/
void SwitcherData::Thread()
{
@ -1099,6 +1058,54 @@ endLoop:
;
}
void switchScene(OBSWeakSource scene, OBSWeakSource transition)
{
obs_source_t* source = obs_weak_source_get_source(scene);
obs_source_t* currentSource = obs_frontend_get_current_scene();
if (source && source != currentSource)
{
obs_weak_source_t* currentScene = obs_source_get_weak_source(currentSource);
obs_weak_source_t* nextTransitionWs = getNextTransition(currentScene, scene);
obs_weak_source_release(currentScene);
if (nextTransitionWs)
{
obs_source_t* nextTransition = obs_weak_source_get_source(nextTransitionWs);
//lock.unlock();
//transitionCv.wait(transitionLock, transitionActiveCheck);
//lock.lock();
obs_frontend_set_current_transition(nextTransition);
obs_source_release(nextTransition);
}
else if (transition)
{
obs_source_t* nextTransition = obs_weak_source_get_source(transition);
//lock.unlock();
//transitionCv.wait(transitionLock, transitionActiveCheck);
//lock.lock();
obs_frontend_set_current_transition(nextTransition);
obs_source_release(nextTransition);
}
obs_frontend_set_current_scene(source);
obs_weak_source_release(nextTransitionWs);
}
obs_source_release(currentSource);
obs_source_release(source);
}
bool SwitcherData::sceneChangedDuringWait() {
bool r = false;
obs_source_t* currentSource = obs_frontend_get_current_scene();
if (!currentSource)
return true;
obs_source_release(currentSource);
if (waitScene && currentSource != waitScene)
r = true;
waitScene = NULL;
return r;
}
void SwitcherData::Start()
{
if (!th.joinable())
@ -1122,6 +1129,10 @@ void SwitcherData::Stop()
}
}
/********************************************************************************
* OBS module setup
********************************************************************************/
extern "C" void FreeSceneSwitcher()
{
delete switcher;
@ -1138,7 +1149,7 @@ static void OBSEvent(enum obs_frontend_event event, void* switcher)
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
{
SwitcherData* s = (SwitcherData*)switcher;
//wakeup if waiting on timer if scene already changed
//stop waiting if scene was manually changed
lock_guard<mutex> lock(s->m);
if (s->sceneChangedDuringWait())
s->cv.notify_one();
@ -1149,9 +1160,6 @@ static void OBSEvent(enum obs_frontend_event event, void* switcher)
}
}
void startStopHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pressed);
void loadKeybinding(obs_hotkey_id hotkeyId);
extern "C" void InitSceneSwitcher()
{
QAction* action

View File

@ -7,11 +7,12 @@
#include "ui_advanced-scene-switcher.h"
#include "switcher-data-structs.hpp"
struct obs_weak_source;
typedef struct obs_weak_source obs_weak_source_t;
class QCloseEvent;
/*******************************************************************************
* Advanced Scene Switcher window
*******************************************************************************/
class SceneSwitcher : public QDialog {
Q_OBJECT
@ -122,13 +123,53 @@ public slots:
void on_close_clicked();
};
/********************************************************************************
* Windowtitle helper
********************************************************************************/
void GetWindowList(std::vector<std::string> &windows);
void GetCurrentWindowTitle(std::string &title);
pair<int, int> getCursorPos();
bool isFullscreen();
int secondsSinceLastInput();
bool isInFocus(const QString &exeToCheck);
void GetProcessList(QStringList &processes);
/********************************************************************************
* Screenregion helper
********************************************************************************/
pair<int, int> getCursorPos();
/********************************************************************************
* Idle detection helper
********************************************************************************/
int secondsSinceLastInput();
/********************************************************************************
* Executable helper
********************************************************************************/
void GetProcessList(QStringList &processes);
bool isInFocus(const QString &exeToCheck);
/********************************************************************************
* Sceneswitch helper
********************************************************************************/
struct obs_weak_source;
typedef struct obs_weak_source obs_weak_source_t;
obs_weak_source_t* getNextTransition(obs_weak_source_t* scene1, obs_weak_source_t* scene2);
void switchScene(OBSWeakSource scene, OBSWeakSource transition);
/********************************************************************************
* Hotkey helper
********************************************************************************/
void startStopHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pressed);
void loadKeybinding(obs_hotkey_id hotkeyId);
/********************************************************************************
* Main SwitcherData
********************************************************************************/
struct SwitcherData;
extern SwitcherData* switcher;

View File

@ -89,8 +89,6 @@ void SwitcherData::writeSceneInfoToFile()
obs_source_release(currentSource);
}
obs_weak_source_t* getNextTransition(obs_weak_source_t* scene1, obs_weak_source_t* scene2);
void SwitcherData::checkSwitchInfoFromFile(bool& match, OBSWeakSource& scene, OBSWeakSource& transition)
{
if (!fileIO.readEnabled || fileIO.readPath.empty())
@ -126,7 +124,6 @@ void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSo
if (!file.open(QIODevice::ReadOnly))
continue;
//check file mod date
if (s.useTime)
{
QDateTime newLastMod = QFileInfo(file).lastModified();
@ -135,7 +132,6 @@ void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSo
s.lastMod = newLastMod;
}
if (s.useRegex)
{
QTextStream in(&file);
@ -178,7 +174,6 @@ void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSo
}
}
void SceneSwitcher::on_browseButton_3_clicked()
{
QString path = QFileDialog::getOpenFileName(
@ -232,10 +227,8 @@ void SceneSwitcher::on_fileRemove_clicked()
switches.erase(switches.begin() + idx);
}
qDeleteAll(ui->fileScenesList->selectedItems());
//delete item;
}
void SceneSwitcher::on_fileScenesList_currentRowChanged(int idx)
{
if (loading)

View File

@ -27,7 +27,6 @@ void SceneSwitcher::on_priorityDown_clicked()
}
}
bool SwitcherData::prioFuncsValid()
{
auto it = std::unique(functionNamesByPriority.begin(), functionNamesByPriority.end());

View File

@ -93,7 +93,6 @@ void SceneSwitcher::on_randomAdd_clicked()
}
}
void SceneSwitcher::on_randomRemove_clicked()
{
QListWidgetItem* item = ui->randomScenesList->currentItem();
@ -121,7 +120,6 @@ void SceneSwitcher::on_randomRemove_clicked()
delete item;
}
void SwitcherData::checkRandom(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, int& delay)
{
if (randomSwitches.size() == 0)

View File

@ -4,8 +4,6 @@
#include "advanced-scene-switcher.hpp"
obs_weak_source_t* getNextTransition(obs_weak_source_t* scene1, obs_weak_source_t* scene2);
void SceneSwitcher::on_sceneRoundTripAdd_clicked()
{
QString scene1Name = ui->sceneRoundTripScenes1->currentText();
@ -188,7 +186,7 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked()
lines.clear();
}
}
//unvalid amount of lines in file or nothing valid read
if (lines.size() != 0 || newSceneRoundTripSwitch.size() == 0)
return;
@ -218,8 +216,7 @@ void SwitcherData::checkSceneRoundTrip(bool& match, OBSWeakSource& scene, OBSWea
int dur = s.delay - interval;
if (dur > 0)
{
string s = obs_source_get_name(currentSource);
waitSceneName = s;
waitScene = currentSource;
cv.wait_for(lock, chrono::milliseconds(dur));
}
obs_source_t* currentSource2 = obs_frontend_get_current_scene();
@ -306,4 +303,3 @@ void SwitcherData::autoStopStreamAndRecording()
obs_source_release(currentSource);
obs_weak_source_release(ws);
}

View File

@ -163,7 +163,8 @@ void SwitcherData::setDefaultSceneTransitions(unique_lock<mutex>& lock)
if (s.scene == ws)
{
obs_source_t* transition = obs_weak_source_get_source(s.transition);
//sleep planned but no fitting OBS event to measure transition time
//This might cancel the current transition
//There is no way to be sure when the previous transition finished
obs_frontend_set_current_transition(transition);
obs_source_release(transition);
break;

View File

@ -30,14 +30,18 @@
using namespace std;
struct SceneSwitch
/********************************************************************************
* Data structs for each scene switching method
********************************************************************************/
struct WindowSceneSwitch
{
OBSWeakSource scene;
string window;
OBSWeakSource transition;
bool fullscreen;
inline SceneSwitch(
inline WindowSceneSwitch(
OBSWeakSource scene_, const char* window_, OBSWeakSource transition_, bool fullscreen_)
: scene(scene_)
, window(window_)
@ -198,7 +202,9 @@ typedef enum {
} NoMatch;
/********************************************************************************
* SwitcherData
********************************************************************************/
struct SwitcherData
{
thread th;
@ -207,31 +213,46 @@ struct SwitcherData
bool transitionActive = false;
bool waitForTransition = false;
condition_variable transitionCv;
bool stop = false;
vector<SceneSwitch> switches;
string lastTitle;
OBSWeakSource nonMatchingScene;
OBSWeakSource lastRandomScene;
int interval = DEFAULT_INTERVAL;
NoMatch switchIfNotMatching = NO_SWITCH;
bool startAtLaunch = false;
bool stop = false;
obs_source_t* waitScene = NULL; //scene during which wait started
int interval = DEFAULT_INTERVAL;
OBSWeakSource nonMatchingScene;
OBSWeakSource lastRandomScene;
NoMatch switchIfNotMatching = NO_SWITCH;
vector<WindowSceneSwitch> windowSwitches;
vector<string> ignoreIdleWindows;
string lastTitle;
vector<ScreenRegionSwitch> screenRegionSwitches;
vector<OBSWeakSource> pauseScenesSwitches;
vector<string> pauseWindowsSwitches;
vector<string> ignoreWindowsSwitches;
vector<SceneRoundTripSwitch> sceneRoundTripSwitches;
vector<RandomSwitch> randomSwitches;
vector<FileSwitch> fileSwitches;
bool autoStopEnable = false;
OBSWeakSource autoStopScene;
string waitSceneName; //indicates which scene was active when we startet waiting on something
vector<SceneTransition> sceneTransitions;
vector<DefaultSceneTransition> defaultSceneTransitions;
vector<ExecutableSceneSwitch> executableSwitches;
FileIOData fileIO;
IdleData idleData;
vector<string> ignoreIdleWindows;
vector<FileSwitch> fileSwitches;
vector<ExecutableSceneSwitch> executableSwitches;
bool autoStopEnable = false;
OBSWeakSource autoStopScene;
vector<SceneTransition> sceneTransitions;
vector<DefaultSceneTransition> defaultSceneTransitions;
vector<int> functionNamesByPriority = vector<int>{
DEFAULT_PRIORITY_0,
DEFAULT_PRIORITY_1,
@ -260,15 +281,13 @@ struct SwitcherData
void checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSource& transition);
void checkRandom(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, int& delay);
void Prune()
{
for (size_t i = 0; i < switches.size(); i++)
for (size_t i = 0; i < windowSwitches.size(); i++)
{
SceneSwitch& s = switches[i];
WindowSceneSwitch& s = windowSwitches[i];
if (!WeakSourceValid(s.scene) || !WeakSourceValid(s.transition))
switches.erase(switches.begin() + i--);
windowSwitches.erase(windowSwitches.begin() + i--);
}
if (nonMatchingScene && !WeakSourceValid(nonMatchingScene))
@ -351,4 +370,3 @@ struct SwitcherData
Stop();
}
};

View File

@ -164,4 +164,3 @@ static inline OBSWeakSource GetWeakTransitionByQString(const QString& name)
{
return GetWeakTransitionByName(name.toUtf8().constData());
}

View File

@ -22,7 +22,7 @@ void SceneSwitcher::on_add_clicked()
if (idx == -1)
{
lock_guard<mutex> lock(switcher->m);
switcher->switches.emplace_back(
switcher->windowSwitches.emplace_back(
source, windowName.toUtf8().constData(), transition, fullscreen);
QListWidgetItem* item = new QListWidgetItem(text, ui->switches);
@ -37,7 +37,7 @@ void SceneSwitcher::on_add_clicked()
{
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->switches)
for (auto& s : switcher->windowSwitches)
{
if (s.window == window)
{
@ -63,7 +63,7 @@ void SceneSwitcher::on_remove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->switches;
auto& switches = switcher->windowSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
@ -188,7 +188,7 @@ void SceneSwitcher::on_switches_currentRowChanged(int idx)
QString window = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->switches)
for (auto& s : switcher->windowSwitches)
{
if (window.compare(s.window.c_str()) == 0)
{
@ -204,8 +204,6 @@ void SceneSwitcher::on_switches_currentRowChanged(int idx)
}
void SceneSwitcher::on_ignoreWindows_currentRowChanged(int idx)
{
if (loading)
@ -251,7 +249,7 @@ void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBS
lastTitle = title;
//direct match
for (SceneSwitch& s : switches)
for (WindowSceneSwitch& s : windowSwitches)
{
if (s.window == title)
{
@ -262,7 +260,7 @@ void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBS
}
}
//regex match
for (SceneSwitch& s : switches)
for (WindowSceneSwitch& s : windowSwitches)
{
try
{
@ -280,4 +278,3 @@ void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBS
}
}