Merge pull request #24 from Myned/master

General improvements, changes, and fixes
This commit is contained in:
WarmUpTill 2020-06-12 18:39:08 +02:00 committed by GitHub
commit 08c668f90a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 2808 additions and 2220 deletions

107
.clang-format Normal file
View File

@ -0,0 +1,107 @@
# please use clang-format version 8 or later
Standard: Cpp11
AccessModifierOffset: -8
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
#AllowAllArgumentsOnNextLine: false # requires clang-format 9
#AllowAllConstructorInitializersOnNextLine: false # requires clang-format 9
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
#AllowShortLambdasOnASingleLine: Inline # requires clang-format 9
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakStringLiterals: false # apparently unpredictable
ColumnLimit: 80
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
FixNamespaceComments: false
ForEachMacros:
- 'json_object_foreach'
- 'json_object_foreach_safe'
- 'json_array_foreach'
IncludeBlocks: Preserve
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
#ObjCBinPackProtocolList: Auto # requires clang-format 7
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
#SpaceAfterLogicalNot: false # requires clang-format 9
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
#SpaceBeforeCtorInitializerColon: true # requires clang-format 7
#SpaceBeforeInheritanceColon: true # requires clang-format 7
SpaceBeforeParens: ControlStatements
#SpaceBeforeRangeBasedForLoopColon: true # requires clang-format 7
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
#StatementMacros: # requires clang-format 8
# - 'Q_OBJECT'
TabWidth: 8
#TypenameMacros: # requires clang-format 9
# - 'DARRAY'
UseTab: ForContinuationAndIndentation
---
Language: ObjC

File diff suppressed because it is too large Load Diff

View File

@ -130,6 +130,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
vector<string> windows;
GetWindowList(windows);
sort(windows.begin(), windows.end());
for (string &window : windows) {
ui->windows->addItem(window.c_str());
@ -159,9 +160,10 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
for (auto &s : switcher->windowSwitches) {
string sceneName = GetWeakSourceName(s.scene);
string transitionName = GetWeakSourceName(s.transition);
QString text =
MakeSwitchName(sceneName.c_str(), s.window.c_str(),
transitionName.c_str(), s.fullscreen);
QString text = MakeSwitchName(sceneName.c_str(),
s.window.c_str(),
transitionName.c_str(),
s.fullscreen, s.focus);
QListWidgetItem *item = new QListWidgetItem(text, ui->switches);
item->setData(Qt::UserRole, s.window.c_str());
@ -462,6 +464,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
s.window.c_str());
obs_data_set_bool(array_obj, "fullscreen",
s.fullscreen);
obs_data_set_bool(array_obj, "focus", s.focus);
obs_data_array_push_back(array, array_obj);
obs_source_release(source);
obs_source_release(transition);
@ -976,11 +979,14 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
obs_data_get_string(array_obj, "window_title");
bool fullscreen =
obs_data_get_bool(array_obj, "fullscreen");
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);
GetWeakTransitionByName(transition), fullscreen,
focus);
obs_data_release(array_obj);
}
@ -1564,11 +1570,11 @@ void SwitcherData::Start()
if (!(th && th->isRunning())) {
stop = false;
switcher->th = new SwitcherThread();
switcher->th->start((QThread::Priority)switcher->threadPriority);
switcher->th->start(
(QThread::Priority)switcher->threadPriority);
}
}
void SwitcherData::Stop()
{
if (th && th->isRunning()) {

View File

@ -1,12 +1,11 @@
#include "headers/advanced-scene-switcher.hpp"
int SceneSwitcher::executableFindByData(const QString& exe)
int SceneSwitcher::executableFindByData(const QString &exe)
{
int count = ui->executables->count();
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->executables->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->executables->item(i);
QString itemExe = item->data(Qt::UserRole).toString();
if (itemExe == exe)
@ -16,7 +15,6 @@ int SceneSwitcher::executableFindByData(const QString& exe)
return -1;
}
void SceneSwitcher::on_executables_currentRowChanged(int idx)
{
if (loading)
@ -24,26 +22,55 @@ void SceneSwitcher::on_executables_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->executables->item(idx);
QListWidgetItem *item = ui->executables->item(idx);
QString exec = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->executableSwitches)
{
if (exec.compare(s.mExe) == 0)
{
for (auto &s : switcher->executableSwitches) {
if (exec.compare(s.mExe) == 0) {
QString sceneName = GetWeakSourceName(s.mScene).c_str();
QString transitionName = GetWeakSourceName(s.mTransition).c_str();
QString transitionName =
GetWeakSourceName(s.mTransition).c_str();
ui->executableScenes->setCurrentText(sceneName);
ui->executable->setCurrentText(exec);
ui->executableTransitions->setCurrentText(transitionName);
ui->executableTransitions->setCurrentText(
transitionName);
ui->requiresFocusCheckBox->setChecked(s.mInFocus);
break;
}
}
}
void SceneSwitcher::on_executableUp_clicked()
{
int index = ui->executables->currentRow();
if (index != -1 && index != 0) {
ui->executables->insertItem(index - 1,
ui->executables->takeItem(index));
ui->executables->setCurrentRow(index - 1);
lock_guard<mutex> lock(switcher->m);
iter_swap(switcher->executableSwitches.begin() + index,
switcher->executableSwitches.begin() + index - 1);
}
}
void SceneSwitcher::on_executableDown_clicked()
{
int index = ui->executables->currentRow();
if (index != -1 && index != ui->executables->count() - 1) {
ui->executables->insertItem(index + 1,
ui->executables->takeItem(index));
ui->executables->setCurrentRow(index + 1);
lock_guard<mutex> lock(switcher->m);
iter_swap(switcher->executableSwitches.begin() + index,
switcher->executableSwitches.begin() + index + 1);
}
}
void SceneSwitcher::on_executableAdd_clicked()
{
@ -59,30 +86,28 @@ void SceneSwitcher::on_executableAdd_clicked()
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QVariant v = QVariant::fromValue(exeName);
QString text = MakeSwitchNameExecutable(sceneName, exeName, transitionName, inFocus);
QString text = MakeSwitchNameExecutable(sceneName, exeName,
transitionName, inFocus);
int idx = executableFindByData(exeName);
if (idx == -1)
{
if (idx == -1) {
lock_guard<mutex> lock(switcher->m);
switcher->executableSwitches.emplace_back(
source, transition, exeName.toUtf8().constData(), inFocus);
source, transition, exeName.toUtf8().constData(),
inFocus);
QListWidgetItem* item = new QListWidgetItem(text, ui->executables);
QListWidgetItem *item =
new QListWidgetItem(text, ui->executables);
item->setData(Qt::UserRole, v);
}
else
{
QListWidgetItem* item = ui->executables->item(idx);
} else {
QListWidgetItem *item = ui->executables->item(idx);
item->setText(text);
{
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->executableSwitches)
{
if (s.mExe == exeName)
{
for (auto &s : switcher->executableSwitches) {
if (s.mExe == exeName) {
s.mScene = source;
s.mTransition = transition;
s.mInFocus = inFocus;
@ -90,15 +115,12 @@ void SceneSwitcher::on_executableAdd_clicked()
}
}
}
ui->executables->sortItems();
}
}
void SceneSwitcher::on_executableRemove_clicked()
{
QListWidgetItem* item = ui->executables->currentItem();
QListWidgetItem *item = ui->executables->currentItem();
if (!item)
return;
@ -106,14 +128,12 @@ void SceneSwitcher::on_executableRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->executableSwitches;
auto &switches = switcher->executableSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.mExe == exe)
{
if (s.mExe == exe) {
switches.erase(it);
break;
}
@ -123,17 +143,52 @@ void SceneSwitcher::on_executableRemove_clicked()
delete item;
}
void SwitcherData::checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition)
void SwitcherData::checkExeSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
string title;
QStringList runningProcesses;
bool ignored = false;
// Check if current window is ignored
GetCurrentWindowTitle(title);
for (auto &window : ignoreWindowsSwitches) {
// True if ignored switch equals title
bool equals = (title == window);
// True if ignored switch matches title
bool matches = QString::fromStdString(title).contains(
QRegularExpression(QString::fromStdString(window)));
if (equals || matches) {
ignored = true;
title = lastTitle;
break;
}
}
lastTitle = title;
// Check for match
GetProcessList(runningProcesses);
for (ExecutableSceneSwitch& s : executableSwitches)
{
if (runningProcesses.contains(s.mExe))
{
for (ExecutableSceneSwitch &s : executableSwitches) {
// True if executable switch is running (direct)
bool equals = runningProcesses.contains(s.mExe);
// True if executable switch is running (regex)
bool matches = (runningProcesses.indexOf(
QRegularExpression(s.mExe)) != -1);
// True if focus is disabled OR switch is focused
bool focus = (!s.mInFocus || isInFocus(s.mExe));
// True if current window is ignored AND switch equals OR matches last window
bool ignore =
(ignored && (title == s.mExe.toStdString() ||
QString::fromStdString(title).contains(
QRegularExpression(s.mExe))));
if ((equals || matches) && (focus || ignore)) {
match = true;
scene = s.mScene;
transition = s.mTransition;
match = !s.mInFocus || (s.mInFocus && isInFocus(s.mExe));
break;
}
}

View File

@ -4,12 +4,11 @@
#include <obs.hpp>
#include "headers/advanced-scene-switcher.hpp"
void SceneSwitcher::on_browseButton_clicked()
{
QString path = QFileDialog::getOpenFileName(
this, tr("Select a file to write to ..."), QDir::currentPath(), tr("Text files (*.txt)"));
this, tr("Select a file to write to ..."), QDir::currentPath(),
tr("Text files (*.txt)"));
if (!path.isEmpty())
ui->writePathLineEdit->setText(path);
}
@ -20,28 +19,24 @@ void SceneSwitcher::on_readFileCheckBox_stateChanged(int state)
return;
lock_guard<mutex> lock(switcher->m);
if (!state)
{
if (!state) {
ui->browseButton_2->setDisabled(true);
ui->readPathLineEdit->setDisabled(true);
switcher->fileIO.readEnabled = false;
}
else
{
} else {
ui->browseButton_2->setDisabled(false);
ui->readPathLineEdit->setDisabled(false);
switcher->fileIO.readEnabled = true;
}
}
void SceneSwitcher::on_readPathLineEdit_textChanged(const QString& text)
void SceneSwitcher::on_readPathLineEdit_textChanged(const QString &text)
{
if (loading)
return;
lock_guard<mutex> lock(switcher->m);
if (text.isEmpty())
{
if (text.isEmpty()) {
switcher->fileIO.readEnabled = false;
return;
}
@ -49,14 +44,13 @@ void SceneSwitcher::on_readPathLineEdit_textChanged(const QString& text)
switcher->fileIO.readPath = text.toUtf8().constData();
}
void SceneSwitcher::on_writePathLineEdit_textChanged(const QString& text)
void SceneSwitcher::on_writePathLineEdit_textChanged(const QString &text)
{
if (loading)
return;
lock_guard<mutex> lock(switcher->m);
if (text.isEmpty())
{
if (text.isEmpty()) {
switcher->fileIO.writeEnabled = false;
return;
}
@ -67,7 +61,8 @@ void SceneSwitcher::on_writePathLineEdit_textChanged(const QString& text)
void SceneSwitcher::on_browseButton_2_clicked()
{
QString path = QFileDialog::getOpenFileName(
this, tr("Select a file to read from ..."), QDir::currentPath(), tr("Any files (*.*)"));
this, tr("Select a file to read from ..."), QDir::currentPath(),
tr("Any files (*.*)"));
if (!path.isEmpty())
ui->readPathLineEdit->setText(path);
}
@ -77,31 +72,32 @@ void SwitcherData::writeSceneInfoToFile()
if (!fileIO.writeEnabled || fileIO.writePath.empty())
return;
obs_source_t* currentSource = obs_frontend_get_current_scene();
obs_source_t *currentSource = obs_frontend_get_current_scene();
QFile file(QString::fromStdString(fileIO.writePath));
if (file.open(QIODevice::WriteOnly))
{
const char* msg = obs_source_get_name(currentSource);
if (file.open(QIODevice::WriteOnly)) {
const char *msg = obs_source_get_name(currentSource);
file.write(msg, qstrlen(msg));
file.close();
}
obs_source_release(currentSource);
}
void SwitcherData::checkSwitchInfoFromFile(bool& match, OBSWeakSource& scene, OBSWeakSource& transition)
void SwitcherData::checkSwitchInfoFromFile(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
if (!fileIO.readEnabled || fileIO.readPath.empty())
return;
QFile file(QString::fromStdString(fileIO.readPath));
if (file.open(QIODevice::ReadOnly))
{
if (file.open(QIODevice::ReadOnly)) {
QTextStream in(&file);
QString sceneStr = in.readLine();
obs_source_t* sceneRead = obs_get_source_by_name(sceneStr.toUtf8().constData());
if (sceneRead){
obs_weak_source_t* sceneReadWs = obs_source_get_weak_source(sceneRead);
obs_source_t *sceneRead =
obs_get_source_by_name(sceneStr.toUtf8().constData());
if (sceneRead) {
obs_weak_source_t *sceneReadWs =
obs_source_get_weak_source(sceneRead);
match = true;
scene = sceneReadWs;
@ -114,32 +110,28 @@ void SwitcherData::checkSwitchInfoFromFile(bool& match, OBSWeakSource& scene, OB
}
}
void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSource& transition)
void SwitcherData::checkFileContent(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
for (FileSwitch& s : fileSwitches)
{
for (FileSwitch &s : fileSwitches) {
bool equal = false;
QString t = QString::fromStdString(s.text);
QFile file(QString::fromStdString(s.file));
if (!file.open(QIODevice::ReadOnly))
continue;
if (s.useTime)
{
if (s.useTime) {
QDateTime newLastMod = QFileInfo(file).lastModified();
if (s.lastMod == newLastMod)
continue;
s.lastMod = newLastMod;
}
if (s.useRegex)
{
if (s.useRegex) {
QTextStream in(&file);
QRegExp rx(t);
equal = rx.exactMatch(in.readAll());
}
else
{
} else {
/*Im using QTextStream here so the conversion between different lineendings is done by QT.
*QT itself uses only the linefeed internally so the input by the user is always using that,
*but the files selected by the user might use different line endings.
@ -147,24 +139,21 @@ void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSo
*/
QTextStream in(&file);
QTextStream text(&t);
while (!in.atEnd() && !text.atEnd())
{
while (!in.atEnd() && !text.atEnd()) {
QString fileLine = in.readLine();
QString textLine = text.readLine();
if (QString::compare(fileLine, textLine, Qt::CaseSensitive) != 0)
{
if (QString::compare(fileLine, textLine,
Qt::CaseSensitive) != 0) {
equal = false;
break;
}
else {
} else {
equal = true;
}
}
}
file.close();
if (equal)
{
if (equal) {
scene = s.scene;
transition = s.transition;
match = true;
@ -177,7 +166,8 @@ void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSo
void SceneSwitcher::on_browseButton_3_clicked()
{
QString path = QFileDialog::getOpenFileName(
this, tr("Select a file to read from ..."), QDir::currentPath(), tr("Any files (*.*)"));
this, tr("Select a file to read from ..."), QDir::currentPath(),
tr("Any files (*.*)"));
if (!path.isEmpty())
ui->filePathLineEdit->setText(path);
}
@ -191,28 +181,31 @@ void SceneSwitcher::on_fileAdd_clicked()
bool useRegex = ui->fileContentRegExCheckBox->isChecked();
bool useTime = ui->fileContentTimeCheckBox->isChecked();
if (sceneName.isEmpty() || transitionName.isEmpty() || fileName.isEmpty() || text.isEmpty())
if (sceneName.isEmpty() || transitionName.isEmpty() ||
fileName.isEmpty() || text.isEmpty())
return;
OBSWeakSource source = GetWeakSourceByQString(sceneName);
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QString switchText = MakeFileSwitchName(sceneName, transitionName, fileName, text, useRegex, useTime);
QString switchText = MakeFileSwitchName(
sceneName, transitionName, fileName, text, useRegex, useTime);
QVariant v = QVariant::fromValue(switchText);
QListWidgetItem* item = new QListWidgetItem(switchText, ui->fileScenesList);
QListWidgetItem *item =
new QListWidgetItem(switchText, ui->fileScenesList);
item->setData(Qt::UserRole, v);
lock_guard<mutex> lock(switcher->m);
switcher->fileSwitches.emplace_back(
source, transition, fileName.toUtf8().constData(), text.toUtf8().constData(), useRegex, useTime);
switcher->fileSwitches.emplace_back(source, transition,
fileName.toUtf8().constData(),
text.toUtf8().constData(), useRegex,
useTime);
}
void SceneSwitcher::on_fileRemove_clicked()
{
QListWidgetItem* item = ui->fileScenesList->currentItem();
QListWidgetItem *item = ui->fileScenesList->currentItem();
if (!item)
return;
@ -223,7 +216,7 @@ void SceneSwitcher::on_fileRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->fileSwitches;
auto &switches = switcher->fileSwitches;
switches.erase(switches.begin() + idx);
}
qDeleteAll(ui->fileScenesList->selectedItems());

View File

@ -15,10 +15,10 @@ void SceneSwitcher::on_startAtLaunch_toggled(bool value)
switcher->startAtLaunch = value;
}
void SceneSwitcher::UpdateNonMatchingScene(const QString& name)
void SceneSwitcher::UpdateNonMatchingScene(const QString &name)
{
obs_source_t* scene = obs_get_source_by_name(name.toUtf8().constData());
obs_weak_source_t* ws = obs_source_get_weak_source(scene);
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
obs_weak_source_t *ws = obs_source_get_weak_source(scene);
switcher->nonMatchingScene = ws;
@ -57,7 +57,7 @@ void SceneSwitcher::on_noMatchRandomSwitch_clicked()
ui->noMatchSwitchScene->setEnabled(false);
}
void SceneSwitcher::on_noMatchSwitchScene_currentTextChanged(const QString& text)
void SceneSwitcher::on_noMatchSwitchScene_currentTextChanged(const QString &text)
{
if (loading)
return;
@ -89,19 +89,16 @@ void SceneSwitcher::SetStopped()
void SceneSwitcher::on_toggleStartButton_clicked()
{
if (switcher->th && switcher->th->isRunning())
{
if (switcher->th && switcher->th->isRunning()) {
switcher->Stop();
SetStopped();
}
else
{
} else {
switcher->Start();
SetStarted();
}
}
void SceneSwitcher::closeEvent(QCloseEvent*)
void SceneSwitcher::closeEvent(QCloseEvent *)
{
obs_frontend_save();
}

View File

@ -51,6 +51,8 @@ public:
public slots:
void on_switches_currentRowChanged(int idx);
void on_up_clicked();
void on_down_clicked();
void on_add_clicked();
void on_remove_clicked();
void on_noMatchDontSwitch_clicked();
@ -99,6 +101,8 @@ public slots:
void on_writePathLineEdit_textChanged(const QString &text);
void on_browseButton_2_clicked();
void on_executableUp_clicked();
void on_executableDown_clicked();
void on_executableAdd_clicked();
void on_executableRemove_clicked();
void on_executables_currentRowChanged(int idx);
@ -141,8 +145,9 @@ public slots:
* Windowtitle helper
********************************************************************************/
void GetWindowList(std::vector<std::string> &windows);
void GetWindowList(QStringList &windows); // Overloaded
void GetCurrentWindowTitle(std::string &title);
bool isFullscreen();
bool isFullscreen(std::string &title);
/********************************************************************************
* Screenregion helper
@ -158,7 +163,7 @@ int secondsSinceLastInput();
* Executable helper
********************************************************************************/
void GetProcessList(QStringList &processes);
bool isInFocus(const QString &exeToCheck);
bool isInFocus(const QString &executable);
/********************************************************************************
* Sceneswitch helper

View File

@ -44,13 +44,16 @@ struct WindowSceneSwitch {
string window;
OBSWeakSource transition;
bool fullscreen;
bool focus;
inline WindowSceneSwitch(OBSWeakSource scene_, const char *window_,
OBSWeakSource transition_, bool fullscreen_)
OBSWeakSource transition_, bool fullscreen_,
bool focus_)
: scene(scene_),
window(window_),
transition(transition_),
fullscreen(fullscreen_)
fullscreen(fullscreen_),
focus(focus_)
{
}
};
@ -254,7 +257,7 @@ typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch;
class SwitcherThread;
/********************************************************************************
* SwitcherData
* SwitcherData
********************************************************************************/
struct SwitcherData {
SwitcherThread *th = nullptr;

View File

@ -14,14 +14,26 @@ static inline bool WeakSourceValid(obs_weak_source_t *ws)
}
static inline QString MakeSwitchName(const QString &scene, const QString &value,
const QString &transition, bool fullscreen)
const QString &transition, bool fullscreen,
bool focus)
{
if (!fullscreen)
return QStringLiteral("[") + scene + QStringLiteral(", ") +
QString name = QStringLiteral("[") + scene + QStringLiteral(", ") +
transition + QStringLiteral("]: ") + value;
return QStringLiteral("[") + scene + QStringLiteral(", ") + transition +
QStringLiteral("]: ") + value +
QStringLiteral(" (only if window is fullscreen)");
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,
@ -34,7 +46,7 @@ static inline QString MakeSwitchNameExecutable(const QString &scene,
transition + QStringLiteral("]: ") + value;
return QStringLiteral("[") + scene + QStringLiteral(", ") + transition +
QStringLiteral("]: ") + value +
QStringLiteral(" (only if window is focused)");
QStringLiteral(" (only if focused)");
}
static inline QString MakeScreenRegionSwitchName(const QString &scene,

View File

@ -1,30 +1,29 @@
#include <obs-module.h>
#include "headers/advanced-scene-switcher.hpp"
void startHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pressed)
void startHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
bool pressed)
{
UNUSED_PARAMETER(data);
UNUSED_PARAMETER(hotkey);
if (pressed)
{
if (pressed) {
if (!(switcher->th && switcher->th->isRunning()))
switcher->Start();
}
obs_data_array* hotkeyData = obs_hotkey_save(id);
obs_data_array *hotkeyData = obs_hotkey_save(id);
if (hotkeyData != NULL)
{
char* path = obs_module_config_path("");
if (hotkeyData != NULL) {
char *path = obs_module_config_path("");
ofstream file;
file.open(string(path).append(START_HOTKEY_PATH), ofstream::trunc);
if (file.is_open())
{
file.open(string(path).append(START_HOTKEY_PATH),
ofstream::trunc);
if (file.is_open()) {
size_t num = obs_data_array_count(hotkeyData);
for (size_t i = 0; i < num; i++)
{
obs_data_t* data = obs_data_array_item(hotkeyData, i);
for (size_t i = 0; i < num; i++) {
obs_data_t *data =
obs_data_array_item(hotkeyData, i);
string temp = obs_data_get_json(data);
obs_data_release(data);
file << temp;
@ -36,30 +35,29 @@ void startHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pr
obs_data_array_release(hotkeyData);
}
void stopHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pressed)
void stopHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
bool pressed)
{
UNUSED_PARAMETER(data);
UNUSED_PARAMETER(hotkey);
if (pressed)
{
if (pressed) {
if (switcher->th && switcher->th->isRunning())
switcher->Stop();
}
obs_data_array* hotkeyData = obs_hotkey_save(id);
obs_data_array *hotkeyData = obs_hotkey_save(id);
if (hotkeyData != NULL)
{
char* path = obs_module_config_path("");
if (hotkeyData != NULL) {
char *path = obs_module_config_path("");
ofstream file;
file.open(string(path).append(STOP_HOTKEY_PATH), ofstream::trunc);
if (file.is_open())
{
file.open(string(path).append(STOP_HOTKEY_PATH),
ofstream::trunc);
if (file.is_open()) {
size_t num = obs_data_array_count(hotkeyData);
for (size_t i = 0; i < num; i++)
{
obs_data_t* data = obs_data_array_item(hotkeyData, i);
for (size_t i = 0; i < num; i++) {
obs_data_t *data =
obs_data_array_item(hotkeyData, i);
string temp = obs_data_get_json(data);
obs_data_release(data);
file << temp;
@ -71,32 +69,31 @@ void stopHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pre
obs_data_array_release(hotkeyData);
}
void startStopToggleHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pressed)
void startStopToggleHotkeyFunc(void *data, obs_hotkey_id id,
obs_hotkey_t *hotkey, bool pressed)
{
UNUSED_PARAMETER(data);
UNUSED_PARAMETER(hotkey);
if (pressed)
{
if (pressed) {
if (switcher->th && switcher->th->isRunning())
switcher->Stop();
else
switcher->Start();
}
obs_data_array* hotkeyData = obs_hotkey_save(id);
obs_data_array *hotkeyData = obs_hotkey_save(id);
if (hotkeyData != NULL)
{
char* path = obs_module_config_path("");
if (hotkeyData != NULL) {
char *path = obs_module_config_path("");
ofstream file;
file.open(string(path).append(TOGGLE_HOTKEY_PATH), ofstream::trunc);
if (file.is_open())
{
file.open(string(path).append(TOGGLE_HOTKEY_PATH),
ofstream::trunc);
if (file.is_open()) {
size_t num = obs_data_array_count(hotkeyData);
for (size_t i = 0; i < num; i++)
{
obs_data_t* data = obs_data_array_item(hotkeyData, i);
for (size_t i = 0; i < num; i++) {
obs_data_t *data =
obs_data_array_item(hotkeyData, i);
string temp = obs_data_get_json(data);
obs_data_release(data);
file << temp;
@ -111,16 +108,16 @@ void startStopToggleHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotke
string loadConfigFile(string filename)
{
ifstream settingsFile;
char* path = obs_module_config_path("");
char *path = obs_module_config_path("");
string value;
settingsFile.open(string(path).append(filename));
if (settingsFile.is_open())
{
if (settingsFile.is_open()) {
settingsFile.seekg(0, ios::end);
value.reserve(settingsFile.tellg());
settingsFile.seekg(0, ios::beg);
value.assign((istreambuf_iterator<char>(settingsFile)), istreambuf_iterator<char>());
value.assign((istreambuf_iterator<char>(settingsFile)),
istreambuf_iterator<char>());
settingsFile.close();
}
bfree(path);
@ -130,10 +127,9 @@ string loadConfigFile(string filename)
void loadKeybinding(obs_hotkey_id hotkeyId, string path)
{
string bindings = loadConfigFile(path);
if (!bindings.empty())
{
obs_data_array_t* hotkeyData = obs_data_array_create();
obs_data_t* data = obs_data_create_from_json(bindings.c_str());
if (!bindings.empty()) {
obs_data_array_t *hotkeyData = obs_data_array_create();
obs_data_t *data = obs_data_create_from_json(bindings.c_str());
obs_data_array_insert(hotkeyData, 0, data);
obs_data_release(data);
obs_hotkey_load(hotkeyId, hotkeyData);

View File

@ -1,6 +1,7 @@
#include "headers/advanced-scene-switcher.hpp"
void SwitcherData::checkIdleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition)
void SwitcherData::checkIdleSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
if (!idleData.idleEnable)
return;
@ -11,44 +12,36 @@ void SwitcherData::checkIdleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSou
GetCurrentWindowTitle(title);
//lock.lock();
for (string& window : ignoreIdleWindows)
{
if (window == title)
{
for (string &window : ignoreIdleWindows) {
if (window == title) {
ignoreIdle = true;
break;
}
}
if (!ignoreIdle)
{
for (string& window : ignoreIdleWindows)
{
try
{
bool matches = regex_match(title, regex(window));
if (matches)
{
if (!ignoreIdle) {
for (string &window : ignoreIdleWindows) {
try {
bool matches =
regex_match(title, regex(window));
if (matches) {
ignoreIdle = true;
break;
}
}
catch (const regex_error&)
{
} catch (const regex_error &) {
}
}
}
if (!ignoreIdle && secondsSinceLastInput() > idleData.time)
{
if (!ignoreIdle && secondsSinceLastInput() > idleData.time) {
if (idleData.alreadySwitched)
return;
scene = (idleData.usePreviousScene) ? previousScene : idleData.scene;
scene = (idleData.usePreviousScene) ? previousScene
: idleData.scene;
transition = idleData.transition;
match = true;
idleData.alreadySwitched = true;
}
else
} else
idleData.alreadySwitched = false;
}
@ -58,16 +51,13 @@ void SceneSwitcher::on_idleCheckBox_stateChanged(int state)
return;
lock_guard<mutex> lock(switcher->m);
if (!state)
{
if (!state) {
ui->idleScenes->setDisabled(true);
ui->idleSpinBox->setDisabled(true);
ui->idleTransitions->setDisabled(true);
switcher->idleData.idleEnable = false;
}
else
{
} else {
ui->idleScenes->setDisabled(false);
ui->idleSpinBox->setDisabled(false);
ui->idleTransitions->setDisabled(false);
@ -79,18 +69,17 @@ void SceneSwitcher::on_idleCheckBox_stateChanged(int state)
}
}
void SceneSwitcher::UpdateIdleDataTransition(const QString& name)
void SceneSwitcher::UpdateIdleDataTransition(const QString &name)
{
obs_weak_source_t* transition = GetWeakTransitionByQString(name);
obs_weak_source_t *transition = GetWeakTransitionByQString(name);
switcher->idleData.transition = transition;
}
void SceneSwitcher::UpdateIdleDataScene(const QString& name)
void SceneSwitcher::UpdateIdleDataScene(const QString &name)
{
switcher->idleData.usePreviousScene = (name == PREVIOUS_SCENE_NAME);
obs_source_t* scene = obs_get_source_by_name(name.toUtf8().constData());
obs_weak_source_t* ws = obs_source_get_weak_source(scene);
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
obs_weak_source_t *ws = obs_source_get_weak_source(scene);
switcher->idleData.scene = ws;
@ -98,7 +87,7 @@ void SceneSwitcher::UpdateIdleDataScene(const QString& name)
obs_source_release(scene);
}
void SceneSwitcher::on_idleTransitions_currentTextChanged(const QString& text)
void SceneSwitcher::on_idleTransitions_currentTextChanged(const QString &text)
{
if (loading)
return;
@ -107,7 +96,7 @@ void SceneSwitcher::on_idleTransitions_currentTextChanged(const QString& text)
UpdateIdleDataTransition(text);
}
void SceneSwitcher::on_idleScenes_currentTextChanged(const QString& text)
void SceneSwitcher::on_idleScenes_currentTextChanged(const QString &text)
{
if (loading)
return;
@ -131,15 +120,13 @@ void SceneSwitcher::on_ignoreIdleWindows_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->ignoreIdleWindows->item(idx);
QListWidgetItem *item = ui->ignoreIdleWindows->item(idx);
QString window = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& w : switcher->ignoreIdleWindows)
{
if (window.compare(w.c_str()) == 0)
{
for (auto &w : switcher->ignoreIdleWindows) {
if (window.compare(w.c_str()) == 0) {
ui->ignoreIdleWindowsWindows->setCurrentText(w.c_str());
break;
}
@ -155,22 +142,24 @@ void SceneSwitcher::on_ignoreIdleAdd_clicked()
QVariant v = QVariant::fromValue(windowName);
QList<QListWidgetItem*> items = ui->ignoreIdleWindows->findItems(windowName, Qt::MatchExactly);
QList<QListWidgetItem *> items =
ui->ignoreIdleWindows->findItems(windowName, Qt::MatchExactly);
if (items.size() == 0)
{
QListWidgetItem* item = new QListWidgetItem(windowName, ui->ignoreIdleWindows);
if (items.size() == 0) {
QListWidgetItem *item =
new QListWidgetItem(windowName, ui->ignoreIdleWindows);
item->setData(Qt::UserRole, v);
lock_guard<mutex> lock(switcher->m);
switcher->ignoreIdleWindows.emplace_back(windowName.toUtf8().constData());
switcher->ignoreIdleWindows.emplace_back(
windowName.toUtf8().constData());
ui->ignoreIdleWindows->sortItems();
}
}
void SceneSwitcher::on_ignoreIdleRemove_clicked()
{
QListWidgetItem* item = ui->ignoreIdleWindows->currentItem();
QListWidgetItem *item = ui->ignoreIdleWindows->currentItem();
if (!item)
return;
@ -178,14 +167,12 @@ void SceneSwitcher::on_ignoreIdleRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& windows = switcher->ignoreIdleWindows;
auto &windows = switcher->ignoreIdleWindows;
for (auto it = windows.begin(); it != windows.end(); ++it)
{
auto& s = *it;
for (auto it = windows.begin(); it != windows.end(); ++it) {
auto &s = *it;
if (s == windowName.toUtf8().constData())
{
if (s == windowName.toUtf8().constData()) {
windows.erase(it);
break;
}
@ -195,18 +182,16 @@ void SceneSwitcher::on_ignoreIdleRemove_clicked()
delete item;
}
int SceneSwitcher::IgnoreIdleWindowsFindByData(const QString& window)
int SceneSwitcher::IgnoreIdleWindowsFindByData(const QString &window)
{
int count = ui->ignoreIdleWindows->count();
int idx = -1;
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->ignoreIdleWindows->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->ignoreIdleWindows->item(i);
QString itemRegion = item->data(Qt::UserRole).toString();
if (itemRegion == window)
{
if (itemRegion == window) {
idx = i;
break;
}

View File

@ -18,7 +18,7 @@
using namespace std;
static Display* xdisplay = 0;
static Display *xdisplay = 0;
Display *disp()
{
@ -40,31 +40,22 @@ void cleanupDisplay()
static bool ewmhIsSupported()
{
Display *display = disp();
Atom netSupportingWmCheck = XInternAtom(display,
"_NET_SUPPORTING_WM_CHECK", true);
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);
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];
ewmh_window = ((Window *)data)[0];
}
if (data) {
XFree(data);
@ -73,21 +64,12 @@ static bool ewmhIsSupported()
}
if (ewmh_window) {
status = XGetWindowProperty(
display,
ewmh_window,
netSupportingWmCheck,
0L,
1L,
false,
XA_WINDOW,
&actualType,
&format,
&num,
&bytes,
&data);
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 != ((Window *)data)[0]) {
ewmh_window = 0;
}
if (status == Success && data) {
@ -98,6 +80,30 @@ static bool ewmhIsSupported()
return ewmh_window != 0;
}
static QStringList getStates(Window window)
{
QStringList states;
if (!ewmhIsSupported())
return states;
Atom wmState = XInternAtom(disp(), "_NET_WM_STATE", true), type;
int format;
unsigned long num, bytes;
unsigned char *data;
int status = XGetWindowProperty(disp(), window, wmState, 0, ~0L, false,
AnyPropertyType, &type, &format, &num,
&bytes, &data);
if (status == Success)
for (unsigned long i = 0; i < num; i++)
states.append(QString(
XGetAtomName(disp(), ((Atom *)data)[i])));
return states;
}
static std::vector<Window> getTopLevelWindows()
{
std::vector<Window> res;
@ -112,24 +118,15 @@ static std::vector<Window> getTopLevelWindows()
Atom actualType;
int format;
unsigned long num, bytes;
Window* data = 0;
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);
int status = XGetWindowProperty(disp(), rootWin, netClList, 0L,
~0L, false, AnyPropertyType,
&actualType, &format, &num,
&bytes, (uint8_t **)&data);
if (status != Success) {
continue;
@ -148,19 +145,22 @@ static std::string GetWindowTitle(size_t i)
{
Window w = getTopLevelWindows().at(i);
std::string windowTitle;
char* name;
char *name;
XTextProperty text;
int status = XGetWMName(disp(), w, &text);
name = reinterpret_cast<char*>(text.value);
if (status >= Success && name != nullptr)
{
int status = XGetTextProperty(
disp(), w, &text, XInternAtom(disp(), "_NET_WM_NAME", true));
if (status == 0)
status = XGetTextProperty(disp(), w, &text,
XInternAtom(disp(), "WM_NAME", true));
name = reinterpret_cast<char *>(text.value);
if (status != 0 && name != nullptr) {
std::string str(name);
windowTitle = str;
XFree(name);
}
XFree(name);
return windowTitle;
}
@ -168,12 +168,23 @@ void GetWindowList(vector<string> &windows)
{
windows.resize(0);
for (size_t i = 0; i < getTopLevelWindows().size(); ++i){
for (size_t i = 0; i < getTopLevelWindows().size(); ++i) {
if (GetWindowTitle(i) != "")
windows.emplace_back(GetWindowTitle(i));
}
}
// Overloaded
void GetWindowList(QStringList &windows)
{
windows.clear();
for (size_t i = 0; i < getTopLevelWindows().size(); ++i) {
if (GetWindowTitle(i) != "")
windows << QString::fromStdString(GetWindowTitle(i));
}
}
void GetCurrentWindowTitle(string &title)
{
if (!ewmhIsSupported()) {
@ -184,35 +195,34 @@ void GetCurrentWindowTitle(string &title)
Atom actualType;
int format;
unsigned long num, bytes;
Window* data = 0;
char* name;
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 xstatus = XGetWindowProperty(disp(), rootWin, active, 0L, ~0L,
false, AnyPropertyType, &actualType,
&format, &num, &bytes,
(uint8_t **)&data);
int status = 0;
XTextProperty text;
int status = XGetWMName(disp(), data[0], &text);
name = reinterpret_cast<char*>(text.value);
if (xstatus == Success) {
status = XGetTextProperty(disp(), data[0], &text,
XInternAtom(disp(), "_NET_WM_NAME",
true));
if (status == 0)
status = XGetTextProperty(disp(), data[0], &text,
XInternAtom(disp(), "WM_NAME",
true));
}
name = reinterpret_cast<char *>(text.value);
if (status >= Success && name != nullptr) {
if (status != 0 && name != nullptr) {
std::string str(name);
title = str;
XFree(name);
}
XFree(name);
}
pair<int, int> getCursorPos()
@ -231,95 +241,108 @@ pair<int, int> getCursorPos()
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);
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()
bool isFullscreen(std::string &title)
{
if (!ewmhIsSupported()) {
if (!ewmhIsSupported())
return false;
// Find switch in top level windows
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 fullscreen
if (equals || matches) {
QStringList states = getStates(window);
if (!states.isEmpty()) {
// 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));
}
break;
}
}
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;
return 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){
for (size_t i = 0; i < getTopLevelWindows().size(); ++i) {
string s = GetWindowTitle(i);
if (s != "")
processes << QString::fromStdString(s);
}
}
bool isInFocus(const QString &exeToCheck)
bool isInFocus(const QString &executable)
{
string curWindow;
GetCurrentWindowTitle(curWindow);
string current;
GetCurrentWindowTitle(current);
return (QString::compare(
QString::fromStdString(curWindow),
exeToCheck,
Qt::CaseInsensitive) == 0) ? true : false;
// True if executable switch equals current window
bool equals = (executable.toStdString() == current);
// True if executable switch matches current window
bool matches = QString::fromStdString(current).contains(
QRegularExpression(executable));
return (equals || matches);
}
int secondsSinceLastInput()
{
time_t idle_time;
static XScreenSaverInfo *mit_info;
Display *display;
int screen;
time_t idle_time;
static XScreenSaverInfo *mit_info;
Display *display;
int screen;
mit_info = XScreenSaverAllocInfo();
mit_info = XScreenSaverAllocInfo();
if((display=XOpenDisplay(NULL)) == NULL)
{
return(-1);
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);
screen = DefaultScreen(display);
XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info);
idle_time = (mit_info->idle) / 1000;
XFree(mit_info);
XCloseDisplay(display);
return idle_time;
return idle_time;
}

View File

@ -6,141 +6,232 @@
#include <util/platform.h>
#include "../headers/advanced-scene-switcher.hpp"
void GetWindowList(vector<string> &windows)
{
windows.resize(0);
windows.resize(0);
@autoreleasepool {
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSArray *array = [ws runningApplications];
for (NSRunningApplication *app in array) {
NSString *name = app.localizedName;
if (!name)
continue;
@autoreleasepool {
NSMutableArray *apps =
(__bridge NSMutableArray *)CGWindowListCopyWindowInfo(
kCGWindowListOptionAll, kCGNullWindowID);
for (NSDictionary *app in apps) {
// Construct string from NSString accounting for nil
string name([[app objectForKey:@"kCGWindowName"]
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
string owner([[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
const char *str = name.UTF8String;
if (str && *str)
windows.emplace_back(str);
}
}
// Check if name exists
if (!name.empty() &&
find(windows.begin(), windows.end(), name) ==
windows.end())
windows.emplace_back(name);
// Check if owner exists
else if (!owner.empty() &&
find(windows.begin(), windows.end(), owner) ==
windows.end())
windows.emplace_back(owner);
}
}
}
// Overloaded
void GetWindowList(QStringList &windows)
{
windows.clear();
@autoreleasepool {
NSMutableArray *apps =
(__bridge NSMutableArray *)CGWindowListCopyWindowInfo(
kCGWindowListOptionAll, kCGNullWindowID);
for (NSDictionary *app in apps) {
// Construct string from NSString accounting for nil
string name([[app objectForKey:@"kCGWindowName"]
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
string owner([[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
// Check if name exists
if (!name.empty() &&
!windows.contains(QString::fromStdString(name)))
windows << QString::fromStdString(name);
// Check if owner exists
else if (!owner.empty() &&
!windows.contains(
QString::fromStdString(name)))
windows << QString::fromStdString(owner);
}
}
}
void GetCurrentWindowTitle(string &title)
{
title.resize(0);
title.resize(0);
@autoreleasepool {
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSRunningApplication *app = [ws frontmostApplication];
if (app) {
NSString *name = app.localizedName;
if (!name)
return;
@autoreleasepool {
NSMutableArray *apps =
(__bridge NSMutableArray *)CGWindowListCopyWindowInfo(
kCGWindowListOptionOnScreenOnly,
kCGNullWindowID);
for (NSDictionary *app in apps) {
int layer =
[[app objectForKey:@"kCGWindowLayer"] intValue];
// True if window is frontmost
if (layer == 0) {
// Construct string from NSString accounting for nil
string name(
[[app objectForKey:@"kCGWindowName"]
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
string owner(
[[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
const char *str = name.UTF8String;
if (str && *str)
title = str;
}
}
if (!name.empty())
title = name;
else if (!owner.empty())
title = owner;
break;
}
}
}
}
pair<int, int> getCursorPos() {
pair<int, int> pos(0, 0);
CGEventRef event = CGEventCreate(NULL);
CGPoint cursorPos = CGEventGetLocation(event);
CFRelease(event);
pos.first = cursorPos.x;
pos.second = cursorPos.y;
return pos;
}
pair<int, int> getCursorPos()
{
pair<int, int> pos(0, 0);
CGEventRef event = CGEventCreate(NULL);
CGPoint cursorPos = CGEventGetLocation(event);
CFRelease(event);
pos.first = cursorPos.x;
pos.second = cursorPos.y;
return pos;
}
bool isFullscreen() {
@autoreleasepool {
AXValueRef temp;
CGSize windowSize;
CGPoint windowPosition;
AXUIElementRef frontMostApp;
AXUIElementRef frontMostWindow;
bool isFullscreen(string &title)
{
// Check for match
@autoreleasepool {
NSArray *screens = [NSScreen screens];
NSMutableArray *apps =
(__bridge NSMutableArray *)CGWindowListCopyWindowInfo(
kCGWindowListOptionAll, kCGNullWindowID);
for (NSDictionary *app in apps) {
// Construct string from NSString accounting for nil
string name([[app objectForKey:@"kCGWindowName"]
UTF8String],
[[app objectForKey:@"kCGWindowName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
string owner([[app objectForKey:@"kCGWindowOwnerName"]
UTF8String],
[[app objectForKey:@"kCGWindowOwnerName"]
lengthOfBytesUsingEncoding:
NSUTF8StringEncoding]);
pid_t pid;
ProcessSerialNumber psn;
@try {
GetFrontProcess(&psn);
GetProcessPID(&psn, &pid);
frontMostApp = AXUIElementCreateApplication(pid);
// True if switch equals app
bool equals = (title == name || title == owner);
// True if switch matches app
bool matches = (QString::fromStdString(name).contains(
QRegularExpression(
QString::fromStdString(
title))) ||
QString::fromStdString(owner).contains(
QRegularExpression(
QString::fromStdString(
title))));
AXUIElementCopyAttributeValue(
frontMostApp, kAXFocusedWindowAttribute, (CFTypeRef *)&frontMostWindow);
// If found, check if fullscreen
if (equals || matches) {
// Get window bounds
NSRect bounds;
CGRectMakeWithDictionaryRepresentation(
(CFDictionaryRef)[app
objectForKey:@"kCGWindowBounds"],
&bounds);
// Get the window size and position
AXUIElementCopyAttributeValue(
frontMostWindow, kAXSizeAttribute, (CFTypeRef *)&temp);
AXValueGetValue(temp, kAXValueTypeCGSize, &windowSize);
CFRelease(temp);
// Compare to screen bounds
for (NSScreen *screen in screens) {
NSRect frame = [screen visibleFrame];
AXUIElementCopyAttributeValue(
frontMostWindow, kAXPositionAttribute, (CFTypeRef *)&temp);
AXValueGetValue(temp, kAXValueTypeCGPoint, &windowPosition);
CFRelease(temp);
// True if flipped window origin equals screen origin
bool origin =
(bounds.origin.x ==
frame.origin.x &&
([screens[0] visibleFrame]
.size.height -
frame.size.height -
bounds.origin.y ==
frame.origin.y));
// True if window size equals screen size
bool size = NSEqualSizes(bounds.size,
frame.size);
CGRect screenBound = CGDisplayBounds(CGMainDisplayID());
CGSize screenSize = screenBound.size;
if (origin && size)
return true;
}
}
}
}
if((windowSize.width == screenSize.width) && (windowSize.height == screenSize.height) &&
(windowPosition.x == 0) && (windowPosition.y == 0))
return true;
}
@catch (...) {
// deal with the exception
}
@catch (NSException *exception) {
// deal with the exception
}
}
return false;
return false;
}
int secondsSinceLastInput()
{
double time = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType) + 0.5;
return (int) time;
double time = CGEventSourceSecondsSinceLastEventType(
kCGEventSourceStateCombinedSessionState,
kCGAnyInputEventType) +
0.5;
return (int)time;
}
void GetProcessList(QStringList& list)
void GetProcessList(QStringList &list)
{
list.clear();
@autoreleasepool {
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSArray *array = [ws runningApplications];
for (NSRunningApplication *app in array) {
NSString *name = app.localizedName;
if (!name)
continue;
const char *str = name.UTF8String;
if (str && *str)
list << (str);
}
}
list.clear();
@autoreleasepool {
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSArray *array = [ws runningApplications];
for (NSRunningApplication *app in array) {
NSString *name = app.localizedName;
if (!name)
continue;
const char *str = name.UTF8String;
if (str && *str)
list << (str);
}
}
}
bool isInFocus(QString const& appQName)
bool isInFocus(const QString &executable)
{
QByteArray ba = appQName.toLocal8Bit();
const char * appName = ba.data();
@autoreleasepool {
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSRunningApplication *app = [ws frontmostApplication];
if (app) {
NSString *name = app.localizedName;
if (!name)
return false;
const char *str = name.UTF8String;
return (str && *str && strcmp(appName,str) == 0 )? true : false;
}
}
return false;
string current;
GetCurrentWindowTitle(current);
// True if executable switch equals current window
bool equals = (executable.toStdString() == current);
// True if executable switch matches current window
bool matches = QString::fromStdString(current).contains(
QRegularExpression(executable));
return (equals || matches);
}

View File

@ -10,11 +10,12 @@ void SceneSwitcher::on_pauseScenesAdd_clicked()
OBSWeakSource source = GetWeakSourceByQString(sceneName);
QVariant v = QVariant::fromValue(sceneName);
QList<QListWidgetItem*> items = ui->pauseScenes->findItems(sceneName, Qt::MatchExactly);
QList<QListWidgetItem *> items =
ui->pauseScenes->findItems(sceneName, Qt::MatchExactly);
if (items.size() == 0)
{
QListWidgetItem* item = new QListWidgetItem(sceneName, ui->pauseScenes);
if (items.size() == 0) {
QListWidgetItem *item =
new QListWidgetItem(sceneName, ui->pauseScenes);
item->setData(Qt::UserRole, v);
lock_guard<mutex> lock(switcher->m);
@ -25,7 +26,7 @@ void SceneSwitcher::on_pauseScenesAdd_clicked()
void SceneSwitcher::on_pauseScenesRemove_clicked()
{
QListWidgetItem* item = ui->pauseScenes->currentItem();
QListWidgetItem *item = ui->pauseScenes->currentItem();
if (!item)
return;
@ -33,14 +34,12 @@ void SceneSwitcher::on_pauseScenesRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->pauseScenesSwitches;
auto &switches = switcher->pauseScenesSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s == GetWeakSourceByQString(pauseScene))
{
if (s == GetWeakSourceByQString(pauseScene)) {
switches.erase(it);
break;
}
@ -59,22 +58,24 @@ void SceneSwitcher::on_pauseWindowsAdd_clicked()
QVariant v = QVariant::fromValue(windowName);
QList<QListWidgetItem*> items = ui->pauseWindows->findItems(windowName, Qt::MatchExactly);
QList<QListWidgetItem *> items =
ui->pauseWindows->findItems(windowName, Qt::MatchExactly);
if (items.size() == 0)
{
QListWidgetItem* item = new QListWidgetItem(windowName, ui->pauseWindows);
if (items.size() == 0) {
QListWidgetItem *item =
new QListWidgetItem(windowName, ui->pauseWindows);
item->setData(Qt::UserRole, v);
lock_guard<mutex> lock(switcher->m);
switcher->pauseWindowsSwitches.emplace_back(windowName.toUtf8().constData());
switcher->pauseWindowsSwitches.emplace_back(
windowName.toUtf8().constData());
ui->pauseWindows->sortItems();
}
}
void SceneSwitcher::on_pauseWindowsRemove_clicked()
{
QListWidgetItem* item = ui->pauseWindows->currentItem();
QListWidgetItem *item = ui->pauseWindows->currentItem();
if (!item)
return;
@ -82,14 +83,12 @@ void SceneSwitcher::on_pauseWindowsRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->pauseWindowsSwitches;
auto &switches = switcher->pauseWindowsSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s == windowName.toUtf8().constData())
{
if (s == windowName.toUtf8().constData()) {
switches.erase(it);
break;
}
@ -106,16 +105,14 @@ void SceneSwitcher::on_pauseScenes_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->pauseScenes->item(idx);
QListWidgetItem *item = ui->pauseScenes->item(idx);
QString scene = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->pauseScenesSwitches)
{
for (auto &s : switcher->pauseScenesSwitches) {
string name = GetWeakSourceName(s);
if (scene.compare(name.c_str()) == 0)
{
if (scene.compare(name.c_str()) == 0) {
ui->pauseScenesScenes->setCurrentText(name.c_str());
break;
}
@ -129,33 +126,29 @@ void SceneSwitcher::on_pauseWindows_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->pauseWindows->item(idx);
QListWidgetItem *item = ui->pauseWindows->item(idx);
QString window = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->pauseWindowsSwitches)
{
if (window.compare(s.c_str()) == 0)
{
for (auto &s : switcher->pauseWindowsSwitches) {
if (window.compare(s.c_str()) == 0) {
ui->pauseWindowsWindows->setCurrentText(s.c_str());
break;
}
}
}
int SceneSwitcher::PauseScenesFindByData(const QString& scene)
int SceneSwitcher::PauseScenesFindByData(const QString &scene)
{
int count = ui->pauseScenes->count();
int idx = -1;
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->pauseScenes->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->pauseScenes->item(i);
QString itemRegion = item->data(Qt::UserRole).toString();
if (itemRegion == scene)
{
if (itemRegion == scene) {
idx = i;
break;
}
@ -164,18 +157,16 @@ int SceneSwitcher::PauseScenesFindByData(const QString& scene)
return idx;
}
int SceneSwitcher::PauseWindowsFindByData(const QString& window)
int SceneSwitcher::PauseWindowsFindByData(const QString &window)
{
int count = ui->pauseWindows->count();
int idx = -1;
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->pauseWindows->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->pauseWindows->item(i);
QString itemRegion = item->data(Qt::UserRole).toString();
if (itemRegion == window)
{
if (itemRegion == window) {
idx = i;
break;
}
@ -187,13 +178,11 @@ int SceneSwitcher::PauseWindowsFindByData(const QString& window)
bool SwitcherData::checkPause()
{
bool pause = false;
obs_source_t* currentSource = obs_frontend_get_current_scene();
obs_weak_source_t* ws = obs_source_get_weak_source(currentSource);
obs_source_t *currentSource = obs_frontend_get_current_scene();
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
for (OBSWeakSource& s : pauseScenesSwitches)
{
if (s == ws)
{
for (OBSWeakSource &s : pauseScenesSwitches) {
if (s == ws) {
pause = true;
break;
}
@ -202,39 +191,31 @@ bool SwitcherData::checkPause()
obs_weak_source_release(ws);
string title;
if (!pause)
{
if (!pause) {
//lock.unlock();
GetCurrentWindowTitle(title);
//lock.lock();
for (string& window : pauseWindowsSwitches)
{
if (window == title)
{
for (string &window : pauseWindowsSwitches) {
if (window == title) {
pause = true;
break;
}
}
}
if (!pause)
{
if (!pause) {
//lock.unlock();
GetCurrentWindowTitle(title);
//lock.lock();
for (string& window : pauseWindowsSwitches)
{
try
{
bool matches = regex_match(title, regex(window));
if (matches)
{
for (string &window : pauseWindowsSwitches) {
try {
bool matches =
regex_match(title, regex(window));
if (matches) {
pause = true;
break;
}
}
catch (const regex_error&)
{
} catch (const regex_error &) {
}
}
}

View File

@ -3,14 +3,14 @@
void SceneSwitcher::on_threadPriority_currentTextChanged(const QString &text)
{
if (loading || ui->threadPriority->count() != switcher->threadPriorities.size())
if (loading ||
ui->threadPriority->count() != switcher->threadPriorities.size())
return;
lock_guard<mutex> lock(switcher->m);
for (auto p : switcher->threadPriorities) {
if (p.name == text.toUtf8()
.constData()) {
if (p.name == text.toUtf8().constData()) {
switcher->threadPriority = p.value;
break;
}

View File

@ -8,17 +8,16 @@ void SceneSwitcher::on_randomScenesList_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->randomScenesList->item(idx);
QListWidgetItem *item = ui->randomScenesList->item(idx);
QString randomSceneStr = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->randomSwitches)
{
if (randomSceneStr.compare(s.randomSwitchStr.c_str()) == 0)
{
for (auto &s : switcher->randomSwitches) {
if (randomSceneStr.compare(s.randomSwitchStr.c_str()) == 0) {
QString sceneName = GetWeakSourceName(s.scene).c_str();
QString transitionName = GetWeakSourceName(s.transition).c_str();
QString transitionName =
GetWeakSourceName(s.transition).c_str();
ui->randomScenes->setCurrentText(sceneName);
ui->randomSpinBox->setValue(s.delay);
ui->randomTransitions->setCurrentText(transitionName);
@ -27,13 +26,12 @@ void SceneSwitcher::on_randomScenesList_currentRowChanged(int idx)
}
}
int SceneSwitcher::randomFindByData(const QString& randomStr)
int SceneSwitcher::randomFindByData(const QString &randomStr)
{
int count = ui->randomScenesList->count();
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->randomScenesList->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->randomScenesList->item(i);
QString str = item->data(Qt::UserRole).toString();
if (str == randomStr)
@ -49,42 +47,38 @@ void SceneSwitcher::on_randomAdd_clicked()
QString transitionName = ui->randomTransitions->currentText();
double delay = ui->randomSpinBox->value();
if (sceneName.isEmpty())
return;
OBSWeakSource source = GetWeakSourceByQString(sceneName);
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QString text = MakeRandomSwitchName(sceneName, transitionName, delay);
QVariant v = QVariant::fromValue(text);
int idx = randomFindByData(text);
if (idx == -1)
{
if (idx == -1) {
lock_guard<mutex> lock(switcher->m);
switcher->randomSwitches.emplace_back(
source, transition, delay, text.toUtf8().constData());
QListWidgetItem* item = new QListWidgetItem(text, ui->randomScenesList);
QListWidgetItem *item =
new QListWidgetItem(text, ui->randomScenesList);
item->setData(Qt::UserRole, v);
}
else
{
QListWidgetItem* item = ui->randomScenesList->item(idx);
} else {
QListWidgetItem *item = ui->randomScenesList->item(idx);
item->setText(text);
{
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->randomSwitches)
{
if (s.scene == source)
{
for (auto &s : switcher->randomSwitches) {
if (s.scene == source) {
s.delay = delay;
s.transition = transition;
s.randomSwitchStr = text.toUtf8().constData();;
s.randomSwitchStr =
text.toUtf8().constData();
;
break;
}
}
@ -96,7 +90,7 @@ void SceneSwitcher::on_randomAdd_clicked()
void SceneSwitcher::on_randomRemove_clicked()
{
QListWidgetItem* item = ui->randomScenesList->currentItem();
QListWidgetItem *item = ui->randomScenesList->currentItem();
if (!item)
return;
@ -104,14 +98,12 @@ void SceneSwitcher::on_randomRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->randomSwitches;
auto &switches = switcher->randomSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.randomSwitchStr == text)
{
if (s.randomSwitchStr == text) {
switches.erase(it);
break;
}
@ -121,17 +113,17 @@ void SceneSwitcher::on_randomRemove_clicked()
delete item;
}
void SwitcherData::checkRandom(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, int& delay)
void SwitcherData::checkRandom(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition, int &delay)
{
if (randomSwitches.size() == 0)
return;
vector<RandomSwitch> rs (randomSwitches);
vector<RandomSwitch> rs(randomSwitches);
std::random_device rng;
std::mt19937 urng(rng());
std::shuffle(rs.begin(), rs.end(), urng);
for (RandomSwitch& r : rs)
{
for (RandomSwitch &r : rs) {
if (r.scene == lastRandomScene)
continue;
scene = r.scene;

View File

@ -22,14 +22,15 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
OBSWeakSource source2 = GetWeakSourceByQString(scene2Name);
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QString text = MakeSceneRoundTripSwitchName(scene1Name, scene2Name, transitionName, delay);
QString text = MakeSceneRoundTripSwitchName(scene1Name, scene2Name,
transitionName, delay);
QVariant v = QVariant::fromValue(text);
int idx = SceneRoundTripFindByData(scene1Name);
if (idx == -1)
{
QListWidgetItem* item = new QListWidgetItem(text, ui->sceneRoundTrips);
if (idx == -1) {
QListWidgetItem *item =
new QListWidgetItem(text, ui->sceneRoundTrips);
item->setData(Qt::UserRole, v);
lock_guard<mutex> lock(switcher->m);
@ -37,23 +38,22 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
source1, source2, transition, int(delay * 1000),
(scene2Name == QString(PREVIOUS_SCENE_NAME)),
text.toUtf8().constData());
}
else
{
QListWidgetItem* item = ui->sceneRoundTrips->item(idx);
} else {
QListWidgetItem *item = ui->sceneRoundTrips->item(idx);
item->setText(text);
{
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->sceneRoundTripSwitches)
{
if (s.scene1 == source1)
{
for (auto &s : switcher->sceneRoundTripSwitches) {
if (s.scene1 == source1) {
s.scene2 = source2;
s.delay = int(delay * 1000);
s.transition = transition;
s.usePreviousScene = (scene2Name == QString(PREVIOUS_SCENE_NAME));
s.sceneRoundTripStr = text.toUtf8().constData();
s.usePreviousScene =
(scene2Name ==
QString(PREVIOUS_SCENE_NAME));
s.sceneRoundTripStr =
text.toUtf8().constData();
break;
}
}
@ -65,7 +65,7 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
void SceneSwitcher::on_sceneRoundTripRemove_clicked()
{
QListWidgetItem* item = ui->sceneRoundTrips->currentItem();
QListWidgetItem *item = ui->sceneRoundTrips->currentItem();
if (!item)
return;
@ -73,14 +73,12 @@ void SceneSwitcher::on_sceneRoundTripRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->sceneRoundTripSwitches;
auto &switches = switcher->sceneRoundTripSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.sceneRoundTripStr == text)
{
if (s.sceneRoundTripStr == text) {
switches.erase(it);
break;
}
@ -96,22 +94,19 @@ void SceneSwitcher::on_autoStopSceneCheckBox_stateChanged(int state)
return;
lock_guard<mutex> lock(switcher->m);
if (!state)
{
if (!state) {
ui->autoStopScenes->setDisabled(true);
switcher->autoStopEnable = false;
}
else
{
} else {
ui->autoStopScenes->setDisabled(false);
switcher->autoStopEnable = true;
}
}
void SceneSwitcher::UpdateAutoStopScene(const QString& name)
void SceneSwitcher::UpdateAutoStopScene(const QString &name)
{
obs_source_t* scene = obs_get_source_by_name(name.toUtf8().constData());
obs_weak_source_t* ws = obs_source_get_weak_source(scene);
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
obs_weak_source_t *ws = obs_source_get_weak_source(scene);
switcher->autoStopScene = ws;
@ -119,7 +114,7 @@ void SceneSwitcher::UpdateAutoStopScene(const QString& name)
obs_source_release(scene);
}
void SceneSwitcher::on_autoStopScenes_currentTextChanged(const QString& text)
void SceneSwitcher::on_autoStopScenes_currentTextChanged(const QString &text)
{
if (loading)
return;
@ -131,23 +126,30 @@ void SceneSwitcher::on_autoStopScenes_currentTextChanged(const QString& text)
void SceneSwitcher::on_sceneRoundTripSave_clicked()
{
QString directory = QFileDialog::getSaveFileName(
this, tr("Save Scene Round Trip to file ..."), QDir::currentPath(), tr("Text files (*.txt)"));
if (!directory.isEmpty())
{
this, tr("Save Scene Round Trip to file ..."),
QDir::currentPath(), tr("Text files (*.txt)"));
if (!directory.isEmpty()) {
QFile file(directory);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;
QTextStream out(&file);
for (SceneRoundTripSwitch s : switcher->sceneRoundTripSwitches)
{
out << QString::fromStdString(GetWeakSourceName(s.scene1)) << "\n";
for (SceneRoundTripSwitch s :
switcher->sceneRoundTripSwitches) {
out << QString::fromStdString(
GetWeakSourceName(s.scene1))
<< "\n";
if (s.usePreviousScene)
out << (PREVIOUS_SCENE_NAME) << "\n";
else
out << QString::fromStdString(GetWeakSourceName(s.scene2)) << "\n";
out << QString::fromStdString(
GetWeakSourceName(s.scene2))
<< "\n";
out << s.delay << "\n";
out << QString::fromStdString(s.sceneRoundTripStr) << "\n";
out << QString::fromStdString(GetWeakSourceName(s.transition)) << "\n";
out << QString::fromStdString(s.sceneRoundTripStr)
<< "\n";
out << QString::fromStdString(
GetWeakSourceName(s.transition))
<< "\n";
}
}
}
@ -157,9 +159,9 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked()
lock_guard<mutex> lock(switcher->m);
QString directory = QFileDialog::getOpenFileName(
this, tr("Select a file to read Scene Round Trip from ..."), QDir::currentPath(), tr("Text files (*.txt)"));
if (!directory.isEmpty())
{
this, tr("Select a file to read Scene Round Trip from ..."),
QDir::currentPath(), tr("Text files (*.txt)"));
if (!directory.isEmpty()) {
QFile file(directory);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
@ -169,26 +171,34 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked()
vector<SceneRoundTripSwitch> newSceneRoundTripSwitch;
while (!in.atEnd())
{
while (!in.atEnd()) {
QString line = in.readLine();
lines.push_back(line);
if (lines.size() == 5)
{
OBSWeakSource scene1 = GetWeakSourceByQString(lines[0]);
OBSWeakSource scene2 = GetWeakSourceByQString(lines[1]);
OBSWeakSource transition = GetWeakTransitionByQString(lines[4]);
if (lines.size() == 5) {
OBSWeakSource scene1 =
GetWeakSourceByQString(lines[0]);
OBSWeakSource scene2 =
GetWeakSourceByQString(lines[1]);
OBSWeakSource transition =
GetWeakTransitionByQString(lines[4]);
if (WeakSourceValid(scene1) && ((lines[1] == QString(PREVIOUS_SCENE_NAME)) || (WeakSourceValid(scene2)))
&& WeakSourceValid(transition))
{
newSceneRoundTripSwitch.emplace_back(SceneRoundTripSwitch(
GetWeakSourceByQString(lines[0]),
GetWeakSourceByQString(lines[1]),
GetWeakTransitionByQString(lines[4]),
lines[2].toInt(),
(lines[1] == QString(PREVIOUS_SCENE_NAME)),
lines[3].toStdString()));
if (WeakSourceValid(scene1) &&
((lines[1] ==
QString(PREVIOUS_SCENE_NAME)) ||
(WeakSourceValid(scene2))) &&
WeakSourceValid(transition)) {
newSceneRoundTripSwitch.emplace_back(
SceneRoundTripSwitch(
GetWeakSourceByQString(
lines[0]),
GetWeakSourceByQString(
lines[1]),
GetWeakTransitionByQString(
lines[4]),
lines[2].toInt(),
(lines[1] ==
QString(PREVIOUS_SCENE_NAME)),
lines[3].toStdString()));
}
lines.clear();
}
@ -200,39 +210,42 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked()
switcher->sceneRoundTripSwitches.clear();
ui->sceneRoundTrips->clear();
switcher->sceneRoundTripSwitches = newSceneRoundTripSwitch;
for (SceneRoundTripSwitch s : switcher->sceneRoundTripSwitches)
{
QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(s.sceneRoundTripStr), ui->sceneRoundTrips);
item->setData(Qt::UserRole, QString::fromStdString(s.sceneRoundTripStr));
for (SceneRoundTripSwitch s :
switcher->sceneRoundTripSwitches) {
QListWidgetItem *item = new QListWidgetItem(
QString::fromStdString(s.sceneRoundTripStr),
ui->sceneRoundTrips);
item->setData(
Qt::UserRole,
QString::fromStdString(s.sceneRoundTripStr));
}
}
}
void SwitcherData::checkSceneRoundTrip(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, unique_lock<mutex>& lock)
void SwitcherData::checkSceneRoundTrip(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition,
unique_lock<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);
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)
{
for (SceneRoundTripSwitch &s : sceneRoundTripSwitches) {
if (s.scene1 == ws) {
sceneRoundTripActive = true;
int dur = s.delay - interval;
if (dur > 0)
{
if (dur > 0) {
waitScene = currentSource;
cv.wait_for(lock, chrono::milliseconds(dur));
}
obs_source_t* currentSource2 = obs_frontend_get_current_scene();
obs_source_t *currentSource2 =
obs_frontend_get_current_scene();
// only switch if user hasn't changed scene manually
if (currentSource == currentSource2)
{
if (currentSource == currentSource2) {
match = true;
scene = (s.usePreviousScene) ? previousScene : s.scene2;
scene = (s.usePreviousScene) ? previousScene
: s.scene2;
transition = s.transition;
}
obs_source_release(currentSource2);
@ -250,42 +263,41 @@ void SceneSwitcher::on_sceneRoundTrips_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->sceneRoundTrips->item(idx);
QListWidgetItem *item = ui->sceneRoundTrips->item(idx);
QString sceneRoundTrip = item->text();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->sceneRoundTripSwitches)
{
if (sceneRoundTrip.compare(s.sceneRoundTripStr.c_str()) == 0)
{
for (auto &s : switcher->sceneRoundTripSwitches) {
if (sceneRoundTrip.compare(s.sceneRoundTripStr.c_str()) == 0) {
string scene1 = GetWeakSourceName(s.scene1);
string scene2 = GetWeakSourceName(s.scene2);
string transitionName = GetWeakSourceName(s.transition);
int delay = s.delay;
ui->sceneRoundTripScenes1->setCurrentText(scene1.c_str());
ui->sceneRoundTripScenes2->setCurrentText(scene2.c_str());
ui->sceneRoundTripTransitions->setCurrentText(transitionName.c_str());
ui->sceneRoundTripSpinBox->setValue((double)delay/1000);
ui->sceneRoundTripScenes1->setCurrentText(
scene1.c_str());
ui->sceneRoundTripScenes2->setCurrentText(
scene2.c_str());
ui->sceneRoundTripTransitions->setCurrentText(
transitionName.c_str());
ui->sceneRoundTripSpinBox->setValue((double)delay /
1000);
break;
}
}
}
int SceneSwitcher::SceneRoundTripFindByData(const QString& scene1)
int SceneSwitcher::SceneRoundTripFindByData(const QString &scene1)
{
QRegExp rx(scene1 + " ->.*");
int count = ui->sceneRoundTrips->count();
int idx = -1;
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->sceneRoundTrips->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->sceneRoundTrips->item(i);
QString itemString = item->data(Qt::UserRole).toString();
if (rx.exactMatch(itemString))
{
if (rx.exactMatch(itemString)) {
idx = i;
break;
}
@ -294,14 +306,12 @@ int SceneSwitcher::SceneRoundTripFindByData(const QString& scene1)
return idx;
}
void SwitcherData::autoStopStreamAndRecording()
{
obs_source_t* currentSource = obs_frontend_get_current_scene();
obs_weak_source_t* ws = obs_source_get_weak_source(currentSource);
obs_source_t *currentSource = obs_frontend_get_current_scene();
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
if (ws && autoStopScene == ws)
{
if (ws && autoStopScene == ws) {
if (obs_frontend_streaming_active())
obs_frontend_streaming_stop();
if (obs_frontend_recording_active())

View File

@ -16,33 +16,33 @@ void SceneSwitcher::on_transitionsAdd_clicked()
OBSWeakSource source2 = GetWeakSourceByQString(scene2Name);
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QString text = MakeSceneTransitionName(scene1Name, scene2Name, transitionName);
QString text =
MakeSceneTransitionName(scene1Name, scene2Name, transitionName);
QVariant v = QVariant::fromValue(text);
int idx = SceneTransitionsFindByData(scene1Name, scene2Name);
if (idx == -1)
{
QListWidgetItem* item = new QListWidgetItem(text, ui->sceneTransitions);
if (idx == -1) {
QListWidgetItem *item =
new QListWidgetItem(text, ui->sceneTransitions);
item->setData(Qt::UserRole, v);
lock_guard<mutex> lock(switcher->m);
switcher->sceneTransitions.emplace_back(
source1, source2, transition, text.toUtf8().constData());
}
else
{
QListWidgetItem* item = ui->sceneTransitions->item(idx);
source1, source2, transition,
text.toUtf8().constData());
} else {
QListWidgetItem *item = ui->sceneTransitions->item(idx);
item->setText(text);
{
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->sceneTransitions)
{
if (s.scene1 == source1 && s.scene2 == source2)
{
for (auto &s : switcher->sceneTransitions) {
if (s.scene1 == source1 &&
s.scene2 == source2) {
s.transition = transition;
s.sceneTransitionStr = text.toUtf8().constData();
s.sceneTransitionStr =
text.toUtf8().constData();
break;
}
}
@ -54,7 +54,7 @@ void SceneSwitcher::on_transitionsAdd_clicked()
void SceneSwitcher::on_transitionsRemove_clicked()
{
QListWidgetItem* item = ui->sceneTransitions->currentItem();
QListWidgetItem *item = ui->sceneTransitions->currentItem();
if (!item)
return;
@ -62,14 +62,12 @@ void SceneSwitcher::on_transitionsRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->sceneTransitions;
auto &switches = switcher->sceneTransitions;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.sceneTransitionStr == text)
{
if (s.sceneTransitionStr == text) {
switches.erase(it);
break;
}
@ -82,7 +80,8 @@ void SceneSwitcher::on_transitionsRemove_clicked()
void SceneSwitcher::on_defaultTransitionsAdd_clicked()
{
QString sceneName = ui->defaultTransitionsScene->currentText();
QString transitionName = ui->defaultTransitionsTransitions->currentText();
QString transitionName =
ui->defaultTransitionsTransitions->currentText();
if (sceneName.isEmpty() || transitionName.isEmpty())
return;
@ -90,33 +89,31 @@ void SceneSwitcher::on_defaultTransitionsAdd_clicked()
OBSWeakSource source = GetWeakSourceByQString(sceneName);
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QString text = MakeDefaultSceneTransitionName(sceneName, transitionName);
QString text =
MakeDefaultSceneTransitionName(sceneName, transitionName);
QVariant v = QVariant::fromValue(text);
int idx = DefaultTransitionsFindByData(sceneName);
if (idx == -1)
{
QListWidgetItem* item = new QListWidgetItem(text, ui->defaultTransitions);
if (idx == -1) {
QListWidgetItem *item =
new QListWidgetItem(text, ui->defaultTransitions);
item->setData(Qt::UserRole, v);
lock_guard<mutex> lock(switcher->m);
switcher->defaultSceneTransitions.emplace_back(
source, transition, text.toUtf8().constData());
}
else
{
QListWidgetItem* item = ui->defaultTransitions->item(idx);
} else {
QListWidgetItem *item = ui->defaultTransitions->item(idx);
item->setText(text);
{
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->defaultSceneTransitions)
{
if (s.scene == source)
{
for (auto &s : switcher->defaultSceneTransitions) {
if (s.scene == source) {
s.transition = transition;
s.sceneTransitionStr = text.toUtf8().constData();
s.sceneTransitionStr =
text.toUtf8().constData();
break;
}
}
@ -128,7 +125,7 @@ void SceneSwitcher::on_defaultTransitionsAdd_clicked()
void SceneSwitcher::on_defaultTransitionsRemove_clicked()
{
QListWidgetItem* item = ui->defaultTransitions->currentItem();
QListWidgetItem *item = ui->defaultTransitions->currentItem();
if (!item)
return;
@ -136,14 +133,12 @@ void SceneSwitcher::on_defaultTransitionsRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->defaultSceneTransitions;
auto &switches = switcher->defaultSceneTransitions;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.sceneTransitionStr == text)
{
if (s.sceneTransitionStr == text) {
switches.erase(it);
break;
}
@ -155,14 +150,13 @@ void SceneSwitcher::on_defaultTransitionsRemove_clicked()
void SwitcherData::setDefaultSceneTransitions()
{
obs_source_t* currentSource = obs_frontend_get_current_scene();
obs_weak_source_t* ws = obs_source_get_weak_source(currentSource);
obs_source_t *currentSource = obs_frontend_get_current_scene();
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
for (DefaultSceneTransition& s : defaultSceneTransitions)
{
if (s.scene == ws)
{
obs_source_t* transition = obs_weak_source_get_source(s.transition);
for (DefaultSceneTransition &s : defaultSceneTransitions) {
if (s.scene == ws) {
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
//This might cancel the current transition
//There is no way to be sure when the previous transition finished
obs_frontend_set_current_transition(transition);
@ -174,19 +168,18 @@ void SwitcherData::setDefaultSceneTransitions()
obs_weak_source_release(ws);
}
int SceneSwitcher::SceneTransitionsFindByData(const QString& scene1, const QString& scene2)
int SceneSwitcher::SceneTransitionsFindByData(const QString &scene1,
const QString &scene2)
{
QRegExp rx(scene1 + " --- .* --> " + scene2);
int count = ui->sceneTransitions->count();
int idx = -1;
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->sceneTransitions->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->sceneTransitions->item(i);
QString itemString = item->data(Qt::UserRole).toString();
if (rx.exactMatch(itemString))
{
if (rx.exactMatch(itemString)) {
idx = i;
break;
}
@ -195,19 +188,17 @@ int SceneSwitcher::SceneTransitionsFindByData(const QString& scene1, const QStri
return idx;
}
int SceneSwitcher::DefaultTransitionsFindByData(const QString& scene)
int SceneSwitcher::DefaultTransitionsFindByData(const QString &scene)
{
QRegExp rx(scene + " --> .*");
int count = ui->defaultTransitions->count();
int idx = -1;
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->defaultTransitions->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->defaultTransitions->item(i);
QString itemString = item->data(Qt::UserRole).toString();
if (rx.exactMatch(itemString))
{
if (rx.exactMatch(itemString)) {
idx = i;
break;
}
@ -223,21 +214,21 @@ void SceneSwitcher::on_sceneTransitions_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->sceneTransitions->item(idx);
QListWidgetItem *item = ui->sceneTransitions->item(idx);
QString sceneTransition = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->sceneTransitions)
{
if (sceneTransition.compare(s.sceneTransitionStr.c_str()) == 0)
{
for (auto &s : switcher->sceneTransitions) {
if (sceneTransition.compare(s.sceneTransitionStr.c_str()) ==
0) {
string scene1 = GetWeakSourceName(s.scene1);
string scene2 = GetWeakSourceName(s.scene2);
string transitionName = GetWeakSourceName(s.transition);
ui->transitionsScene1->setCurrentText(scene1.c_str());
ui->transitionsScene2->setCurrentText(scene2.c_str());
ui->transitionsTransitions->setCurrentText(transitionName.c_str());
ui->transitionsTransitions->setCurrentText(
transitionName.c_str());
break;
}
}
@ -250,31 +241,31 @@ void SceneSwitcher::on_defaultTransitions_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->defaultTransitions->item(idx);
QListWidgetItem *item = ui->defaultTransitions->item(idx);
QString sceneTransition = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->defaultSceneTransitions)
{
if (sceneTransition.compare(s.sceneTransitionStr.c_str()) == 0)
{
for (auto &s : switcher->defaultSceneTransitions) {
if (sceneTransition.compare(s.sceneTransitionStr.c_str()) ==
0) {
string scene = GetWeakSourceName(s.scene);
string transitionName = GetWeakSourceName(s.transition);
ui->defaultTransitionsScene->setCurrentText(scene.c_str());
ui->defaultTransitionsTransitions->setCurrentText(transitionName.c_str());
ui->defaultTransitionsScene->setCurrentText(
scene.c_str());
ui->defaultTransitionsTransitions->setCurrentText(
transitionName.c_str());
break;
}
}
}
obs_weak_source_t* getNextTransition(obs_weak_source_t* scene1, obs_weak_source_t* scene2)
obs_weak_source_t *getNextTransition(obs_weak_source_t *scene1,
obs_weak_source_t *scene2)
{
obs_weak_source_t* ws = nullptr;
if (scene1 && scene2)
{
for (SceneTransition& t : switcher->sceneTransitions)
{
obs_weak_source_t *ws = nullptr;
if (scene1 && scene2) {
for (SceneTransition &t : switcher->sceneTransitions) {
if (t.scene1 == scene1 && t.scene2 == scene2)
ws = t.transition;
}

View File

@ -1,18 +1,16 @@
#include "headers/advanced-scene-switcher.hpp"
void SwitcherData::checkScreenRegionSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition)
void SwitcherData::checkScreenRegionSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
pair<int, int> cursorPos = getCursorPos();
int minRegionSize = 99999;
for (auto& s : screenRegionSwitches)
{
if (cursorPos.first >= s.minX && cursorPos.second >= s.minY
&& cursorPos.first <= s.maxX && cursorPos.second <= s.maxY)
{
for (auto &s : screenRegionSwitches) {
if (cursorPos.first >= s.minX && cursorPos.second >= s.minY &&
cursorPos.first <= s.maxX && cursorPos.second <= s.maxY) {
int regionSize = (s.maxX - s.minX) + (s.maxY - s.minY);
if (regionSize < minRegionSize)
{
if (regionSize < minRegionSize) {
match = true;
scene = s.scene;
transition = s.transition;
@ -43,40 +41,37 @@ void SceneSwitcher::on_screenRegionAdd_clicked()
int maxX = ui->screenRegionMaxX->value();
int maxY = ui->screenRegionMaxY->value();
string regionStr = to_string(minX) + ", " + to_string(minY) + " x " + to_string(maxX) + ", "
+ to_string(maxY);
string regionStr = to_string(minX) + ", " + to_string(minY) + " x " +
to_string(maxX) + ", " + to_string(maxY);
QString region = QString::fromStdString(regionStr);
OBSWeakSource source = GetWeakSourceByQString(sceneName);
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QVariant v = QVariant::fromValue(region);
QString text = MakeScreenRegionSwitchName(sceneName, transitionName, minX, minY, maxX, maxY);
QString text = MakeScreenRegionSwitchName(sceneName, transitionName,
minX, minY, maxX, maxY);
int idx = ScreenRegionFindByData(region);
if (idx == -1)
{
QListWidgetItem* item = new QListWidgetItem(text, ui->screenRegions);
if (idx == -1) {
QListWidgetItem *item =
new QListWidgetItem(text, ui->screenRegions);
item->setData(Qt::UserRole, v);
lock_guard<mutex> lock(switcher->m);
switcher->screenRegionSwitches.emplace_back(
source, transition, minX, minY, maxX, maxY, regionStr);
}
else
{
QListWidgetItem* item = ui->screenRegions->item(idx);
} else {
QListWidgetItem *item = ui->screenRegions->item(idx);
item->setText(text);
string curRegion = region.toUtf8().constData();
{
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->screenRegionSwitches)
{
if (s.regionStr == curRegion)
{
for (auto &s : switcher->screenRegionSwitches) {
if (s.regionStr == curRegion) {
s.scene = source;
s.transition = transition;
break;
@ -90,22 +85,21 @@ void SceneSwitcher::on_screenRegionAdd_clicked()
void SceneSwitcher::on_screenRegionRemove_clicked()
{
QListWidgetItem* item = ui->screenRegions->currentItem();
QListWidgetItem *item = ui->screenRegions->currentItem();
if (!item)
return;
string region = item->data(Qt::UserRole).toString().toUtf8().constData();
string region =
item->data(Qt::UserRole).toString().toUtf8().constData();
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->screenRegionSwitches;
auto &switches = switcher->screenRegionSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.regionStr == region)
{
if (s.regionStr == region) {
switches.erase(it);
break;
}
@ -122,19 +116,18 @@ void SceneSwitcher::on_screenRegions_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->screenRegions->item(idx);
QListWidgetItem *item = ui->screenRegions->item(idx);
QString region = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->screenRegionSwitches)
{
if (region.compare(s.regionStr.c_str()) == 0)
{
for (auto &s : switcher->screenRegionSwitches) {
if (region.compare(s.regionStr.c_str()) == 0) {
string name = GetWeakSourceName(s.scene);
string transitionName = GetWeakSourceName(s.transition);
ui->screenRegionScenes->setCurrentText(name.c_str());
ui->screenRegionsTransitions->setCurrentText(transitionName.c_str());
ui->screenRegionsTransitions->setCurrentText(
transitionName.c_str());
ui->screenRegionMinX->setValue(s.minX);
ui->screenRegionMinY->setValue(s.minY);
ui->screenRegionMaxX->setValue(s.maxX);
@ -144,18 +137,16 @@ void SceneSwitcher::on_screenRegions_currentRowChanged(int idx)
}
}
int SceneSwitcher::ScreenRegionFindByData(const QString& region)
int SceneSwitcher::ScreenRegionFindByData(const QString &region)
{
int count = ui->screenRegions->count();
int idx = -1;
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->screenRegions->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->screenRegions->item(i);
QString itemRegion = item->data(Qt::UserRole).toString();
if (itemRegion == region)
{
if (itemRegion == region) {
idx = i;
break;
}

View File

@ -6,7 +6,7 @@
using namespace std;
static bool GetWindowTitle(HWND window, string& title)
static bool GetWindowTitle(HWND window, string &title)
{
size_t len = (size_t)GetWindowTextLengthW(window);
wstring wtitle;
@ -45,12 +45,13 @@ static bool WindowValid(HWND window)
return true;
}
void GetWindowList(vector<string>& windows)
void GetWindowList(vector<string> &windows)
{
windows.resize(0);
HWND window = GetWindow(GetDesktopWindow(), GW_CHILD);
while (window)
{
while (window) {
string title;
if (WindowValid(window) && GetWindowTitle(window, title))
windows.emplace_back(title);
@ -58,7 +59,22 @@ void GetWindowList(vector<string>& windows)
}
}
void GetCurrentWindowTitle(string& title)
// Overloaded
void GetWindowList(QStringList &windows)
{
windows.clear();
HWND window = GetWindow(GetDesktopWindow(), GW_CHILD);
while (window) {
string title;
if (WindowValid(window) && GetWindowTitle(window, title))
windows << QString::fromStdString(title);
window = GetNextWindow(window, GW_HWNDNEXT);
}
}
void GetCurrentWindowTitle(string &title)
{
HWND window = GetForegroundWindow();
DWORD pid;
@ -79,39 +95,59 @@ pair<int, int> getCursorPos()
{
pair<int, int> pos(0, 0);
POINT cursorPos;
if (GetPhysicalCursorPos(&cursorPos))
{
if (GetPhysicalCursorPos(&cursorPos)) {
pos.first = cursorPos.x;
pos.second = cursorPos.y;
}
return pos;
}
bool isFullscreen()
bool isFullscreen(std::string &title)
{
RECT appBounds;
RECT rc;
GetWindowRect(GetDesktopWindow(), &rc);
HWND hwnd = GetForegroundWindow();
if (hwnd != GetDesktopWindow() && hwnd != GetShellWindow())
{
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()) {
if (IsZoomed(hwnd)) {
return true;
}
GetWindowRect(hwnd, &appBounds);
if (rc.bottom == appBounds.bottom && rc.top == appBounds.top && rc.left == appBounds.left
&& rc.right == appBounds.right)
{
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;
}
void GetProcessList(QStringList &processes) {
void GetProcessList(QStringList &processes)
{
HANDLE procSnapshot;
PROCESSENTRY32 procEntry;
procSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (procSnapshot == INVALID_HANDLE_VALUE) return;
if (procSnapshot == INVALID_HANDLE_VALUE)
return;
procEntry.dwSize = sizeof(PROCESSENTRY32);
@ -122,30 +158,45 @@ void GetProcessList(QStringList &processes) {
do {
QString tempexe = QString::fromWCharArray(procEntry.szExeFile);
if (tempexe == "System") continue;
if (tempexe == "[System Process]") continue;
if (processes.contains(tempexe)) continue;
if (tempexe == "System")
continue;
if (tempexe == "[System Process]")
continue;
if (processes.contains(tempexe))
continue;
processes.append(tempexe);
} while (Process32Next(procSnapshot, &procEntry));
CloseHandle(procSnapshot);
}
bool isInFocus(const QString &exeToCheck) {
bool isInFocus(const QString &executable)
{
// only checks if the current foreground window is from the same executable,
// may return true for incorrent not meant windows from a program
// may return true for any window from a program
HWND foregroundWindow = GetForegroundWindow();
DWORD processId = 0;
GetWindowThreadProcessId(foregroundWindow, &processId);
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
if (process == NULL) return false;
HANDLE process = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
if (process == NULL)
return false;
WCHAR executablePath[600];
GetModuleFileNameEx(process, 0, executablePath, 600);
CloseHandle(process);
return exeToCheck == QString::fromWCharArray(executablePath).split(QRegExp("(/|\\\\)")).back();
QString file = QString::fromWCharArray(executablePath)
.split(QRegularExpression("(/|\\\\)"))
.back();
// True if executable switch equals current window
bool equals = (executable == file);
// True if executable switch matches current window
bool matches = file.contains(QRegularExpression(executable));
return (equals || matches);
}
int getLastInputTime()

View File

@ -1,12 +1,71 @@
#include <obs-module.h>
#include "headers/advanced-scene-switcher.hpp"
bool isRunning(std::string &title)
{
QStringList windows;
GetWindowList(windows);
// True if switch is running (direct)
bool equals = windows.contains(QString::fromStdString(title));
// True if switch is running (regex)
bool matches = (windows.indexOf(QRegularExpression(
QString::fromStdString(title))) != -1);
return (equals || matches);
}
bool isFocused(std::string &title)
{
string current;
GetCurrentWindowTitle(current);
// True if switch equals current window
bool equals = (title == current);
// True if switch matches current window
bool matches = QString::fromStdString(current).contains(
QRegularExpression(QString::fromStdString(title)));
return (equals || matches);
}
void SceneSwitcher::on_up_clicked()
{
int index = ui->switches->currentRow();
if (index != -1 && index != 0) {
ui->switches->insertItem(index - 1,
ui->switches->takeItem(index));
ui->switches->setCurrentRow(index - 1);
lock_guard<mutex> lock(switcher->m);
iter_swap(switcher->windowSwitches.begin() + index,
switcher->windowSwitches.begin() + index - 1);
}
}
void SceneSwitcher::on_down_clicked()
{
int index = ui->switches->currentRow();
if (index != -1 && index != ui->switches->count() - 1) {
ui->switches->insertItem(index + 1,
ui->switches->takeItem(index));
ui->switches->setCurrentRow(index + 1);
lock_guard<mutex> lock(switcher->m);
iter_swap(switcher->windowSwitches.begin() + index,
switcher->windowSwitches.begin() + index + 1);
}
}
void SceneSwitcher::on_add_clicked()
{
QString sceneName = ui->scenes->currentText();
QString windowName = ui->windows->currentText();
QString transitionName = ui->transitions->currentText();
bool fullscreen = ui->fullscreenCheckBox->isChecked();
bool focus = ui->focusCheckBox->isChecked();
if (windowName.isEmpty() || sceneName.isEmpty())
return;
@ -15,62 +74,57 @@ void SceneSwitcher::on_add_clicked()
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QVariant v = QVariant::fromValue(windowName);
QString text = MakeSwitchName(sceneName, windowName, transitionName, fullscreen);
QString text = MakeSwitchName(sceneName, windowName, transitionName,
fullscreen, focus);
int idx = FindByData(windowName);
if (idx == -1)
{
if (idx == -1) {
lock_guard<mutex> lock(switcher->m);
switcher->windowSwitches.emplace_back(
source, windowName.toUtf8().constData(), transition, fullscreen);
source, windowName.toUtf8().constData(), transition,
fullscreen, focus);
QListWidgetItem* item = new QListWidgetItem(text, ui->switches);
QListWidgetItem *item = new QListWidgetItem(text, ui->switches);
item->setData(Qt::UserRole, v);
}
else
{
QListWidgetItem* item = ui->switches->item(idx);
} else {
QListWidgetItem *item = ui->switches->item(idx);
item->setText(text);
string window = windowName.toUtf8().constData();
{
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->windowSwitches)
{
if (s.window == window)
{
for (auto &s : switcher->windowSwitches) {
if (s.window == window) {
s.scene = source;
s.transition = transition;
s.fullscreen = fullscreen;
s.focus = focus;
break;
}
}
}
ui->switches->sortItems();
}
}
void SceneSwitcher::on_remove_clicked()
{
QListWidgetItem* item = ui->switches->currentItem();
QListWidgetItem *item = ui->switches->currentItem();
if (!item)
return;
string window = item->data(Qt::UserRole).toString().toUtf8().constData();
string window =
item->data(Qt::UserRole).toString().toUtf8().constData();
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->windowSwitches;
auto &switches = switcher->windowSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.window == window)
{
if (s.window == window) {
switches.erase(it);
break;
}
@ -80,9 +134,6 @@ void SceneSwitcher::on_remove_clicked()
delete item;
}
void SceneSwitcher::on_ignoreWindowsAdd_clicked()
{
QString windowName = ui->ignoreWindowsWindows->currentText();
@ -92,22 +143,23 @@ void SceneSwitcher::on_ignoreWindowsAdd_clicked()
QVariant v = QVariant::fromValue(windowName);
QList<QListWidgetItem*> items = ui->ignoreWindows->findItems(windowName, Qt::MatchExactly);
QList<QListWidgetItem *> items =
ui->ignoreWindows->findItems(windowName, Qt::MatchExactly);
if (items.size() == 0)
{
QListWidgetItem* item = new QListWidgetItem(windowName, ui->ignoreWindows);
if (items.size() == 0) {
QListWidgetItem *item =
new QListWidgetItem(windowName, ui->ignoreWindows);
item->setData(Qt::UserRole, v);
lock_guard<mutex> lock(switcher->m);
switcher->ignoreWindowsSwitches.emplace_back(windowName.toUtf8().constData());
ui->ignoreWindows->sortItems();
switcher->ignoreWindowsSwitches.emplace_back(
windowName.toUtf8().constData());
}
}
void SceneSwitcher::on_ignoreWindowsRemove_clicked()
{
QListWidgetItem* item = ui->ignoreWindows->currentItem();
QListWidgetItem *item = ui->ignoreWindows->currentItem();
if (!item)
return;
@ -115,14 +167,12 @@ void SceneSwitcher::on_ignoreWindowsRemove_clicked()
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->ignoreWindowsSwitches;
auto &switches = switcher->ignoreWindowsSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it)
{
auto& s = *it;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s == windowName.toUtf8().constData())
{
if (s == windowName.toUtf8().constData()) {
switches.erase(it);
break;
}
@ -132,18 +182,16 @@ void SceneSwitcher::on_ignoreWindowsRemove_clicked()
delete item;
}
int SceneSwitcher::FindByData(const QString& window)
int SceneSwitcher::FindByData(const QString &window)
{
int count = ui->switches->count();
int idx = -1;
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->switches->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->switches->item(i);
QString itemWindow = item->data(Qt::UserRole).toString();
if (itemWindow == window)
{
if (itemWindow == window) {
idx = i;
break;
}
@ -152,21 +200,16 @@ int SceneSwitcher::FindByData(const QString& window)
return idx;
}
int SceneSwitcher::IgnoreWindowsFindByData(const QString& window)
int SceneSwitcher::IgnoreWindowsFindByData(const QString &window)
{
int count = ui->ignoreWindows->count();
int idx = -1;
for (int i = 0; i < count; i++)
{
QListWidgetItem* item = ui->ignoreWindows->item(i);
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->ignoreWindows->item(i);
QString itemRegion = item->data(Qt::UserRole).toString();
if (itemRegion == window)
{
if (itemRegion == window) {
idx = i;
break;
}
@ -175,7 +218,6 @@ int SceneSwitcher::IgnoreWindowsFindByData(const QString& window)
return idx;
}
void SceneSwitcher::on_switches_currentRowChanged(int idx)
{
if (loading)
@ -183,27 +225,25 @@ void SceneSwitcher::on_switches_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->switches->item(idx);
QListWidgetItem *item = ui->switches->item(idx);
QString window = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->windowSwitches)
{
if (window.compare(s.window.c_str()) == 0)
{
for (auto &s : switcher->windowSwitches) {
if (window.compare(s.window.c_str()) == 0) {
string name = GetWeakSourceName(s.scene);
string transitionName = GetWeakSourceName(s.transition);
ui->scenes->setCurrentText(name.c_str());
ui->windows->setCurrentText(window);
ui->transitions->setCurrentText(transitionName.c_str());
ui->fullscreenCheckBox->setChecked(s.fullscreen);
ui->focusCheckBox->setChecked(s.focus);
break;
}
}
}
void SceneSwitcher::on_ignoreWindows_currentRowChanged(int idx)
{
if (loading)
@ -211,70 +251,63 @@ void SceneSwitcher::on_ignoreWindows_currentRowChanged(int idx)
if (idx == -1)
return;
QListWidgetItem* item = ui->ignoreWindows->item(idx);
QListWidgetItem *item = ui->ignoreWindows->item(idx);
QString window = item->data(Qt::UserRole).toString();
lock_guard<mutex> lock(switcher->m);
for (auto& s : switcher->ignoreWindowsSwitches)
{
if (window.compare(s.c_str()) == 0)
{
for (auto &s : switcher->ignoreWindowsSwitches) {
if (window.compare(s.c_str()) == 0) {
ui->ignoreWindowsWindows->setCurrentText(s.c_str());
break;
}
}
}
void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition)
void SwitcherData::checkWindowTitleSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
//check if title should be ignored
string title;
bool ignored = false;
// Check if current window is ignored
GetCurrentWindowTitle(title);
for (auto& window : ignoreWindowsSwitches)
{
try
{
bool matches = regex_match(title, regex(window));
if (matches)
{
title = lastTitle;
break;
}
}
catch (const regex_error&)
{
for (auto &window : ignoreWindowsSwitches) {
// True if ignored switch equals current window
bool equals = (title == window);
// True if ignored switch matches current window
bool matches = QString::fromStdString(title).contains(
QRegularExpression(QString::fromStdString(window)));
if (equals || matches) {
ignored = true;
title = lastTitle;
break;
}
}
lastTitle = title;
//direct match
for (WindowSceneSwitch& s : windowSwitches)
{
if (s.window == title)
{
match = !s.fullscreen || (s.fullscreen && isFullscreen());
// Check for match
for (WindowSceneSwitch &s : windowSwitches) {
// True if fullscreen is disabled OR current window is fullscreen
bool fullscreen = (!s.fullscreen || isFullscreen(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
bool ignore =
(ignored &&
(title == s.window ||
QString::fromStdString(title).contains(
QRegularExpression(
QString::fromStdString(s.window)))));
if (isRunning(s.window) && (fullscreen && (focus || ignore))) {
match = true;
scene = s.scene;
transition = s.transition;
return;
}
}
//regex match
for (WindowSceneSwitch& s : windowSwitches)
{
try
{
bool matches = regex_match(title, regex(s.window));
if (matches)
{
match = !s.fullscreen || (s.fullscreen && isFullscreen());
scene = s.scene;
transition = s.transition;
}
}
catch (const regex_error&)
{
}
}
break;
}
}
}