SceneSwitcher/src/switch-executable.cpp
WarmUpTill a84a205608
Minor style changes (#114)
* use GetWeakSourceName() where possible

* add getCurrentScene() to scene group

* silence OBS warning log and fix typo in audio switch

* extract showing initial status of widgets to function in generic switch
2021-02-03 20:27:25 +01:00

316 lines
7.7 KiB
C++

#include "headers/advanced-scene-switcher.hpp"
#include "headers/utility.hpp"
bool ExecutableSwitch::pause = false;
static QMetaObject::Connection addPulse;
void AdvSceneSwitcher::on_executableAdd_clicked()
{
std::lock_guard<std::mutex> lock(switcher->m);
switcher->executableSwitches.emplace_back();
listAddClicked(ui->executables,
new ExecutableSwitchWidget(
this, &switcher->executableSwitches.back()),
ui->executableAdd, &addPulse);
ui->exeHelp->setVisible(false);
}
void AdvSceneSwitcher::on_executableRemove_clicked()
{
QListWidgetItem *item = ui->executables->currentItem();
if (!item) {
return;
}
{
std::lock_guard<std::mutex> lock(switcher->m);
int idx = ui->executables->currentRow();
auto &switches = switcher->executableSwitches;
switches.erase(switches.begin() + idx);
}
delete item;
}
void AdvSceneSwitcher::on_executableUp_clicked()
{
int index = ui->executables->currentRow();
if (!listMoveUp(ui->executables)) {
return;
}
ExecutableSwitchWidget *s1 =
(ExecutableSwitchWidget *)ui->executables->itemWidget(
ui->executables->item(index));
ExecutableSwitchWidget *s2 =
(ExecutableSwitchWidget *)ui->executables->itemWidget(
ui->executables->item(index - 1));
ExecutableSwitchWidget::swapSwitchData(s1, s2);
std::lock_guard<std::mutex> lock(switcher->m);
std::swap(switcher->executableSwitches[index],
switcher->executableSwitches[index - 1]);
}
void AdvSceneSwitcher::on_executableDown_clicked()
{
int index = ui->executables->currentRow();
if (!listMoveDown(ui->executables)) {
return;
}
ExecutableSwitchWidget *s1 =
(ExecutableSwitchWidget *)ui->executables->itemWidget(
ui->executables->item(index));
ExecutableSwitchWidget *s2 =
(ExecutableSwitchWidget *)ui->executables->itemWidget(
ui->executables->item(index + 1));
ExecutableSwitchWidget::swapSwitchData(s1, s2);
std::lock_guard<std::mutex> lock(switcher->m);
std::swap(switcher->executableSwitches[index],
switcher->executableSwitches[index + 1]);
}
void SwitcherData::checkExeSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
if (executableSwitches.size() == 0 || ExecutableSwitch::pause) {
return;
}
std::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 (ExecutableSwitch &s : executableSwitches) {
if (!s.initialized()) {
continue;
}
bool equals = runningProcesses.contains(s.exe);
bool matches = (runningProcesses.indexOf(
QRegularExpression(s.exe)) != -1);
bool focus = (!s.inFocus || isInFocus(s.exe));
// True if current window is ignored AND switch equals OR matches last window
bool ignore =
(ignored && (title == s.exe.toStdString() ||
QString::fromStdString(title).contains(
QRegularExpression(s.exe))));
if ((equals || matches) && (focus || ignore)) {
match = true;
scene = s.getScene();
transition = s.transition;
if (verbose) {
s.logMatch();
}
break;
}
}
}
void SwitcherData::saveExecutableSwitches(obs_data_t *obj)
{
obs_data_array_t *executableArray = obs_data_array_create();
for (ExecutableSwitch &s : switcher->executableSwitches) {
obs_data_t *array_obj = obs_data_create();
s.save(array_obj);
obs_data_array_push_back(executableArray, array_obj);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "executableSwitches", executableArray);
obs_data_array_release(executableArray);
}
void SwitcherData::loadExecutableSwitches(obs_data_t *obj)
{
switcher->executableSwitches.clear();
obs_data_array_t *executableArray =
obs_data_get_array(obj, "executableSwitches");
size_t count = obs_data_array_count(executableArray);
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(executableArray, i);
switcher->executableSwitches.emplace_back();
executableSwitches.back().load(array_obj);
obs_data_release(array_obj);
}
obs_data_array_release(executableArray);
}
void AdvSceneSwitcher::setupExecutableTab()
{
for (auto &s : switcher->executableSwitches) {
QListWidgetItem *item;
item = new QListWidgetItem(ui->executables);
ui->executables->addItem(item);
ExecutableSwitchWidget *sw =
new ExecutableSwitchWidget(this, &s);
item->setSizeHint(sw->minimumSizeHint());
ui->executables->setItemWidget(item, sw);
}
if (switcher->executableSwitches.size() == 0) {
addPulse = PulseWidget(ui->executableAdd, QColor(Qt::green));
ui->exeHelp->setVisible(true);
} else {
ui->exeHelp->setVisible(false);
}
}
void ExecutableSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);
obs_data_set_string(obj, "exefile", exe.toUtf8());
obs_data_set_bool(obj, "infocus", inFocus);
}
// To be removed in future version
bool loadOldExe(obs_data_t *obj, ExecutableSwitch *s)
{
if (!s) {
return false;
}
const char *scene = obs_data_get_string(obj, "scene");
if (strcmp(scene, "") == 0) {
return false;
}
s->scene = GetWeakSourceByName(scene);
const char *transition = obs_data_get_string(obj, "transition");
s->transition = GetWeakTransitionByName(transition);
s->exe = obs_data_get_string(obj, "exefile");
s->inFocus = obs_data_get_bool(obj, "infocus");
s->usePreviousScene = strcmp(scene, previous_scene_name) == 0;
return true;
}
void ExecutableSwitch::load(obs_data_t *obj)
{
if (loadOldExe(obj, this)) {
return;
}
SceneSwitcherEntry::load(obj);
exe = obs_data_get_string(obj, "exefile");
inFocus = obs_data_get_bool(obj, "infocus");
}
ExecutableSwitchWidget::ExecutableSwitchWidget(QWidget *parent,
ExecutableSwitch *s)
: SwitchWidget(parent, s, true, true)
{
processes = new QComboBox();
requiresFocus = new QCheckBox(obs_module_text(
"AdvSceneSwitcher.executableTab.requiresFocus"));
QWidget::connect(processes, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(ProcessChanged(const QString &)));
QWidget::connect(requiresFocus, SIGNAL(stateChanged(int)), this,
SLOT(FocusChanged(int)));
AdvSceneSwitcher::populateProcessSelection(processes);
processes->setEditable(true);
processes->setMaxVisibleItems(20);
if (s) {
processes->setCurrentText(s->exe);
requiresFocus->setChecked(s->inFocus);
}
QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{processes}}", processes},
{"{{requiresFocus}}", requiresFocus},
{"{{scenes}}", scenes},
{"{{transitions}}", transitions}};
placeWidgets(obs_module_text("AdvSceneSwitcher.executableTab.entry"),
mainLayout, widgetPlaceholders);
setLayout(mainLayout);
switchData = s;
loading = false;
}
ExecutableSwitch *ExecutableSwitchWidget::getSwitchData()
{
return switchData;
}
void ExecutableSwitchWidget::setSwitchData(ExecutableSwitch *s)
{
switchData = s;
}
void ExecutableSwitchWidget::swapSwitchData(ExecutableSwitchWidget *s1,
ExecutableSwitchWidget *s2)
{
SwitchWidget::swapSwitchData(s1, s2);
ExecutableSwitch *t = s1->getSwitchData();
s1->setSwitchData(s2->getSwitchData());
s2->setSwitchData(t);
}
void ExecutableSwitchWidget::ProcessChanged(const QString &text)
{
if (loading || !switchData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
switchData->exe = text;
}
void ExecutableSwitchWidget::FocusChanged(int state)
{
if (loading || !switchData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
switchData->inFocus = state;
}