mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Fix for crash on Scene Collection change
functionNamesByPriority was cleared while in use when changing Scene Collection.
This commit is contained in:
parent
ad052e9323
commit
dd2d70bb9c
|
|
@ -1,323 +1,323 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/scrnsaver.h>
|
||||
#undef Bool
|
||||
#undef CursorShape
|
||||
#undef Expose
|
||||
#undef KeyPress
|
||||
#undef KeyRelease
|
||||
#undef FocusIn
|
||||
#undef FocusOut
|
||||
#undef FontChange
|
||||
#undef None
|
||||
#undef Status
|
||||
#undef Unsorted
|
||||
#include <util/platform.h>
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static Display* xdisplay = 0;
|
||||
|
||||
Display *disp()
|
||||
{
|
||||
if (!xdisplay)
|
||||
xdisplay = XOpenDisplay(NULL);
|
||||
|
||||
return xdisplay;
|
||||
}
|
||||
|
||||
void cleanupDisplay()
|
||||
{
|
||||
if (!xdisplay)
|
||||
return;
|
||||
|
||||
XCloseDisplay(xdisplay);
|
||||
xdisplay = 0;
|
||||
}
|
||||
|
||||
static bool ewmhIsSupported()
|
||||
{
|
||||
Display *display = disp();
|
||||
Atom netSupportingWmCheck = XInternAtom(display,
|
||||
"_NET_SUPPORTING_WM_CHECK", true);
|
||||
Atom actualType;
|
||||
int format = 0;
|
||||
unsigned long num = 0, bytes = 0;
|
||||
unsigned char *data = NULL;
|
||||
Window ewmh_window = 0;
|
||||
|
||||
int status = XGetWindowProperty(
|
||||
display,
|
||||
DefaultRootWindow(display),
|
||||
netSupportingWmCheck,
|
||||
0L,
|
||||
1L,
|
||||
false,
|
||||
XA_WINDOW,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
&data);
|
||||
|
||||
if (status == Success) {
|
||||
if (num > 0) {
|
||||
ewmh_window = ((Window*)data)[0];
|
||||
}
|
||||
if (data) {
|
||||
XFree(data);
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ewmh_window) {
|
||||
status = XGetWindowProperty(
|
||||
display,
|
||||
ewmh_window,
|
||||
netSupportingWmCheck,
|
||||
0L,
|
||||
1L,
|
||||
false,
|
||||
XA_WINDOW,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
&data);
|
||||
if (status != Success || num == 0 ||
|
||||
ewmh_window != ((Window*)data)[0]) {
|
||||
ewmh_window = 0;
|
||||
}
|
||||
if (status == Success && data) {
|
||||
XFree(data);
|
||||
}
|
||||
}
|
||||
|
||||
return ewmh_window != 0;
|
||||
}
|
||||
|
||||
static std::vector<Window> getTopLevelWindows()
|
||||
{
|
||||
std::vector<Window> res;
|
||||
|
||||
res.resize(0);
|
||||
|
||||
if (!ewmhIsSupported()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
Atom netClList = XInternAtom(disp(), "_NET_CLIENT_LIST", true);
|
||||
Atom actualType;
|
||||
int format;
|
||||
unsigned long num, bytes;
|
||||
Window* data = 0;
|
||||
|
||||
for (int i = 0; i < ScreenCount(disp()); ++i) {
|
||||
Window rootWin = RootWindow(disp(), i);
|
||||
|
||||
int status = XGetWindowProperty(
|
||||
disp(),
|
||||
rootWin,
|
||||
netClList,
|
||||
0L,
|
||||
~0L,
|
||||
false,
|
||||
AnyPropertyType,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
(uint8_t**)&data);
|
||||
|
||||
if (status != Success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (unsigned long i = 0; i < num; ++i)
|
||||
res.emplace_back(data[i]);
|
||||
|
||||
XFree(data);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string GetWindowTitle(size_t i)
|
||||
{
|
||||
Window w = getTopLevelWindows().at(i);
|
||||
std::string windowTitle;
|
||||
char* name;
|
||||
|
||||
int status = XFetchName(disp(), w, &name);
|
||||
if (status >= Success && name != nullptr)
|
||||
{
|
||||
std::string str(name);
|
||||
windowTitle = str;
|
||||
}
|
||||
|
||||
XFree(name);
|
||||
|
||||
return windowTitle;
|
||||
}
|
||||
|
||||
void GetWindowList(vector<string> &windows)
|
||||
{
|
||||
windows.resize(0);
|
||||
|
||||
for (size_t i = 0; i < getTopLevelWindows().size(); ++i){
|
||||
if (GetWindowTitle(i) != "")
|
||||
windows.emplace_back(GetWindowTitle(i));
|
||||
}
|
||||
}
|
||||
|
||||
void GetCurrentWindowTitle(string &title)
|
||||
{
|
||||
if (!ewmhIsSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Atom active = XInternAtom(disp(), "_NET_ACTIVE_WINDOW", true);
|
||||
Atom actualType;
|
||||
int format;
|
||||
unsigned long num, bytes;
|
||||
Window* data = 0;
|
||||
char* name;
|
||||
|
||||
Window rootWin = RootWindow(disp(), 0);
|
||||
|
||||
XGetWindowProperty(
|
||||
disp(),
|
||||
rootWin,
|
||||
active,
|
||||
0L,
|
||||
~0L,
|
||||
false,
|
||||
AnyPropertyType,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
(uint8_t**)&data);
|
||||
|
||||
int status = XFetchName(disp(), data[0], &name);
|
||||
|
||||
if (status >= Success && name != nullptr) {
|
||||
std::string str(name);
|
||||
title = str;
|
||||
}
|
||||
|
||||
XFree(name);
|
||||
}
|
||||
|
||||
pair<int, int> getCursorPos()
|
||||
{
|
||||
pair<int, int> pos(0, 0);
|
||||
Display *dpy;
|
||||
Window root;
|
||||
Window ret_root;
|
||||
Window ret_child;
|
||||
int root_x;
|
||||
int root_y;
|
||||
int win_x;
|
||||
int win_y;
|
||||
unsigned int mask;
|
||||
|
||||
dpy = XOpenDisplay(NULL);
|
||||
root = XDefaultRootWindow(dpy);
|
||||
|
||||
if(XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y,
|
||||
&win_x, &win_y, &mask))
|
||||
{
|
||||
pos = pair<int, int> (root_x,root_y);
|
||||
}
|
||||
XCloseDisplay(dpy);
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool isFullscreen()
|
||||
{
|
||||
if (!ewmhIsSupported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Atom active = XInternAtom(disp(), "_NET_ACTIVE_WINDOW", true);
|
||||
Atom actualType;
|
||||
int format;
|
||||
unsigned long num, bytes;
|
||||
Window* data = 0;
|
||||
|
||||
Window rootWin = RootWindow(disp(), 0);
|
||||
XGetWindowProperty(
|
||||
disp(),
|
||||
rootWin,
|
||||
active,
|
||||
0L,
|
||||
~0L,
|
||||
false,
|
||||
AnyPropertyType,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
(uint8_t**)&data);
|
||||
|
||||
|
||||
XWindowAttributes window_attributes_return;
|
||||
XWindowAttributes screen_attributes_return;
|
||||
|
||||
XGetWindowAttributes(disp(), rootWin, &screen_attributes_return);
|
||||
XGetWindowAttributes(disp(), data[0], &window_attributes_return);
|
||||
|
||||
//menu bar is always 24 pixels in height
|
||||
return (window_attributes_return.width >= screen_attributes_return.width &&
|
||||
window_attributes_return.height + 24 >= screen_attributes_return.height) ? true : false;
|
||||
}
|
||||
|
||||
//exe switch is not quite what is expected but it works for now
|
||||
void GetProcessList(QStringList &processes)
|
||||
{
|
||||
processes.clear();
|
||||
for (size_t i = 0; i < getTopLevelWindows().size(); ++i){
|
||||
string s = GetWindowTitle(i);
|
||||
if (s != "")
|
||||
processes << QString::fromStdString(s);
|
||||
}
|
||||
}
|
||||
|
||||
bool isInFocus(const QString &exeToCheck)
|
||||
{
|
||||
string curWindow;
|
||||
GetCurrentWindowTitle(curWindow);
|
||||
|
||||
return (QString::compare(
|
||||
QString::fromStdString(curWindow),
|
||||
exeToCheck,
|
||||
Qt::CaseInsensitive) == 0) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
int secondsSinceLastInput()
|
||||
{
|
||||
time_t idle_time;
|
||||
static XScreenSaverInfo *mit_info;
|
||||
Display *display;
|
||||
int screen;
|
||||
|
||||
mit_info = XScreenSaverAllocInfo();
|
||||
|
||||
if((display=XOpenDisplay(NULL)) == NULL)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
screen = DefaultScreen(display);
|
||||
XScreenSaverQueryInfo(display, RootWindow(display,screen), mit_info);
|
||||
idle_time = (mit_info->idle) / 1000;
|
||||
XFree(mit_info);
|
||||
XCloseDisplay(display);
|
||||
|
||||
return idle_time;
|
||||
}
|
||||
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/scrnsaver.h>
|
||||
#undef Bool
|
||||
#undef CursorShape
|
||||
#undef Expose
|
||||
#undef KeyPress
|
||||
#undef KeyRelease
|
||||
#undef FocusIn
|
||||
#undef FocusOut
|
||||
#undef FontChange
|
||||
#undef None
|
||||
#undef Status
|
||||
#undef Unsorted
|
||||
#include <util/platform.h>
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static Display* xdisplay = 0;
|
||||
|
||||
Display *disp()
|
||||
{
|
||||
if (!xdisplay)
|
||||
xdisplay = XOpenDisplay(NULL);
|
||||
|
||||
return xdisplay;
|
||||
}
|
||||
|
||||
void cleanupDisplay()
|
||||
{
|
||||
if (!xdisplay)
|
||||
return;
|
||||
|
||||
XCloseDisplay(xdisplay);
|
||||
xdisplay = 0;
|
||||
}
|
||||
|
||||
static bool ewmhIsSupported()
|
||||
{
|
||||
Display *display = disp();
|
||||
Atom netSupportingWmCheck = XInternAtom(display,
|
||||
"_NET_SUPPORTING_WM_CHECK", true);
|
||||
Atom actualType;
|
||||
int format = 0;
|
||||
unsigned long num = 0, bytes = 0;
|
||||
unsigned char *data = NULL;
|
||||
Window ewmh_window = 0;
|
||||
|
||||
int status = XGetWindowProperty(
|
||||
display,
|
||||
DefaultRootWindow(display),
|
||||
netSupportingWmCheck,
|
||||
0L,
|
||||
1L,
|
||||
false,
|
||||
XA_WINDOW,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
&data);
|
||||
|
||||
if (status == Success) {
|
||||
if (num > 0) {
|
||||
ewmh_window = ((Window*)data)[0];
|
||||
}
|
||||
if (data) {
|
||||
XFree(data);
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ewmh_window) {
|
||||
status = XGetWindowProperty(
|
||||
display,
|
||||
ewmh_window,
|
||||
netSupportingWmCheck,
|
||||
0L,
|
||||
1L,
|
||||
false,
|
||||
XA_WINDOW,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
&data);
|
||||
if (status != Success || num == 0 ||
|
||||
ewmh_window != ((Window*)data)[0]) {
|
||||
ewmh_window = 0;
|
||||
}
|
||||
if (status == Success && data) {
|
||||
XFree(data);
|
||||
}
|
||||
}
|
||||
|
||||
return ewmh_window != 0;
|
||||
}
|
||||
|
||||
static std::vector<Window> getTopLevelWindows()
|
||||
{
|
||||
std::vector<Window> res;
|
||||
|
||||
res.resize(0);
|
||||
|
||||
if (!ewmhIsSupported()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
Atom netClList = XInternAtom(disp(), "_NET_CLIENT_LIST", true);
|
||||
Atom actualType;
|
||||
int format;
|
||||
unsigned long num, bytes;
|
||||
Window* data = 0;
|
||||
|
||||
for (int i = 0; i < ScreenCount(disp()); ++i) {
|
||||
Window rootWin = RootWindow(disp(), i);
|
||||
|
||||
int status = XGetWindowProperty(
|
||||
disp(),
|
||||
rootWin,
|
||||
netClList,
|
||||
0L,
|
||||
~0L,
|
||||
false,
|
||||
AnyPropertyType,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
(uint8_t**)&data);
|
||||
|
||||
if (status != Success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (unsigned long i = 0; i < num; ++i)
|
||||
res.emplace_back(data[i]);
|
||||
|
||||
XFree(data);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string GetWindowTitle(size_t i)
|
||||
{
|
||||
Window w = getTopLevelWindows().at(i);
|
||||
std::string windowTitle;
|
||||
char* name;
|
||||
|
||||
int status = XFetchName(disp(), w, &name);
|
||||
if (status >= Success && name != nullptr)
|
||||
{
|
||||
std::string str(name);
|
||||
windowTitle = str;
|
||||
}
|
||||
|
||||
XFree(name);
|
||||
|
||||
return windowTitle;
|
||||
}
|
||||
|
||||
void GetWindowList(vector<string> &windows)
|
||||
{
|
||||
windows.resize(0);
|
||||
|
||||
for (size_t i = 0; i < getTopLevelWindows().size(); ++i){
|
||||
if (GetWindowTitle(i) != "")
|
||||
windows.emplace_back(GetWindowTitle(i));
|
||||
}
|
||||
}
|
||||
|
||||
void GetCurrentWindowTitle(string &title)
|
||||
{
|
||||
if (!ewmhIsSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Atom active = XInternAtom(disp(), "_NET_ACTIVE_WINDOW", true);
|
||||
Atom actualType;
|
||||
int format;
|
||||
unsigned long num, bytes;
|
||||
Window* data = 0;
|
||||
char* name;
|
||||
|
||||
Window rootWin = RootWindow(disp(), 0);
|
||||
|
||||
XGetWindowProperty(
|
||||
disp(),
|
||||
rootWin,
|
||||
active,
|
||||
0L,
|
||||
~0L,
|
||||
false,
|
||||
AnyPropertyType,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
(uint8_t**)&data);
|
||||
|
||||
int status = XFetchName(disp(), data[0], &name);
|
||||
|
||||
if (status >= Success && name != nullptr) {
|
||||
std::string str(name);
|
||||
title = str;
|
||||
}
|
||||
|
||||
XFree(name);
|
||||
}
|
||||
|
||||
pair<int, int> getCursorPos()
|
||||
{
|
||||
pair<int, int> pos(0, 0);
|
||||
Display *dpy;
|
||||
Window root;
|
||||
Window ret_root;
|
||||
Window ret_child;
|
||||
int root_x;
|
||||
int root_y;
|
||||
int win_x;
|
||||
int win_y;
|
||||
unsigned int mask;
|
||||
|
||||
dpy = XOpenDisplay(NULL);
|
||||
root = XDefaultRootWindow(dpy);
|
||||
|
||||
if(XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y,
|
||||
&win_x, &win_y, &mask))
|
||||
{
|
||||
pos = pair<int, int> (root_x,root_y);
|
||||
}
|
||||
XCloseDisplay(dpy);
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool isFullscreen()
|
||||
{
|
||||
if (!ewmhIsSupported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Atom active = XInternAtom(disp(), "_NET_ACTIVE_WINDOW", true);
|
||||
Atom actualType;
|
||||
int format;
|
||||
unsigned long num, bytes;
|
||||
Window* data = 0;
|
||||
|
||||
Window rootWin = RootWindow(disp(), 0);
|
||||
XGetWindowProperty(
|
||||
disp(),
|
||||
rootWin,
|
||||
active,
|
||||
0L,
|
||||
~0L,
|
||||
false,
|
||||
AnyPropertyType,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
(uint8_t**)&data);
|
||||
|
||||
|
||||
XWindowAttributes window_attributes_return;
|
||||
XWindowAttributes screen_attributes_return;
|
||||
|
||||
XGetWindowAttributes(disp(), rootWin, &screen_attributes_return);
|
||||
XGetWindowAttributes(disp(), data[0], &window_attributes_return);
|
||||
|
||||
//menu bar is always 24 pixels in height
|
||||
return (window_attributes_return.width >= screen_attributes_return.width &&
|
||||
window_attributes_return.height + 24 >= screen_attributes_return.height) ? true : false;
|
||||
}
|
||||
|
||||
//exe switch is not quite what is expected but it works for now
|
||||
void GetProcessList(QStringList &processes)
|
||||
{
|
||||
processes.clear();
|
||||
for (size_t i = 0; i < getTopLevelWindows().size(); ++i){
|
||||
string s = GetWindowTitle(i);
|
||||
if (s != "")
|
||||
processes << QString::fromStdString(s);
|
||||
}
|
||||
}
|
||||
|
||||
bool isInFocus(const QString &exeToCheck)
|
||||
{
|
||||
string curWindow;
|
||||
GetCurrentWindowTitle(curWindow);
|
||||
|
||||
return (QString::compare(
|
||||
QString::fromStdString(curWindow),
|
||||
exeToCheck,
|
||||
Qt::CaseInsensitive) == 0) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
int secondsSinceLastInput()
|
||||
{
|
||||
time_t idle_time;
|
||||
static XScreenSaverInfo *mit_info;
|
||||
Display *display;
|
||||
int screen;
|
||||
|
||||
mit_info = XScreenSaverAllocInfo();
|
||||
|
||||
if((display=XOpenDisplay(NULL)) == NULL)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
screen = DefaultScreen(display);
|
||||
XScreenSaverQueryInfo(display, RootWindow(display,screen), mit_info);
|
||||
idle_time = (mit_info->idle) / 1000;
|
||||
XFree(mit_info);
|
||||
XCloseDisplay(display);
|
||||
|
||||
return idle_time;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -483,7 +483,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
|
|||
obs_data_set_int(obj, "interval", switcher->interval);
|
||||
obs_data_set_string(obj, "non_matching_scene", nonMatchingSceneName.c_str());
|
||||
obs_data_set_bool(obj, "switch_if_not_matching", switcher->switchIfNotMatching);
|
||||
obs_data_set_bool(obj, "active", switcher->th.joinable());
|
||||
obs_data_set_bool(obj, "active", !switcher->stop);
|
||||
|
||||
obs_data_set_array(obj, "switches", array);
|
||||
obs_data_set_array(obj, "screenRegion", screenRegionArray);
|
||||
|
|
@ -760,22 +760,20 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
|
|||
obs_data_set_default_string(obj, "priority4", DEFAULT_PRIORITY_4);
|
||||
obs_data_set_default_string(obj, "priority5", DEFAULT_PRIORITY_5);
|
||||
|
||||
switcher->functionNamesByPriority.clear();
|
||||
switcher->functionNamesByPriority.push_back(obs_data_get_string(obj, "priority0"));
|
||||
switcher->functionNamesByPriority.push_back(obs_data_get_string(obj, "priority1"));
|
||||
switcher->functionNamesByPriority.push_back(obs_data_get_string(obj, "priority2"));
|
||||
switcher->functionNamesByPriority.push_back(obs_data_get_string(obj, "priority3"));
|
||||
switcher->functionNamesByPriority.push_back(obs_data_get_string(obj, "priority4"));
|
||||
switcher->functionNamesByPriority.push_back(obs_data_get_string(obj, "priority5"));
|
||||
switcher->functionNamesByPriority[0] = (obs_data_get_string(obj, "priority0"));
|
||||
switcher->functionNamesByPriority[1] = (obs_data_get_string(obj, "priority1"));
|
||||
switcher->functionNamesByPriority[2] = (obs_data_get_string(obj, "priority2"));
|
||||
switcher->functionNamesByPriority[3] = (obs_data_get_string(obj, "priority3"));
|
||||
switcher->functionNamesByPriority[4] = (obs_data_get_string(obj, "priority4"));
|
||||
switcher->functionNamesByPriority[5] = (obs_data_get_string(obj, "priority5"));
|
||||
if (!switcher->prioFuncsValid())
|
||||
{
|
||||
switcher->functionNamesByPriority.clear();
|
||||
switcher->functionNamesByPriority.push_back(DEFAULT_PRIORITY_0);
|
||||
switcher->functionNamesByPriority.push_back(DEFAULT_PRIORITY_1);
|
||||
switcher->functionNamesByPriority.push_back(DEFAULT_PRIORITY_2);
|
||||
switcher->functionNamesByPriority.push_back(DEFAULT_PRIORITY_3);
|
||||
switcher->functionNamesByPriority.push_back(DEFAULT_PRIORITY_4);
|
||||
switcher->functionNamesByPriority.push_back(DEFAULT_PRIORITY_5);
|
||||
switcher->functionNamesByPriority[0] = (DEFAULT_PRIORITY_0);
|
||||
switcher->functionNamesByPriority[1] = (DEFAULT_PRIORITY_1);
|
||||
switcher->functionNamesByPriority[2] = (DEFAULT_PRIORITY_2);
|
||||
switcher->functionNamesByPriority[3] = (DEFAULT_PRIORITY_3);
|
||||
switcher->functionNamesByPriority[4] = (DEFAULT_PRIORITY_4);
|
||||
switcher->functionNamesByPriority[5] = (DEFAULT_PRIORITY_5);
|
||||
}
|
||||
|
||||
obs_data_array_release(array);
|
||||
|
|
@ -802,6 +800,8 @@ 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)
|
||||
|
|
@ -850,18 +850,19 @@ void switchScene(OBSWeakSource scene, OBSWeakSource transition)
|
|||
|
||||
void SwitcherData::Thread()
|
||||
{
|
||||
|
||||
//to avoid scene duplication when rapidly switching scene collection
|
||||
this_thread::sleep_for(chrono::seconds(2));
|
||||
|
||||
while (true)
|
||||
{
|
||||
startLoop:
|
||||
unique_lock<mutex> lock(m);
|
||||
unique_lock<mutex> transitionLock(transitionMutex);
|
||||
bool match = false;
|
||||
OBSWeakSource scene;
|
||||
OBSWeakSource transition;
|
||||
chrono::milliseconds duration(interval);
|
||||
|
||||
switcher->Prune();
|
||||
|
||||
//sleep for a bit
|
||||
cv.wait_for(lock, duration);
|
||||
if (switcher->stop)
|
||||
|
|
@ -878,7 +879,6 @@ void SwitcherData::Thread()
|
|||
continue;
|
||||
}
|
||||
|
||||
//do callbacks 'n stuff in future ...
|
||||
for (string switchFuncName : functionNamesByPriority)
|
||||
{
|
||||
if (switchFuncName == READ_FILE_FUNC)
|
||||
|
|
@ -905,7 +905,9 @@ void SwitcherData::Thread()
|
|||
{
|
||||
checkSceneRoundTrip(match, scene, transition, lock);
|
||||
if (sceneChangedDuringWait()) //scene might have changed during the sleep
|
||||
{
|
||||
goto startLoop;
|
||||
}
|
||||
}
|
||||
if (switcher->stop)
|
||||
{
|
||||
|
|
@ -917,7 +919,6 @@ void SwitcherData::Thread()
|
|||
}
|
||||
}
|
||||
|
||||
//switch if no match?
|
||||
if (!match && switchIfNotMatching && nonMatchingScene)
|
||||
{
|
||||
match = true;
|
||||
|
|
@ -950,11 +951,9 @@ void SwitcherData::Stop()
|
|||
if (th.joinable())
|
||||
{
|
||||
switcher->stop = true;
|
||||
switcher->stop = true;
|
||||
cv.notify_one();
|
||||
transitionCv.notify_one();
|
||||
th.join();
|
||||
cv.notify_one();
|
||||
th.join();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -964,7 +963,6 @@ extern "C" void FreeSceneSwitcher()
|
|||
switcher = nullptr;
|
||||
}
|
||||
|
||||
//why is OBS_FRONTEND_EVENT_SCENE_CHANGED fired after OBS_FRONTEND_EVENT_TRANSITION_STOPPED?
|
||||
static void OBSEvent(enum obs_frontend_event event, void* switcher)
|
||||
{
|
||||
switch (event){
|
||||
|
|
@ -981,15 +979,9 @@ static void OBSEvent(enum obs_frontend_event event, void* switcher)
|
|||
s->cv.notify_one();
|
||||
break;
|
||||
}
|
||||
case OBS_FRONTEND_EVENT_TRANSITION_STOPPED:
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case OBS_FRONTEND_EVENT_TRANSITION_CHANGED:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void startStopHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pressed);
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@ struct SwitcherData
|
|||
thread th;
|
||||
condition_variable cv;
|
||||
mutex m;
|
||||
mutex transitionMutex;
|
||||
bool transitionActive = false;
|
||||
bool waitForTransition = false;
|
||||
condition_variable transitionCv;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user