add option to switch based on file contents

This commit is contained in:
WarmUpTill 2018-05-21 23:20:02 +02:00 committed by GitHub
parent 9cc2875455
commit 104f74bf39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 660 additions and 216 deletions

View File

@ -55,6 +55,7 @@ SceneSwitcher::SceneSwitcher(QWidget* parent)
ui->executableScenes->addItem(name);
ui->idleScenes->addItem(name);
ui->randomScenes->addItem(name);
ui->fileScenes->addItem(name);
temp++;
}
@ -72,6 +73,7 @@ SceneSwitcher::SceneSwitcher(QWidget* parent)
ui->executableTransitions->addItem(name);
ui->idleTransitions->addItem(name);
ui->randomTransitions->addItem(name);
ui->fileTransitions->addItem(name);
}
obs_frontend_source_list_free(transitions);
@ -242,6 +244,17 @@ SceneSwitcher::SceneSwitcher(QWidget* parent)
item->setData(Qt::UserRole, text);
}
for (auto& s : switcher->fileSwitches)
{
string sceneName = GetWeakSourceName(s.scene);
string transitionName = GetWeakSourceName(s.transition);
QString listText = MakeFileSwitchName(
sceneName.c_str(), transitionName.c_str(), s.file.c_str(), s.text.c_str());
QListWidgetItem* item = new QListWidgetItem(listText, ui->fileScenesList);
item->setData(Qt::UserRole, listText);
}
ui->idleCheckBox->setChecked(switcher->idleData.idleEnable);
ui->idleScenes->setCurrentText(GetWeakSourceName(switcher->idleData.scene).c_str());
ui->idleTransitions->setCurrentText(GetWeakSourceName(switcher->idleData.transition).c_str());
@ -287,8 +300,28 @@ SceneSwitcher::SceneSwitcher(QWidget* parent)
connect(screenRegionTimer, SIGNAL(timeout()), this, SLOT(updateScreenRegionCursorPos()));
screenRegionTimer->start(1000);
for (string s : switcher->functionNamesByPriority)
for (int p : switcher->functionNamesByPriority)
{
string s = "";
switch (p) {
case READ_FILE_FUNC:
s = "File Content";
break;
case ROUND_TRIP_FUNC:
s = "Scene Sequence";
break;
case IDLE_FUNC:
s = "Idle Detection";
break;
case EXE_FUNC:
s = "Executable";
break;
case SCREEN_REGION_FUNC:
s = "Screen Region";
break;
case WINDOW_TITLE_FUNC:
s = "Window Title";
}
QString text(s.c_str());
QListWidgetItem* item = new QListWidgetItem(text, ui->priorityList);
item->setData(Qt::UserRole, text);
@ -315,6 +348,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_array_t* ignoreIdleWindowsArray = obs_data_array_create();
obs_data_array_t* executableArray = obs_data_array_create();
obs_data_array_t* randomArray = obs_data_array_create();
obs_data_array_t* fileArray = obs_data_array_create();
switcher->Prune();
@ -524,6 +558,29 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_release(array_obj);
}
for (FileSwitch& s : switcher->fileSwitches)
{
obs_data_t* array_obj = obs_data_create();
obs_source_t* source = obs_weak_source_get_source(s.scene);
obs_source_t* transition = obs_weak_source_get_source(s.transition);
if (source && transition)
{
const char* sceneName = obs_source_get_name(source);
const char* transitionName = obs_source_get_name(transition);
obs_data_set_string(array_obj, "scene", sceneName);
obs_data_set_string(array_obj, "transition", transitionName);
obs_data_set_string(array_obj, "file", s.file.c_str());
obs_data_set_string(array_obj, "text", s.text.c_str());
obs_data_array_push_back(fileArray, array_obj);
obs_source_release(source);
obs_source_release(transition);
}
obs_data_release(array_obj);
}
string nonMatchingSceneName = GetWeakSourceName(switcher->nonMatchingScene);
obs_data_set_int(obj, "interval", switcher->interval);
@ -542,6 +599,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_set_array(obj, "executableSwitches", executableArray);
obs_data_set_array(obj, "ignoreIdleWindows", ignoreIdleWindowsArray);
obs_data_set_array(obj, "randomSwitches", randomArray);
obs_data_set_array(obj, "fileSwitches", fileArray);
string autoStopSceneName = GetWeakSourceName(switcher->autoStopScene);
@ -560,12 +618,12 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_set_bool(obj, "writeEnabled", switcher->fileIO.writeEnabled);
obs_data_set_string(obj, "writePath", switcher->fileIO.writePath.c_str());
obs_data_set_string(obj, "priority0", switcher->functionNamesByPriority[0].c_str());
obs_data_set_string(obj, "priority1", switcher->functionNamesByPriority[1].c_str());
obs_data_set_string(obj, "priority2", switcher->functionNamesByPriority[2].c_str());
obs_data_set_string(obj, "priority3", switcher->functionNamesByPriority[3].c_str());
obs_data_set_string(obj, "priority4", switcher->functionNamesByPriority[4].c_str());
obs_data_set_string(obj, "priority5", switcher->functionNamesByPriority[5].c_str());
obs_data_set_int(obj, "priority0", switcher->functionNamesByPriority[0]);
obs_data_set_int(obj, "priority1", switcher->functionNamesByPriority[1]);
obs_data_set_int(obj, "priority2", switcher->functionNamesByPriority[2]);
obs_data_set_int(obj, "priority3", switcher->functionNamesByPriority[3]);
obs_data_set_int(obj, "priority4", switcher->functionNamesByPriority[4]);
obs_data_set_int(obj, "priority5", switcher->functionNamesByPriority[5]);
obs_data_set_obj(save_data, "advanced-scene-switcher", obj);
@ -580,6 +638,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_array_release(executableArray);
obs_data_array_release(ignoreIdleWindowsArray);
obs_data_array_release(randomArray);
obs_data_array_release(fileArray);
obs_data_release(obj);
}
@ -599,6 +658,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_array_t* executableArray = obs_data_get_array(obj, "executableSwitches");
obs_data_array_t* ignoreIdleWindowsArray = obs_data_get_array(obj, "ignoreIdleWindows");
obs_data_array_t* randomArray = obs_data_get_array(obj, "randomSwitches");
obs_data_array_t* fileArray = obs_data_get_array(obj, "fileSwitches");
if (!obj)
obj = obs_data_create();
@ -606,6 +666,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_set_default_int(obj, "interval", DEFAULT_INTERVAL);
switcher->interval = obs_data_get_int(obj, "interval");
obs_data_set_default_int(obj, "switch_if_not_matching", NO_SWITCH);
switcher->switchIfNotMatching = (NoMatch)obs_data_get_int(obj, "switch_if_not_matching");
string nonMatchingScene = obs_data_get_string(obj, "non_matching_scene");
bool active = obs_data_get_bool(obj, "active");
@ -786,6 +847,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_release(array_obj);
}
switcher->randomSwitches.clear();
count = obs_data_array_count(randomArray);
for (size_t i = 0; i < count; i++)
@ -795,7 +857,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
const char* scene = obs_data_get_string(array_obj, "scene");
const char* transition = obs_data_get_string(array_obj, "transition");
double delay = obs_data_get_double(array_obj, "delay");
string str = obs_data_get_string(array_obj, "str");
const char* str = obs_data_get_string(array_obj, "str");
switcher->randomSwitches.emplace_back(
GetWeakSourceByName(scene), GetWeakTransitionByName(transition), delay, str);
@ -803,6 +865,24 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_release(array_obj);
}
switcher->fileSwitches.clear();
count = obs_data_array_count(fileArray);
for (size_t i = 0; i < count; i++)
{
obs_data_t* array_obj = obs_data_array_item(fileArray, i);
const char* scene = obs_data_get_string(array_obj, "scene");
const char* transition = obs_data_get_string(array_obj, "transition");
const char* file = obs_data_get_string(array_obj, "file");
const char* text = obs_data_get_string(array_obj, "text");
switcher->fileSwitches.emplace_back(
GetWeakSourceByName(scene), GetWeakTransitionByName(transition), file, text);
obs_data_release(array_obj);
}
string autoStopScene = obs_data_get_string(obj, "autoStopSceneName");
switcher->autoStopEnable = obs_data_get_bool(obj, "autoStopEnable");
switcher->autoStopScene = GetWeakSourceByName(autoStopScene.c_str());
@ -811,27 +891,31 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
string idleTransitionName = obs_data_get_string(obj, "idleTransitionName");
switcher->idleData.scene = GetWeakSourceByName(idleSceneName.c_str());
switcher->idleData.transition = GetWeakTransitionByName(idleTransitionName.c_str());
obs_data_set_default_bool(obj, "idleEnable", false);
switcher->idleData.idleEnable = obs_data_get_bool(obj, "idleEnable");
obs_data_set_default_int(obj, "idleTime", DEFAULT_IDLE_TIME);
switcher->idleData.time = obs_data_get_int(obj, "idleTime");
obs_data_set_default_bool(obj, "readEnabled", false);
switcher->fileIO.readEnabled = obs_data_get_bool(obj, "readEnabled");
switcher->fileIO.readPath = obs_data_get_string(obj, "readPath");
obs_data_set_default_bool(obj, "writeEnabled", false);
switcher->fileIO.writeEnabled = obs_data_get_bool(obj, "writeEnabled");
switcher->fileIO.writePath = obs_data_get_string(obj, "writePath");
obs_data_set_default_string(obj, "priority0", DEFAULT_PRIORITY_0);
obs_data_set_default_string(obj, "priority1", DEFAULT_PRIORITY_1);
obs_data_set_default_string(obj, "priority2", DEFAULT_PRIORITY_2);
obs_data_set_default_string(obj, "priority3", DEFAULT_PRIORITY_3);
obs_data_set_default_string(obj, "priority4", DEFAULT_PRIORITY_4);
obs_data_set_default_string(obj, "priority5", DEFAULT_PRIORITY_5);
obs_data_set_default_int(obj, "priority0", DEFAULT_PRIORITY_0);
obs_data_set_default_int(obj, "priority1", DEFAULT_PRIORITY_1);
obs_data_set_default_int(obj, "priority2", DEFAULT_PRIORITY_2);
obs_data_set_default_int(obj, "priority3", DEFAULT_PRIORITY_3);
obs_data_set_default_int(obj, "priority4", DEFAULT_PRIORITY_4);
obs_data_set_default_int(obj, "priority5", DEFAULT_PRIORITY_5);
switcher->functionNamesByPriority[0] = (obs_data_get_string(obj, "priority0"));
switcher->functionNamesByPriority[1] = (obs_data_get_string(obj, "priority1"));
switcher->functionNamesByPriority[2] = (obs_data_get_string(obj, "priority2"));
switcher->functionNamesByPriority[3] = (obs_data_get_string(obj, "priority3"));
switcher->functionNamesByPriority[4] = (obs_data_get_string(obj, "priority4"));
switcher->functionNamesByPriority[5] = (obs_data_get_string(obj, "priority5"));
switcher->functionNamesByPriority[0] = (obs_data_get_int(obj, "priority0"));
switcher->functionNamesByPriority[1] = (obs_data_get_int(obj, "priority1"));
switcher->functionNamesByPriority[2] = (obs_data_get_int(obj, "priority2"));
switcher->functionNamesByPriority[3] = (obs_data_get_int(obj, "priority3"));
switcher->functionNamesByPriority[4] = (obs_data_get_int(obj, "priority4"));
switcher->functionNamesByPriority[5] = (obs_data_get_int(obj, "priority5"));
if (!switcher->prioFuncsValid())
{
switcher->functionNamesByPriority[0] = (DEFAULT_PRIORITY_0);
@ -852,6 +936,7 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*)
obs_data_array_release(executableArray);
obs_data_array_release(ignoreIdleWindowsArray);
obs_data_array_release(randomArray);
obs_data_array_release(fileArray);
obs_data_release(obj);
@ -921,7 +1006,7 @@ void SwitcherData::Thread()
//to avoid scene duplication when rapidly switching scene collection
this_thread::sleep_for(chrono::seconds(2));
int extraSleep = 0;
int sleep = 0;
while (true)
{
@ -931,11 +1016,11 @@ void SwitcherData::Thread()
OBSWeakSource scene;
OBSWeakSource transition;
chrono::milliseconds duration;
if (extraSleep > interval)
duration = chrono::milliseconds(extraSleep);
if (sleep > interval)
duration = chrono::milliseconds(sleep);
else
duration = chrono::milliseconds(interval);
extraSleep = 0;
sleep = 0;
switcher->Prune();
writeSceneInfoToFile();
//sleep for a bit
@ -954,30 +1039,27 @@ void SwitcherData::Thread()
continue;
}
for (string switchFuncName : functionNamesByPriority)
for (int switchFuncName : functionNamesByPriority)
{
if (switchFuncName == READ_FILE_FUNC)
{
switch (switchFuncName) {
case READ_FILE_FUNC:
checkSwitchInfoFromFile(match, scene, transition);
}
if (switchFuncName == IDLE_FUNC)
{
checkFileContent(match, scene, transition);
break;
case IDLE_FUNC:
checkIdleSwitch(match, scene, transition);
}
if (switchFuncName == EXE_FUNC)
{
break;
case EXE_FUNC:
checkExeSwitch(match, scene, transition);
}
if (switchFuncName == SCREEN_REGION_FUNC)
{
break;
case SCREEN_REGION_FUNC:
checkScreenRegionSwitch(match, scene, transition);
}
if (switchFuncName == WINDOW_TITLE_FUNC)
{
break;
case WINDOW_TITLE_FUNC:
checkWindowTitleSwitch(match, scene, transition);
}
if (switchFuncName == ROUND_TRIP_FUNC)
{
break;
case ROUND_TRIP_FUNC:
checkSceneRoundTrip(match, scene, transition, lock);
if (sceneChangedDuringWait()) //scene might have changed during the sleep
{
@ -1002,7 +1084,7 @@ void SwitcherData::Thread()
}
if (!match && switchIfNotMatching == RANDOM_SWITCH)
{
checkRandom(match, scene, transition, extraSleep);
checkRandom(match, scene, transition, sleep);
}
if (match)
{

View File

@ -109,6 +109,11 @@ public slots:
void on_randomRemove_clicked();
void on_randomScenesList_currentRowChanged(int idx);
void on_fileAdd_clicked();
void on_fileRemove_clicked();
void on_fileScenesList_currentRowChanged(int idx);
void on_browseButton_3_clicked();
void on_priorityUp_clicked();
void on_priorityDown_clicked();

View File

@ -7,10 +7,10 @@
void SceneSwitcher::on_browseButton_clicked()
{
QString directory = QFileDialog::getOpenFileName(
QString path = QFileDialog::getOpenFileName(
this, tr("Select a file to write to ..."), QDir::currentPath(), tr("Text files (*.txt)"));
if (!directory.isEmpty())
ui->writePathLineEdit->setText(directory);
if (!path.isEmpty())
ui->writePathLineEdit->setText(path);
}
void SceneSwitcher::on_readFileCheckBox_stateChanged(int state)
@ -65,15 +65,15 @@ void SceneSwitcher::on_writePathLineEdit_textChanged(const QString& text)
void SceneSwitcher::on_browseButton_2_clicked()
{
QString directory = QFileDialog::getOpenFileName(
QString path = QFileDialog::getOpenFileName(
this, tr("Select a file to read from ..."), QDir::currentPath(), tr("Text files (*.txt)"));
if (!directory.isEmpty())
ui->readPathLineEdit->setText(directory);
if (!path.isEmpty())
ui->readPathLineEdit->setText(path);
}
void SwitcherData::writeSceneInfoToFile()
{
if (!fileIO.writeEnabled)
if (!fileIO.writeEnabled || fileIO.writePath.empty())
return;
obs_source_t* currentSource = obs_frontend_get_current_scene();
@ -114,3 +114,126 @@ void SwitcherData::checkSwitchInfoFromFile(bool& match, OBSWeakSource& scene, OB
file.close();
}
}
void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSource& transition)
{
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;
/*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.
*If you are reading this and know of a cleaner way to do this, please let me know :)
*/
QTextStream in(&file);
QTextStream text(&t);
while (!in.atEnd() && !text.atEnd())
{
QString fileLine = in.readLine();
QString textLine = text.readLine();
if (QString::compare(fileLine, textLine, Qt::CaseSensitive) != 0)
{
equal = false;
break;
}
else {
equal = true;
}
}
file.close();
if (equal) {
scene = s.scene;
transition = s.transition;
match = true;
break;
}
}
}
void SceneSwitcher::on_browseButton_3_clicked()
{
QString path = QFileDialog::getOpenFileName(
this, tr("Select a file to read from ..."), QDir::currentPath(), tr("Text files (*.txt)"));
if (!path.isEmpty())
ui->filePathLineEdit->setText(path);
}
void SceneSwitcher::on_fileAdd_clicked()
{
QString sceneName = ui->fileScenes->currentText();
QString transitionName = ui->fileTransitions->currentText();
QString fileName = ui->filePathLineEdit->text();
QString text = ui->fileTextEdit->toPlainText();
//QFile file(QString::fromStdString(fileName)); //don't check if file exists because it might not yet exist
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);
QVariant v = QVariant::fromValue(switchText);
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());
}
void SceneSwitcher::on_fileRemove_clicked()
{
QListWidgetItem* item = ui->fileScenesList->currentItem();
if (!item)
return;
int idx = ui->fileScenesList->currentRow();
if (idx == -1)
return;
{
lock_guard<mutex> lock(switcher->m);
auto& switches = switcher->fileSwitches;
switches.erase(switches.begin() + idx);
}
qDeleteAll(ui->fileScenesList->selectedItems());
//delete item;
}
void SceneSwitcher::on_fileScenesList_currentRowChanged(int idx)
{
if (loading)
return;
if (idx == -1)
return;
lock_guard<mutex> lock(switcher->m);
if (switcher->fileSwitches.size() <= idx)
return;
FileSwitch s = switcher->fileSwitches[idx];
string sceneName = GetWeakSourceName(s.scene);
string transitionName = GetWeakSourceName(s.transition);
ui->fileScenes->setCurrentText(sceneName.c_str());
ui->fileTransitions->setCurrentText(transitionName.c_str());
ui->fileTextEdit->setPlainText(s.text.c_str());
ui->filePathLineEdit->setText(s.file.c_str());
}

View File

@ -25,101 +25,11 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_31">
<item>
<spacer name="horizontalSpacer_29">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="description">
<property name="text">
<string>Order the different switching methods in order of their priority (with the highest priority being at the top):</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_30">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="priorityList"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_32">
<item>
<widget class="QPushButton" name="priorityUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/up.png</normaloff>../../../forms/images/up.png</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">upArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="priorityDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/down.png</normaloff>../../../forms/images/down.png</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">downArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_31">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
<widget class="Line" name="line_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
@ -296,12 +206,96 @@
</layout>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>(You can set a Hotkey to start and stop the scene switcher under Settings / Hotkeys / Toggle Start Stop for the Advanced Scene Switcher)</string>
<widget class="Line" name="line_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_31">
<item>
<widget class="QLabel" name="description">
<property name="text">
<string>Order the different switching methods in order of their priority (with the highest priority being at the top):</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_30">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="priorityList"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_32">
<item>
<widget class="QPushButton" name="priorityUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/up.png</normaloff>../../../forms/images/up.png</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">upArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="priorityDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/down.png</normaloff>../../../forms/images/down.png</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">downArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_31">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_33">
<item>
@ -342,6 +336,20 @@
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>(You can set a Hotkey to start and stop the scene switcher under Settings / Hotkeys / Toggle Start Stop for the Advanced Scene Switcher)</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="close">
<property name="text">
@ -474,6 +482,13 @@
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
@ -589,6 +604,20 @@
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_47">
<property name="text">
<string>(If you want to add OBS itself as a window title use &quot;OBS&quot; - If you want to add ALT + TAB add &quot;Task Switching&quot;)</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="screenRegionTab">
@ -1520,6 +1549,13 @@
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_34">
<item>
@ -1791,6 +1827,13 @@
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="transitionWarning">
<property name="text">
@ -2066,7 +2109,7 @@
<attribute name="title">
<string> Write To File / Read From File </string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
@ -2089,52 +2132,216 @@
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_10">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<widget class="QCheckBox" name="readFileCheckBox">
<property name="text">
<string>Enable switching of scenes based on file input</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
<widget class="QCheckBox" name="readFileCheckBox">
<property name="text">
<string>Enable switching of scenes based on file input</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QLabel" name="label_16">
<property name="text">
<string>Read scene name to be switched to from this file:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="readPathLineEdit"/>
</item>
<item>
<widget class="QPushButton" name="browseButton_2">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_39">
<property name="text">
<string>Switch scene based on file contents:</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_36">
<item>
<widget class="QLabel" name="label_16">
<widget class="QLabel" name="label_44">
<property name="text">
<string>Read scene to be switched to from this file:</string>
<string>If the file</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="readPathLineEdit"/>
<widget class="QLineEdit" name="filePathLineEdit"/>
</item>
<item>
<widget class="QPushButton" name="browseButton_2">
<widget class="QPushButton" name="browseButton_3">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_40">
<property name="text">
<string>contains:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPlainTextEdit" name="fileTextEdit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_38">
<item>
<widget class="QLabel" name="label_45">
<property name="text">
<string>switch to</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="fileScenes">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_46">
<property name="text">
<string>using</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="fileTransitions"/>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="fileScenesList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sortingEnabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_35">
<item>
<widget class="QPushButton" name="fileAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">addIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="fileRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_38">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>

View File

@ -27,29 +27,17 @@ void SceneSwitcher::on_priorityDown_clicked()
}
}
bool prioStrValid(string s)
{
if (s == WINDOW_TITLE_FUNC)
return true;
if (s == SCREEN_REGION_FUNC)
return true;
if (s == ROUND_TRIP_FUNC)
return true;
if (s == (IDLE_FUNC))
return true;
if (s == EXE_FUNC)
return true;
if (s == READ_FILE_FUNC)
return true;
return false;
}
bool SwitcherData::prioFuncsValid()
{
for (string f : functionNamesByPriority)
auto it = std::unique(functionNamesByPriority.begin(), functionNamesByPriority.end());
bool wasUnique = (it == functionNamesByPriority.end());
if (!wasUnique)
return false;
for (int p : functionNamesByPriority)
{
if (!prioStrValid(f))
if (p < 0 || p > 5)
return false;
}
return true;

View File

@ -124,11 +124,10 @@ void SceneSwitcher::on_randomRemove_clicked()
void SwitcherData::checkRandom(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, int& delay)
{
int size = randomSwitches.size();
if (randomSwitches.size() == 0)
return;
vector<RandomSwitch> rs = randomSwitches;
vector<RandomSwitch> rs (randomSwitches);
std::random_shuffle(rs.begin(), rs.end());
for (RandomSwitch& r : rs)
{

View File

@ -11,12 +11,14 @@
#define DEFAULT_INTERVAL 300
#define READ_FILE_FUNC "File based"
#define ROUND_TRIP_FUNC "Scene Sequence"
#define IDLE_FUNC "Idle detection"
#define EXE_FUNC "Executable"
#define SCREEN_REGION_FUNC "Screen region"
#define WINDOW_TITLE_FUNC "Window title"
#define DEFAULT_IDLE_TIME 60
#define READ_FILE_FUNC 0
#define ROUND_TRIP_FUNC 1
#define IDLE_FUNC 2
#define EXE_FUNC 3
#define SCREEN_REGION_FUNC 4
#define WINDOW_TITLE_FUNC 5
#define DEFAULT_PRIORITY_0 READ_FILE_FUNC
#define DEFAULT_PRIORITY_1 ROUND_TRIP_FUNC
@ -149,18 +151,35 @@ struct DefaultSceneTransition
}
};
struct FileSwitch
{
OBSWeakSource scene;
OBSWeakSource transition;
string file;
string text;
inline FileSwitch(
OBSWeakSource scene_, OBSWeakSource transition_, const char* file_, const char* text_)
: scene(scene_)
, transition(transition_)
, file(file_)
, text(text_)
{
}
};
struct FileIOData
{
bool readEnabled;
bool readEnabled = false;
string readPath;
bool writeEnabled;
bool writeEnabled = false;
string writePath;
};
struct IdleData
{
bool idleEnable;
int time;
bool idleEnable = false;
int time = DEFAULT_IDLE_TIME;
OBSWeakSource scene;
OBSWeakSource transition;
};
@ -188,7 +207,7 @@ struct SwitcherData
OBSWeakSource nonMatchingScene;
OBSWeakSource lastRandomScene;
int interval = DEFAULT_INTERVAL;
NoMatch switchIfNotMatching;
NoMatch switchIfNotMatching = NO_SWITCH;
bool startAtLaunch = false;
vector<ScreenRegionSwitch> screenRegionSwitches;
vector<OBSWeakSource> pauseScenesSwitches;
@ -196,6 +215,7 @@ struct SwitcherData
vector<string> ignoreWindowsSwitches;
vector<SceneRoundTripSwitch> sceneRoundTripSwitches;
vector<RandomSwitch> randomSwitches;
vector<FileSwitch> fileSwitches;
bool autoStopEnable = false;
OBSWeakSource autoStopScene;
string waitSceneName; //indicates which scene was active when we startet waiting on something
@ -205,13 +225,13 @@ struct SwitcherData
FileIOData fileIO;
IdleData idleData;
vector<string> ignoreIdleWindows;
vector<string> functionNamesByPriority = vector<string>{
string(DEFAULT_PRIORITY_0),
string(DEFAULT_PRIORITY_1),
string(DEFAULT_PRIORITY_2),
string(DEFAULT_PRIORITY_3),
string(DEFAULT_PRIORITY_4),
string(DEFAULT_PRIORITY_5),
vector<int> functionNamesByPriority = vector<int>{
DEFAULT_PRIORITY_0,
DEFAULT_PRIORITY_1,
DEFAULT_PRIORITY_2,
DEFAULT_PRIORITY_3,
DEFAULT_PRIORITY_4,
DEFAULT_PRIORITY_5,
};
void Thread();
@ -230,6 +250,7 @@ struct SwitcherData
void checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition);
void checkScreenRegionSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition);
void checkSwitchInfoFromFile(bool& match, OBSWeakSource& scene, OBSWeakSource& transition);
void checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSource& transition);
void checkRandom(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, int& delay);
@ -306,6 +327,13 @@ struct SwitcherData
executableSwitches.erase(executableSwitches.begin() + i--);
}
for (size_t i = 0; i < fileSwitches.size(); i++)
{
FileSwitch& s = fileSwitches[i];
if (!WeakSourceValid(s.scene) || !WeakSourceValid(s.transition))
fileSwitches.erase(fileSwitches.begin() + i--);
}
if (!WeakSourceValid(idleData.scene) || !WeakSourceValid(idleData.transition))
{
idleData.idleEnable = false;

View File

@ -69,6 +69,18 @@ static inline QString MakeRandomSwitchName(
+ QString::number(delay) + QStringLiteral(" seconds");
}
static inline QString MakeFileSwitchName(
const QString& scene, const QString& transition, const QString& fileName, const QString& text)
{
if (text.length() > 30)
return QStringLiteral("Switch to ") + scene + QStringLiteral(" using ") + transition + QStringLiteral(" if ")
+ fileName + QStringLiteral(" contains: \n\"") + text.left(27) + QStringLiteral("...\"");
else
return QStringLiteral("Switch to ") + scene + QStringLiteral(" using ") + transition + QStringLiteral(" if ")
+ fileName + QStringLiteral(" contains: \n\"") + text + QStringLiteral("\"");
}
static inline string GetWeakSourceName(obs_weak_source_t* weak_source)
{
string name;