From 38bd59c1fdde57179450e6f724659d96c7ced019 Mon Sep 17 00:00:00 2001 From: Exeldro Date: Sun, 19 Apr 2020 20:26:24 +0200 Subject: [PATCH] add media --- CMakeLists.txt | 2 + forms/advanced-scene-switcher.ui | 170 +++ src/advanced-scene-switcher.cpp | 1287 ++++++++++++++--------- src/headers/advanced-scene-switcher.hpp | 49 +- src/headers/switcher-data-structs.hpp | 336 +++--- src/headers/utility.hpp | 180 +++- src/media-switch.cpp | 87 ++ src/priority.cpp | 2 +- 8 files changed, 1387 insertions(+), 726 deletions(-) create mode 100644 src/media-switch.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d81279b8..1f1079da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ if(BUILD_OUT_OF_TREE) src/scene-round-trip.cpp src/file-switch.cpp src/window-title-switch.cpp + src/media-switch.cpp src/hotkey.cpp src/general.cpp src/pause-switch.cpp @@ -175,6 +176,7 @@ else () src/scene-round-trip.cpp src/file-switch.cpp src/window-title-switch.cpp + src/media-switch.cpp src/hotkey.cpp src/general.cpp src/pause-switch.cpp diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index fe134d3e..1564578c 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -2373,6 +2373,176 @@ + + + Media + + + + + + + + When + + + + + + + + + + state is + + + + + + + + + + and + + + + + + + + + + ms + + + 00 + + + 1000000 + + + + + + + switch to + + + + + + + + 100 + 0 + + + + + + + + using the + + + + + + + + + + transition + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + true + + + true + + + + + + + 4 + + + + + + 22 + 22 + + + + true + + + addIconSmall + + + + + + + + 22 + 22 + + + + true + + + removeIconSmall + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Implemented by Exeldro + + + + + + + diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index bd102e1c..35d7ff50 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -24,16 +24,13 @@ #include "headers/utility.hpp" #include "headers/advanced-scene-switcher.hpp" - -SwitcherData* switcher = nullptr; - +SwitcherData *switcher = nullptr; /******************************************************************************** * Create the Advanced Scene Switcher settings window ********************************************************************************/ -SceneSwitcher::SceneSwitcher(QWidget* parent) - : QDialog(parent) - , ui(new Ui_SceneSwitcher) +SceneSwitcher::SceneSwitcher(QWidget *parent) + : QDialog(parent), ui(new Ui_SceneSwitcher) { ui->setupUi(this); @@ -41,11 +38,10 @@ SceneSwitcher::SceneSwitcher(QWidget* parent) switcher->Prune(); - BPtr scenes = obs_frontend_get_scene_names(); - char** temp = scenes; - while (*temp) - { - const char* name = *temp; + BPtr scenes = obs_frontend_get_scene_names(); + char **temp = scenes; + while (*temp) { + const char *name = *temp; ui->scenes->addItem(name); ui->noMatchSwitchScene->addItem(name); ui->screenRegionScenes->addItem(name); @@ -60,18 +56,47 @@ SceneSwitcher::SceneSwitcher(QWidget* parent) ui->idleScenes->addItem(name); ui->randomScenes->addItem(name); ui->fileScenes->addItem(name); + ui->mediaScenes->addItem(name); temp++; } + auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ + { + QComboBox *combo = reinterpret_cast(data); + if (obs_source_media_get_state(source) != + OBS_MEDIA_STATE_NONE) { + const char *name = obs_source_get_name(source); + combo->addItem(name); + } + return true; + }; + + obs_enum_sources(sourceEnum, ui->mediaSources); + + ui->mediaStates->addItem("None"); + ui->mediaStates->addItem("Playing"); + ui->mediaStates->addItem("Opening"); + ui->mediaStates->addItem("Buffering"); + ui->mediaStates->addItem("Paused"); + ui->mediaStates->addItem("Stopped"); + ui->mediaStates->addItem("Ended"); + ui->mediaStates->addItem("Error"); + + ui->mediaTimeRestrictions->addItem("None"); + ui->mediaTimeRestrictions->addItem("Time shorter"); + ui->mediaTimeRestrictions->addItem("Time longer"); + ui->mediaTimeRestrictions->addItem("Time remaining shorter"); + ui->mediaTimeRestrictions->addItem("Time remaining longer"); + ui->sceneRoundTripScenes2->addItem(PREVIOUS_SCENE_NAME); ui->idleScenes->addItem(PREVIOUS_SCENE_NAME); - obs_frontend_source_list* transitions = new obs_frontend_source_list(); + obs_frontend_source_list *transitions = new obs_frontend_source_list(); obs_frontend_get_transitions(transitions); - for (size_t i = 0; i < transitions->sources.num; i++) - { - const char* name = obs_source_get_name(transitions->sources.array[i]); + for (size_t i = 0; i < transitions->sources.num; i++) { + const char *name = + obs_source_get_name(transitions->sources.array[i]); ui->transitions->addItem(name); ui->screenRegionsTransitions->addItem(name); ui->sceneRoundTripTransitions->addItem(name); @@ -81,33 +106,29 @@ SceneSwitcher::SceneSwitcher(QWidget* parent) ui->idleTransitions->addItem(name); ui->randomTransitions->addItem(name); ui->fileTransitions->addItem(name); + ui->mediaTransitions->addItem(name); } obs_frontend_source_list_free(transitions); - if (switcher->switchIfNotMatching == SWITCH) - { + if (switcher->switchIfNotMatching == SWITCH) { ui->noMatchSwitch->setChecked(true); ui->noMatchSwitchScene->setEnabled(true); - } - else if (switcher->switchIfNotMatching == NO_SWITCH) - { + } else if (switcher->switchIfNotMatching == NO_SWITCH) { ui->noMatchDontSwitch->setChecked(true); ui->noMatchSwitchScene->setEnabled(false); - } - else - { + } else { ui->noMatchRandomSwitch->setChecked(true); ui->noMatchSwitchScene->setEnabled(false); } - ui->noMatchSwitchScene->setCurrentText(GetWeakSourceName(switcher->nonMatchingScene).c_str()); + ui->noMatchSwitchScene->setCurrentText( + GetWeakSourceName(switcher->nonMatchingScene).c_str()); ui->checkInterval->setValue(switcher->interval); vector windows; GetWindowList(windows); - for (string& window : windows) - { + for (string &window : windows) { ui->windows->addItem(window.c_str()); ui->ignoreWindowsWindows->addItem(window.c_str()); ui->pauseWindowsWindows->addItem(window.c_str()); @@ -116,180 +137,200 @@ SceneSwitcher::SceneSwitcher(QWidget* parent) QStringList processes; GetProcessList(processes); - for (QString& process : processes) + for (QString &process : processes) ui->executable->addItem(process); - for (auto& s : switcher->executableSwitches) - { + for (auto &s : switcher->executableSwitches) { string sceneName = GetWeakSourceName(s.mScene); string transitionName = GetWeakSourceName(s.mTransition); - QString text = MakeSwitchNameExecutable( - sceneName.c_str(), s.mExe, transitionName.c_str(), s.mInFocus); + QString text = MakeSwitchNameExecutable(sceneName.c_str(), + s.mExe, + transitionName.c_str(), + s.mInFocus); - QListWidgetItem* item = new QListWidgetItem(text, ui->executables); + QListWidgetItem *item = + new QListWidgetItem(text, ui->executables); item->setData(Qt::UserRole, s.mExe); } - for (auto& s : switcher->windowSwitches) - { + 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); - QListWidgetItem* item = new QListWidgetItem(text, ui->switches); + QListWidgetItem *item = new QListWidgetItem(text, ui->switches); item->setData(Qt::UserRole, s.window.c_str()); } - for (auto& s : switcher->screenRegionSwitches) - { + for (auto &s : switcher->screenRegionSwitches) { string sceneName = GetWeakSourceName(s.scene); string transitionName = GetWeakSourceName(s.transition); QString text = MakeScreenRegionSwitchName( - sceneName.c_str(), transitionName.c_str(), s.minX, s.minY, s.maxX, s.maxY); + sceneName.c_str(), transitionName.c_str(), s.minX, + s.minY, s.maxX, s.maxY); - QListWidgetItem* item = new QListWidgetItem(text, ui->screenRegions); + QListWidgetItem *item = + new QListWidgetItem(text, ui->screenRegions); item->setData(Qt::UserRole, s.regionStr.c_str()); } ui->autoStopSceneCheckBox->setChecked(switcher->autoStopEnable); - ui->autoStopScenes->setCurrentText(GetWeakSourceName(switcher->autoStopScene).c_str()); + ui->autoStopScenes->setCurrentText( + GetWeakSourceName(switcher->autoStopScene).c_str()); - if (ui->autoStopSceneCheckBox->checkState()) - { + if (ui->autoStopSceneCheckBox->checkState()) { ui->autoStopScenes->setDisabled(false); - } - else - { + } else { ui->autoStopScenes->setDisabled(true); } - for (auto& scene : switcher->pauseScenesSwitches) - { + for (auto &scene : switcher->pauseScenesSwitches) { string sceneName = GetWeakSourceName(scene); QString text = QString::fromStdString(sceneName); - QListWidgetItem* item = new QListWidgetItem(text, ui->pauseScenes); + QListWidgetItem *item = + new QListWidgetItem(text, ui->pauseScenes); item->setData(Qt::UserRole, text); } - for (auto& window : switcher->pauseWindowsSwitches) - { + for (auto &window : switcher->pauseWindowsSwitches) { QString text = QString::fromStdString(window); - QListWidgetItem* item = new QListWidgetItem(text, ui->pauseWindows); + QListWidgetItem *item = + new QListWidgetItem(text, ui->pauseWindows); item->setData(Qt::UserRole, text); } - for (auto& window : switcher->ignoreWindowsSwitches) - { + for (auto &window : switcher->ignoreWindowsSwitches) { QString text = QString::fromStdString(window); - QListWidgetItem* item = new QListWidgetItem(text, ui->ignoreWindows); + QListWidgetItem *item = + new QListWidgetItem(text, ui->ignoreWindows); item->setData(Qt::UserRole, text); } int smallestDelay = switcher->interval; - for (auto& s : switcher->sceneRoundTripSwitches) - { - string sceneName1 = GetWeakSourceName(s.scene1); - string sceneName2 = (s.usePreviousScene) ? PREVIOUS_SCENE_NAME : GetWeakSourceName(s.scene2); + for (auto &s : switcher->sceneRoundTripSwitches) { + string sceneName1 = GetWeakSourceName(s.scene1); + string sceneName2 = (s.usePreviousScene) + ? PREVIOUS_SCENE_NAME + : GetWeakSourceName(s.scene2); string transitionName = GetWeakSourceName(s.transition); QString text = MakeSceneRoundTripSwitchName( - sceneName1.c_str(), sceneName2.c_str(), transitionName.c_str(), (double)s.delay / 1000); + sceneName1.c_str(), sceneName2.c_str(), + transitionName.c_str(), (double)s.delay / 1000); - QListWidgetItem* item = new QListWidgetItem(text, ui->sceneRoundTrips); + QListWidgetItem *item = + new QListWidgetItem(text, ui->sceneRoundTrips); item->setData(Qt::UserRole, text); if (s.delay < smallestDelay) smallestDelay = s.delay; } - (smallestDelay < switcher->interval) ? ui->intervalWarning->setVisible(true) : ui->intervalWarning->setVisible(false); + (smallestDelay < switcher->interval) + ? ui->intervalWarning->setVisible(true) + : ui->intervalWarning->setVisible(false); - for (auto& s : switcher->sceneTransitions) - { + for (auto &s : switcher->sceneTransitions) { string sceneName1 = GetWeakSourceName(s.scene1); string sceneName2 = GetWeakSourceName(s.scene2); string transitionName = GetWeakSourceName(s.transition); - QString text = MakeSceneTransitionName( - sceneName1.c_str(), sceneName2.c_str(), transitionName.c_str()); + QString text = MakeSceneTransitionName(sceneName1.c_str(), + sceneName2.c_str(), + transitionName.c_str()); - QListWidgetItem* item = new QListWidgetItem(text, ui->sceneTransitions); + QListWidgetItem *item = + new QListWidgetItem(text, ui->sceneTransitions); item->setData(Qt::UserRole, text); } //(transitionDurationLongerThanInterval(switcher->interval)) ? ui->transitionWarning->setVisible(true) : ui->transitionWarning->setVisible(false); - for (auto& s : switcher->defaultSceneTransitions) - { + for (auto &s : switcher->defaultSceneTransitions) { string sceneName = GetWeakSourceName(s.scene); string transitionName = GetWeakSourceName(s.transition); QString text = MakeDefaultSceneTransitionName( sceneName.c_str(), transitionName.c_str()); - QListWidgetItem* item = new QListWidgetItem(text, ui->defaultTransitions); + QListWidgetItem *item = + new QListWidgetItem(text, ui->defaultTransitions); item->setData(Qt::UserRole, text); } - for (auto& window : switcher->ignoreIdleWindows) - { + for (auto &window : switcher->ignoreIdleWindows) { QString text = QString::fromStdString(window); - QListWidgetItem* item = new QListWidgetItem(text, ui->ignoreIdleWindows); + QListWidgetItem *item = + new QListWidgetItem(text, ui->ignoreIdleWindows); item->setData(Qt::UserRole, text); } - for (auto& s : switcher->randomSwitches) - { + for (auto &s : switcher->randomSwitches) { string sceneName = GetWeakSourceName(s.scene); string transitionName = GetWeakSourceName(s.transition); QString text = MakeRandomSwitchName( sceneName.c_str(), transitionName.c_str(), s.delay); - QListWidgetItem* item = new QListWidgetItem(text, ui->randomScenesList); + QListWidgetItem *item = + new QListWidgetItem(text, ui->randomScenesList); item->setData(Qt::UserRole, text); } - for (auto& s : switcher->fileSwitches) - { + 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(), s.useRegex, s.useTime); + sceneName.c_str(), transitionName.c_str(), + s.file.c_str(), s.text.c_str(), s.useRegex, s.useTime); - QListWidgetItem* item = new QListWidgetItem(listText, ui->fileScenesList); + QListWidgetItem *item = + new QListWidgetItem(listText, ui->fileScenesList); + item->setData(Qt::UserRole, listText); + } + + for (auto &s : switcher->mediaSwitches) { + string sourceName = GetWeakSourceName(s.source); + string sceneName = GetWeakSourceName(s.scene); + string transitionName = GetWeakSourceName(s.transition); + QString listText = MakeMediaSwitchName( + sourceName.c_str(), sceneName.c_str(), + transitionName.c_str(), s.state, s.restriction, s.time); + + QListWidgetItem *item = + new QListWidgetItem(listText, ui->mediaSwitches); item->setData(Qt::UserRole, listText); } ui->idleCheckBox->setChecked(switcher->idleData.idleEnable); ui->idleScenes->setCurrentText( - switcher->idleData.usePreviousScene ? PREVIOUS_SCENE_NAME : GetWeakSourceName(switcher->idleData.scene).c_str()); - ui->idleTransitions->setCurrentText(GetWeakSourceName(switcher->idleData.transition).c_str()); + switcher->idleData.usePreviousScene + ? PREVIOUS_SCENE_NAME + : GetWeakSourceName(switcher->idleData.scene).c_str()); + ui->idleTransitions->setCurrentText( + GetWeakSourceName(switcher->idleData.transition).c_str()); ui->idleSpinBox->setValue(switcher->idleData.time); - if (ui->idleCheckBox->checkState()) - { + if (ui->idleCheckBox->checkState()) { ui->idleScenes->setDisabled(false); ui->idleSpinBox->setDisabled(false); ui->idleTransitions->setDisabled(false); - } - else - { + } else { ui->idleScenes->setDisabled(true); ui->idleSpinBox->setDisabled(true); ui->idleTransitions->setDisabled(true); } - ui->readPathLineEdit->setText(QString::fromStdString(switcher->fileIO.readPath.c_str())); + ui->readPathLineEdit->setText( + QString::fromStdString(switcher->fileIO.readPath.c_str())); ui->readFileCheckBox->setChecked(switcher->fileIO.readEnabled); - ui->writePathLineEdit->setText(QString::fromStdString(switcher->fileIO.writePath.c_str())); + ui->writePathLineEdit->setText( + QString::fromStdString(switcher->fileIO.writePath.c_str())); - if (ui->readFileCheckBox->checkState()) - { + if (ui->readFileCheckBox->checkState()) { ui->browseButton_2->setDisabled(false); ui->readPathLineEdit->setDisabled(false); - } - else - { + } else { ui->browseButton_2->setDisabled(true); ui->readPathLineEdit->setDisabled(true); } @@ -302,12 +343,12 @@ SceneSwitcher::SceneSwitcher(QWidget* parent) loading = false; // screen region cursor position - QTimer* screenRegionTimer = new QTimer(this); - connect(screenRegionTimer, SIGNAL(timeout()), this, SLOT(updateScreenRegionCursorPos())); + QTimer *screenRegionTimer = new QTimer(this); + connect(screenRegionTimer, SIGNAL(timeout()), this, + SLOT(updateScreenRegionCursorPos())); screenRegionTimer->start(1000); - for (int p : switcher->functionNamesByPriority) - { + for (int p : switcher->functionNamesByPriority) { string s = ""; switch (p) { case READ_FILE_FUNC: @@ -327,53 +368,65 @@ SceneSwitcher::SceneSwitcher(QWidget* parent) break; case WINDOW_TITLE_FUNC: s = "Window Title"; + break; + case MEDIA_FUNC: + s = "Media"; + break; } QString text(s.c_str()); - QListWidgetItem* item = new QListWidgetItem(text, ui->priorityList); + QListWidgetItem *item = + new QListWidgetItem(text, ui->priorityList); item->setData(Qt::UserRole, text); } - } - /******************************************************************************** * Saving and loading ********************************************************************************/ -static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) +static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) { - if (saving) - { + if (saving) { lock_guard lock(switcher->m); - obs_data_t* obj = obs_data_create(); - obs_data_array_t* array = obs_data_array_create(); - obs_data_array_t* screenRegionArray = obs_data_array_create(); - obs_data_array_t* pauseScenesArray = obs_data_array_create(); - obs_data_array_t* pauseWindowsArray = obs_data_array_create(); - obs_data_array_t* ignoreWindowsArray = obs_data_array_create(); - obs_data_array_t* sceneRoundTripArray = obs_data_array_create(); - obs_data_array_t* sceneTransitionsArray = obs_data_array_create(); - obs_data_array_t* defaultTransitionsArray = obs_data_array_create(); - 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(); + obs_data_t *obj = obs_data_create(); + obs_data_array_t *array = obs_data_array_create(); + obs_data_array_t *screenRegionArray = obs_data_array_create(); + obs_data_array_t *pauseScenesArray = obs_data_array_create(); + obs_data_array_t *pauseWindowsArray = obs_data_array_create(); + obs_data_array_t *ignoreWindowsArray = obs_data_array_create(); + obs_data_array_t *sceneRoundTripArray = obs_data_array_create(); + obs_data_array_t *sceneTransitionsArray = + obs_data_array_create(); + obs_data_array_t *defaultTransitionsArray = + obs_data_array_create(); + 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(); + obs_data_array_t *mediaArray = obs_data_array_create(); switcher->Prune(); - for (WindowSceneSwitch& s : switcher->windowSwitches) - { - obs_data_t* array_obj = obs_data_create(); + for (WindowSceneSwitch &s : switcher->windowSwitches) { + 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, "window_title", s.window.c_str()); - obs_data_set_bool(array_obj, "fullscreen", s.fullscreen); + 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, "window_title", + s.window.c_str()); + obs_data_set_bool(array_obj, "fullscreen", + s.fullscreen); obs_data_array_push_back(array, array_obj); obs_source_release(source); obs_source_release(transition); @@ -382,24 +435,32 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_release(array_obj); } - for (ScreenRegionSwitch& s : switcher->screenRegionSwitches) - { - obs_data_t* array_obj = obs_data_create(); + for (ScreenRegionSwitch &s : switcher->screenRegionSwitches) { + 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, "screenRegionScene", sceneName); - obs_data_set_string(array_obj, "transition", transitionName); + 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, + "screenRegionScene", + sceneName); + obs_data_set_string(array_obj, "transition", + transitionName); obs_data_set_int(array_obj, "minX", s.minX); obs_data_set_int(array_obj, "minY", s.minY); obs_data_set_int(array_obj, "maxX", s.maxX); obs_data_set_int(array_obj, "maxY", s.maxY); - obs_data_set_string(array_obj, "screenRegionStr", s.regionStr.c_str()); - obs_data_array_push_back(screenRegionArray, array_obj); + obs_data_set_string(array_obj, + "screenRegionStr", + s.regionStr.c_str()); + obs_data_array_push_back(screenRegionArray, + array_obj); obs_source_release(source); obs_source_release(transition); } @@ -407,58 +468,78 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_release(array_obj); } - for (OBSWeakSource& scene : switcher->pauseScenesSwitches) - { - obs_data_t* array_obj = obs_data_create(); + for (OBSWeakSource &scene : switcher->pauseScenesSwitches) { + obs_data_t *array_obj = obs_data_create(); - obs_source_t* source = obs_weak_source_get_source(scene); - if (source) - { - const char* n = obs_source_get_name(source); + obs_source_t *source = + obs_weak_source_get_source(scene); + if (source) { + const char *n = obs_source_get_name(source); obs_data_set_string(array_obj, "pauseScene", n); - obs_data_array_push_back(pauseScenesArray, array_obj); + obs_data_array_push_back(pauseScenesArray, + array_obj); obs_source_release(source); } obs_data_release(array_obj); } - for (string& window : switcher->pauseWindowsSwitches) - { - obs_data_t* array_obj = obs_data_create(); - obs_data_set_string(array_obj, "pauseWindow", window.c_str()); + for (string &window : switcher->pauseWindowsSwitches) { + obs_data_t *array_obj = obs_data_create(); + obs_data_set_string(array_obj, "pauseWindow", + window.c_str()); obs_data_array_push_back(pauseWindowsArray, array_obj); obs_data_release(array_obj); } - for (string& window : switcher->ignoreWindowsSwitches) - { - obs_data_t* array_obj = obs_data_create(); - obs_data_set_string(array_obj, "ignoreWindow", window.c_str()); + for (string &window : switcher->ignoreWindowsSwitches) { + obs_data_t *array_obj = obs_data_create(); + obs_data_set_string(array_obj, "ignoreWindow", + window.c_str()); obs_data_array_push_back(ignoreWindowsArray, array_obj); obs_data_release(array_obj); } - for (SceneRoundTripSwitch& s : switcher->sceneRoundTripSwitches) - { - obs_data_t* array_obj = obs_data_create(); + for (SceneRoundTripSwitch &s : + switcher->sceneRoundTripSwitches) { + obs_data_t *array_obj = obs_data_create(); - obs_source_t* source1 = obs_weak_source_get_source(s.scene1); - obs_source_t* source2 = obs_weak_source_get_source(s.scene2); - obs_source_t* transition = obs_weak_source_get_source(s.transition); - if (source1 && (s.usePreviousScene || source2) && transition) - { - const char* sceneName1 = obs_source_get_name(source1); - const char* sceneName2 = obs_source_get_name(source2); - const char* transitionName = obs_source_get_name(transition); - obs_data_set_string(array_obj, "sceneRoundTripScene1", sceneName1); - obs_data_set_string(array_obj, "sceneRoundTripScene2", - s.usePreviousScene ? PREVIOUS_SCENE_NAME : sceneName2); - obs_data_set_string(array_obj, "transition", transitionName); - obs_data_set_int(array_obj, "sceneRoundTripDelay", s.delay / 1000); //delay stored in two separate values - obs_data_set_int(array_obj, "sceneRoundTripDelayMs", s.delay % 1000); //to be compatible with older versions - obs_data_set_string(array_obj, "sceneRoundTripStr", s.sceneRoundTripStr.c_str()); - obs_data_array_push_back(sceneRoundTripArray, array_obj); + obs_source_t *source1 = + obs_weak_source_get_source(s.scene1); + obs_source_t *source2 = + obs_weak_source_get_source(s.scene2); + obs_source_t *transition = + obs_weak_source_get_source(s.transition); + if (source1 && (s.usePreviousScene || source2) && + transition) { + const char *sceneName1 = + obs_source_get_name(source1); + const char *sceneName2 = + obs_source_get_name(source2); + const char *transitionName = + obs_source_get_name(transition); + obs_data_set_string(array_obj, + "sceneRoundTripScene1", + sceneName1); + obs_data_set_string( + array_obj, "sceneRoundTripScene2", + s.usePreviousScene ? PREVIOUS_SCENE_NAME + : sceneName2); + obs_data_set_string(array_obj, "transition", + transitionName); + obs_data_set_int( + array_obj, "sceneRoundTripDelay", + s.delay / + 1000); //delay stored in two separate values + obs_data_set_int( + array_obj, "sceneRoundTripDelayMs", + s.delay % + 1000); //to be compatible with older versions + obs_data_set_string( + array_obj, "sceneRoundTripStr", + s.sceneRoundTripStr.c_str()); + obs_data_array_push_back(sceneRoundTripArray, + array_obj); obs_source_release(source1); obs_source_release(source2); obs_source_release(transition); @@ -467,23 +548,33 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_release(array_obj); } - for (SceneTransition& s : switcher->sceneTransitions) - { - obs_data_t* array_obj = obs_data_create(); + for (SceneTransition &s : switcher->sceneTransitions) { + obs_data_t *array_obj = obs_data_create(); - obs_source_t* source1 = obs_weak_source_get_source(s.scene1); - obs_source_t* source2 = obs_weak_source_get_source(s.scene2); - obs_source_t* transition = obs_weak_source_get_source(s.transition); - if (source1 && source2 && transition) - { - const char* sceneName1 = obs_source_get_name(source1); - const char* sceneName2 = obs_source_get_name(source2); - const char* transitionName = obs_source_get_name(transition); - obs_data_set_string(array_obj, "Scene1", sceneName1); - obs_data_set_string(array_obj, "Scene2", sceneName2); - obs_data_set_string(array_obj, "transition", transitionName); - obs_data_set_string(array_obj, "Str", s.sceneTransitionStr.c_str()); - obs_data_array_push_back(sceneTransitionsArray, array_obj); + obs_source_t *source1 = + obs_weak_source_get_source(s.scene1); + obs_source_t *source2 = + obs_weak_source_get_source(s.scene2); + obs_source_t *transition = + obs_weak_source_get_source(s.transition); + if (source1 && source2 && transition) { + const char *sceneName1 = + obs_source_get_name(source1); + const char *sceneName2 = + obs_source_get_name(source2); + const char *transitionName = + obs_source_get_name(transition); + obs_data_set_string(array_obj, "Scene1", + sceneName1); + obs_data_set_string(array_obj, "Scene2", + sceneName2); + obs_data_set_string(array_obj, "transition", + transitionName); + obs_data_set_string( + array_obj, "Str", + s.sceneTransitionStr.c_str()); + obs_data_array_push_back(sceneTransitionsArray, + array_obj); obs_source_release(source1); obs_source_release(source2); obs_source_release(transition); @@ -492,20 +583,28 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_release(array_obj); } - for (DefaultSceneTransition& s : switcher->defaultSceneTransitions) - { - obs_data_t* array_obj = obs_data_create(); + for (DefaultSceneTransition &s : + switcher->defaultSceneTransitions) { + 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, "Str", s.sceneTransitionStr.c_str()); - obs_data_array_push_back(defaultTransitionsArray, array_obj); + 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, "Str", + s.sceneTransitionStr.c_str()); + obs_data_array_push_back( + defaultTransitionsArray, array_obj); obs_source_release(source); obs_source_release(transition); } @@ -513,22 +612,29 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_release(array_obj); } - for (ExecutableSceneSwitch& s : switcher->executableSwitches) - { - obs_data_t* array_obj = obs_data_create(); + for (ExecutableSceneSwitch &s : switcher->executableSwitches) { + obs_data_t *array_obj = obs_data_create(); - obs_source_t* source = obs_weak_source_get_source(s.mScene); - obs_source_t* transition = obs_weak_source_get_source(s.mTransition); + obs_source_t *source = + obs_weak_source_get_source(s.mScene); + obs_source_t *transition = + obs_weak_source_get_source(s.mTransition); - 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, "exefile", s.mExe.toUtf8()); - obs_data_set_bool(array_obj, "infocus", s.mInFocus); - obs_data_array_push_back(executableArray, array_obj); + 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, "exefile", + s.mExe.toUtf8()); + obs_data_set_bool(array_obj, "infocus", + s.mInFocus); + obs_data_array_push_back(executableArray, + array_obj); obs_source_release(source); obs_source_release(transition); } @@ -536,22 +642,29 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_release(array_obj); } - for (RandomSwitch& s : switcher->randomSwitches) - { - obs_data_t* array_obj = obs_data_create(); + for (RandomSwitch &s : switcher->randomSwitches) { + 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); + 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_double(array_obj, "delay", s.delay); - obs_data_set_string(array_obj, "str", s.randomSwitchStr.c_str()); - obs_data_array_push_back(randomArray, array_obj); + 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_double(array_obj, "delay", + s.delay); + obs_data_set_string(array_obj, "str", + s.randomSwitchStr.c_str()); + obs_data_array_push_back(randomArray, + array_obj); obs_source_release(source); obs_source_release(transition); } @@ -559,31 +672,40 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_release(array_obj); } - for (string& window : switcher->ignoreIdleWindows) - { - obs_data_t* array_obj = obs_data_create(); - obs_data_set_string(array_obj, "window", window.c_str()); - obs_data_array_push_back(ignoreIdleWindowsArray, array_obj); + for (string &window : switcher->ignoreIdleWindows) { + obs_data_t *array_obj = obs_data_create(); + obs_data_set_string(array_obj, "window", + window.c_str()); + obs_data_array_push_back(ignoreIdleWindowsArray, + array_obj); obs_data_release(array_obj); } - for (FileSwitch& s : switcher->fileSwitches) - { - obs_data_t* array_obj = obs_data_create(); + 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); + 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_set_bool(array_obj, "useRegex", s.useRegex); - obs_data_set_bool(array_obj, "useTime", s.useTime); + 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_set_bool(array_obj, "useRegex", + s.useRegex); + obs_data_set_bool(array_obj, "useTime", + s.useTime); obs_data_array_push_back(fileArray, array_obj); obs_source_release(source); obs_source_release(transition); @@ -592,11 +714,49 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_release(array_obj); } - string nonMatchingSceneName = GetWeakSourceName(switcher->nonMatchingScene); + for (MediaSwitch &s : switcher->mediaSwitches) { + obs_data_t *array_obj = obs_data_create(); + + obs_source_t *source = + obs_weak_source_get_source(s.source); + obs_source_t *sceneSource = + obs_weak_source_get_source(s.scene); + obs_source_t *transition = + obs_weak_source_get_source(s.transition); + if (source && sceneSource && transition) { + const char *sourceName = + obs_source_get_name(source); + const char *sceneName = + obs_source_get_name(sceneSource); + const char *transitionName = + obs_source_get_name(transition); + obs_data_set_string(array_obj, "source", + sourceName); + obs_data_set_string(array_obj, "scene", + sceneName); + obs_data_set_string(array_obj, "transition", + transitionName); + obs_data_set_int(array_obj, "state", s.state); + obs_data_set_int(array_obj, "restriction", + s.restriction); + obs_data_set_int(array_obj, "time", s.time); + obs_data_array_push_back(mediaArray, array_obj); + } + obs_source_release(source); + obs_source_release(sceneSource); + obs_source_release(transition); + + obs_data_release(array_obj); + } + + string nonMatchingSceneName = + GetWeakSourceName(switcher->nonMatchingScene); obs_data_set_int(obj, "interval", switcher->interval); - obs_data_set_string(obj, "non_matching_scene", nonMatchingSceneName.c_str()); - obs_data_set_int(obj, "switch_if_not_matching", switcher->switchIfNotMatching); + obs_data_set_string(obj, "non_matching_scene", + nonMatchingSceneName.c_str()); + obs_data_set_int(obj, "switch_if_not_matching", + switcher->switchIfNotMatching); obs_data_set_bool(obj, "active", !switcher->stop); obs_data_set_array(obj, "switches", array); @@ -605,37 +765,61 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_set_array(obj, "pauseWindows", pauseWindowsArray); obs_data_set_array(obj, "ignoreWindows", ignoreWindowsArray); obs_data_set_array(obj, "sceneRoundTrip", sceneRoundTripArray); - obs_data_set_array(obj, "sceneTransitions", sceneTransitionsArray); - obs_data_set_array(obj, "defaultTransitions", defaultTransitionsArray); + obs_data_set_array(obj, "sceneTransitions", + sceneTransitionsArray); + obs_data_set_array(obj, "defaultTransitions", + defaultTransitionsArray); obs_data_set_array(obj, "executableSwitches", executableArray); - obs_data_set_array(obj, "ignoreIdleWindows", ignoreIdleWindowsArray); + obs_data_set_array(obj, "ignoreIdleWindows", + ignoreIdleWindowsArray); obs_data_set_array(obj, "randomSwitches", randomArray); obs_data_set_array(obj, "fileSwitches", fileArray); + obs_data_set_array(obj, "mediaSwitches", mediaArray); + string autoStopSceneName = + GetWeakSourceName(switcher->autoStopScene); + obs_data_set_bool(obj, "autoStopEnable", + switcher->autoStopEnable); + obs_data_set_string(obj, "autoStopSceneName", + autoStopSceneName.c_str()); - string autoStopSceneName = GetWeakSourceName(switcher->autoStopScene); - obs_data_set_bool(obj, "autoStopEnable", switcher->autoStopEnable); - obs_data_set_string(obj, "autoStopSceneName", autoStopSceneName.c_str()); - - string idleSceneName = GetWeakSourceName(switcher->idleData.scene); - string idleTransitionName = GetWeakSourceName(switcher->idleData.transition); - obs_data_set_bool(obj, "idleEnable", switcher->idleData.idleEnable); + string idleSceneName = + GetWeakSourceName(switcher->idleData.scene); + string idleTransitionName = + GetWeakSourceName(switcher->idleData.transition); + obs_data_set_bool(obj, "idleEnable", + switcher->idleData.idleEnable); obs_data_set_string(obj, "idleSceneName", - switcher->idleData.usePreviousScene ? PREVIOUS_SCENE_NAME : idleSceneName.c_str()); - obs_data_set_string(obj, "idleTransitionName", idleTransitionName.c_str()); + switcher->idleData.usePreviousScene + ? PREVIOUS_SCENE_NAME + : idleSceneName.c_str()); + obs_data_set_string(obj, "idleTransitionName", + idleTransitionName.c_str()); obs_data_set_int(obj, "idleTime", switcher->idleData.time); - obs_data_set_bool(obj, "readEnabled", switcher->fileIO.readEnabled); - obs_data_set_string(obj, "readPath", switcher->fileIO.readPath.c_str()); - obs_data_set_bool(obj, "writeEnabled", switcher->fileIO.writeEnabled); - obs_data_set_string(obj, "writePath", switcher->fileIO.writePath.c_str()); + obs_data_set_bool(obj, "readEnabled", + switcher->fileIO.readEnabled); + obs_data_set_string(obj, "readPath", + switcher->fileIO.readPath.c_str()); + obs_data_set_bool(obj, "writeEnabled", + switcher->fileIO.writeEnabled); + obs_data_set_string(obj, "writePath", + switcher->fileIO.writePath.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_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_int(obj, "priority6", + switcher->functionNamesByPriority[6]); obs_data_set_obj(save_data, "advanced-scene-switcher", obj); @@ -651,26 +835,39 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) obs_data_array_release(ignoreIdleWindowsArray); obs_data_array_release(randomArray); obs_data_array_release(fileArray); + obs_data_array_release(mediaArray); obs_data_release(obj); - } - else - { + } else { switcher->m.lock(); - obs_data_t* obj = obs_data_get_obj(save_data, "advanced-scene-switcher"); - obs_data_array_t* array = obs_data_get_array(obj, "switches"); - obs_data_array_t* screenRegionArray = obs_data_get_array(obj, "screenRegion"); - obs_data_array_t* pauseScenesArray = obs_data_get_array(obj, "pauseScenes"); - obs_data_array_t* pauseWindowsArray = obs_data_get_array(obj, "pauseWindows"); - obs_data_array_t* ignoreWindowsArray = obs_data_get_array(obj, "ignoreWindows"); - obs_data_array_t* sceneRoundTripArray = obs_data_get_array(obj, "sceneRoundTrip"); - obs_data_array_t* sceneTransitionsArray = obs_data_get_array(obj, "sceneTransitions"); - obs_data_array_t* defaultTransitionsArray = obs_data_get_array(obj, "defaultTransitions"); - 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"); + obs_data_t *obj = + obs_data_get_obj(save_data, "advanced-scene-switcher"); + obs_data_array_t *array = obs_data_get_array(obj, "switches"); + obs_data_array_t *screenRegionArray = + obs_data_get_array(obj, "screenRegion"); + obs_data_array_t *pauseScenesArray = + obs_data_get_array(obj, "pauseScenes"); + obs_data_array_t *pauseWindowsArray = + obs_data_get_array(obj, "pauseWindows"); + obs_data_array_t *ignoreWindowsArray = + obs_data_get_array(obj, "ignoreWindows"); + obs_data_array_t *sceneRoundTripArray = + obs_data_get_array(obj, "sceneRoundTrip"); + obs_data_array_t *sceneTransitionsArray = + obs_data_get_array(obj, "sceneTransitions"); + obs_data_array_t *defaultTransitionsArray = + obs_data_get_array(obj, "defaultTransitions"); + 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"); + obs_data_array_t *mediaArray = + obs_data_get_array(obj, "mediaSwitches"); if (!obj) obj = obs_data_create(); @@ -678,27 +875,36 @@ 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"); + 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"); - switcher->nonMatchingScene = GetWeakSourceByName(nonMatchingScene.c_str()); + switcher->nonMatchingScene = + GetWeakSourceByName(nonMatchingScene.c_str()); switcher->windowSwitches.clear(); size_t count = obs_data_array_count(array); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(array, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = obs_data_array_item(array, i); - const char* scene = obs_data_get_string(array_obj, "scene"); - const char* transition = obs_data_get_string(array_obj, "transition"); - const char* window = obs_data_get_string(array_obj, "window_title"); - bool fullscreen = obs_data_get_bool(array_obj, "fullscreen"); + const char *scene = + obs_data_get_string(array_obj, "scene"); + const char *transition = + obs_data_get_string(array_obj, "transition"); + const char *window = + obs_data_get_string(array_obj, "window_title"); + bool fullscreen = + obs_data_get_bool(array_obj, "fullscreen"); - switcher->windowSwitches.emplace_back(GetWeakSourceByName(scene), window, - GetWeakTransitionByName(transition), fullscreen); + switcher->windowSwitches.emplace_back( + GetWeakSourceByName(scene), window, + GetWeakTransitionByName(transition), + fullscreen); obs_data_release(array_obj); } @@ -706,20 +912,25 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->screenRegionSwitches.clear(); count = obs_data_array_count(screenRegionArray); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(screenRegionArray, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(screenRegionArray, i); - const char* scene = obs_data_get_string(array_obj, "screenRegionScene"); - const char* transition = obs_data_get_string(array_obj, "transition"); + const char *scene = obs_data_get_string( + array_obj, "screenRegionScene"); + const char *transition = + obs_data_get_string(array_obj, "transition"); int minX = obs_data_get_int(array_obj, "minX"); int minY = obs_data_get_int(array_obj, "minY"); int maxX = obs_data_get_int(array_obj, "maxX"); int maxY = obs_data_get_int(array_obj, "maxY"); - string regionStr = obs_data_get_string(array_obj, "screenRegionStr"); + string regionStr = obs_data_get_string( + array_obj, "screenRegionStr"); - switcher->screenRegionSwitches.emplace_back(GetWeakSourceByName(scene), - GetWeakTransitionByName(transition), minX, minY, maxX, maxY, regionStr); + switcher->screenRegionSwitches.emplace_back( + GetWeakSourceByName(scene), + GetWeakTransitionByName(transition), minX, minY, + maxX, maxY, regionStr); obs_data_release(array_obj); } @@ -727,13 +938,15 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->pauseScenesSwitches.clear(); count = obs_data_array_count(pauseScenesArray); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(pauseScenesArray, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(pauseScenesArray, i); - const char* scene = obs_data_get_string(array_obj, "pauseScene"); + const char *scene = + obs_data_get_string(array_obj, "pauseScene"); - switcher->pauseScenesSwitches.emplace_back(GetWeakSourceByName(scene)); + switcher->pauseScenesSwitches.emplace_back( + GetWeakSourceByName(scene)); obs_data_release(array_obj); } @@ -741,11 +954,12 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->pauseWindowsSwitches.clear(); count = obs_data_array_count(pauseWindowsArray); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(pauseWindowsArray, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(pauseWindowsArray, i); - const char* window = obs_data_get_string(array_obj, "pauseWindow"); + const char *window = + obs_data_get_string(array_obj, "pauseWindow"); switcher->pauseWindowsSwitches.emplace_back(window); @@ -757,11 +971,12 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->ignoreWindowsSwitches.clear(); count = obs_data_array_count(ignoreWindowsArray); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(ignoreWindowsArray, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(ignoreWindowsArray, i); - const char* window = obs_data_get_string(array_obj, "ignoreWindow"); + const char *window = + obs_data_get_string(array_obj, "ignoreWindow"); switcher->ignoreWindowsSwitches.emplace_back(window); @@ -771,21 +986,36 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->sceneRoundTripSwitches.clear(); count = obs_data_array_count(sceneRoundTripArray); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(sceneRoundTripArray, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(sceneRoundTripArray, i); - const char* scene1 = obs_data_get_string(array_obj, "sceneRoundTripScene1"); - const char* scene2 = obs_data_get_string(array_obj, "sceneRoundTripScene2"); - const char* transition = obs_data_get_string(array_obj, "transition"); - int delay = obs_data_get_int(array_obj, "sceneRoundTripDelay"); //delay stored in two separate values - delay = delay * 1000 + obs_data_get_int(array_obj, "sceneRoundTripDelayMs"); //to be compatible with older versions - string str = MakeSceneRoundTripSwitchName(scene1, scene2, transition, ((double)delay)/1000.0).toUtf8().constData(); - const char* sceneRoundTripStr = str.c_str(); + const char *scene1 = obs_data_get_string( + array_obj, "sceneRoundTripScene1"); + const char *scene2 = obs_data_get_string( + array_obj, "sceneRoundTripScene2"); + const char *transition = + obs_data_get_string(array_obj, "transition"); + int delay = obs_data_get_int( + array_obj, + "sceneRoundTripDelay"); //delay stored in two separate values + delay = delay * 1000 + + obs_data_get_int( + array_obj, + "sceneRoundTripDelayMs"); //to be compatible with older versions + string str = MakeSceneRoundTripSwitchName( + scene1, scene2, transition, + ((double)delay) / 1000.0) + .toUtf8() + .constData(); + const char *sceneRoundTripStr = str.c_str(); - switcher->sceneRoundTripSwitches.emplace_back(GetWeakSourceByName(scene1), - GetWeakSourceByName(scene2), GetWeakTransitionByName(transition), delay, - (strcmp(scene2, PREVIOUS_SCENE_NAME) == 0), sceneRoundTripStr); + switcher->sceneRoundTripSwitches.emplace_back( + GetWeakSourceByName(scene1), + GetWeakSourceByName(scene2), + GetWeakTransitionByName(transition), delay, + (strcmp(scene2, PREVIOUS_SCENE_NAME) == 0), + sceneRoundTripStr); obs_data_release(array_obj); } @@ -793,17 +1023,23 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->sceneTransitions.clear(); count = obs_data_array_count(sceneTransitionsArray); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(sceneTransitionsArray, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(sceneTransitionsArray, i); - const char* scene1 = obs_data_get_string(array_obj, "Scene1"); - const char* scene2 = obs_data_get_string(array_obj, "Scene2"); - const char* transition = obs_data_get_string(array_obj, "transition"); - const char* sceneTransitionsStr = obs_data_get_string(array_obj, "Str"); + const char *scene1 = + obs_data_get_string(array_obj, "Scene1"); + const char *scene2 = + obs_data_get_string(array_obj, "Scene2"); + const char *transition = + obs_data_get_string(array_obj, "transition"); + const char *sceneTransitionsStr = + obs_data_get_string(array_obj, "Str"); - switcher->sceneTransitions.emplace_back(GetWeakSourceByName(scene1), - GetWeakSourceByName(scene2), GetWeakTransitionByName(transition), + switcher->sceneTransitions.emplace_back( + GetWeakSourceByName(scene1), + GetWeakSourceByName(scene2), + GetWeakTransitionByName(transition), sceneTransitionsStr); obs_data_release(array_obj); @@ -812,15 +1048,19 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->defaultSceneTransitions.clear(); count = obs_data_array_count(defaultTransitionsArray); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(defaultTransitionsArray, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(defaultTransitionsArray, i); - const char* scene = obs_data_get_string(array_obj, "Scene"); - const char* transition = obs_data_get_string(array_obj, "transition"); - const char* sceneTransitionsStr = obs_data_get_string(array_obj, "Str"); + const char *scene = + obs_data_get_string(array_obj, "Scene"); + const char *transition = + obs_data_get_string(array_obj, "transition"); + const char *sceneTransitionsStr = + obs_data_get_string(array_obj, "Str"); - switcher->defaultSceneTransitions.emplace_back(GetWeakSourceByName(scene), + switcher->defaultSceneTransitions.emplace_back( + GetWeakSourceByName(scene), GetWeakTransitionByName(transition), sceneTransitionsStr); @@ -830,17 +1070,22 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->executableSwitches.clear(); 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); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(executableArray, i); - const char* scene = obs_data_get_string(array_obj, "scene"); - const char* transition = obs_data_get_string(array_obj, "transition"); - const char* exe = obs_data_get_string(array_obj, "exefile"); + const char *scene = + obs_data_get_string(array_obj, "scene"); + const char *transition = + obs_data_get_string(array_obj, "transition"); + const char *exe = + obs_data_get_string(array_obj, "exefile"); bool infocus = obs_data_get_bool(array_obj, "infocus"); switcher->executableSwitches.emplace_back( - GetWeakSourceByName(scene), GetWeakTransitionByName(transition), exe, infocus); + GetWeakSourceByName(scene), + GetWeakTransitionByName(transition), exe, + infocus); obs_data_release(array_obj); } @@ -848,11 +1093,12 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->ignoreIdleWindows.clear(); count = obs_data_array_count(ignoreIdleWindowsArray); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(ignoreIdleWindowsArray, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(ignoreIdleWindowsArray, i); - const char* window = obs_data_get_string(array_obj, "window"); + const char *window = + obs_data_get_string(array_obj, "window"); switcher->ignoreIdleWindows.emplace_back(window); @@ -862,17 +1108,21 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) switcher->randomSwitches.clear(); count = obs_data_array_count(randomArray); - for (size_t i = 0; i < count; i++) - { - obs_data_t* array_obj = obs_data_array_item(randomArray, i); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(randomArray, i); - const char* scene = obs_data_get_string(array_obj, "scene"); - const char* transition = obs_data_get_string(array_obj, "transition"); + 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"); - const char* 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); + GetWeakSourceByName(scene), + GetWeakTransitionByName(transition), delay, + str); obs_data_release(array_obj); } @@ -880,43 +1130,91 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) 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); + 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"); - bool useRegex = obs_data_get_bool(array_obj, "useRegex"); + 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"); + bool useRegex = + obs_data_get_bool(array_obj, "useRegex"); bool useTime = obs_data_get_bool(array_obj, "useTime"); switcher->fileSwitches.emplace_back( - GetWeakSourceByName(scene), GetWeakTransitionByName(transition), file, text, useRegex, useTime); + GetWeakSourceByName(scene), + GetWeakTransitionByName(transition), file, text, + useRegex, useTime); 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()); + switcher->mediaSwitches.clear(); + count = obs_data_array_count(mediaArray); - string idleSceneName = obs_data_get_string(obj, "idleSceneName"); - string idleTransitionName = obs_data_get_string(obj, "idleTransitionName"); - switcher->idleData.scene = GetWeakSourceByName(idleSceneName.c_str()); - switcher->idleData.transition = GetWeakTransitionByName(idleTransitionName.c_str()); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = + obs_data_array_item(mediaArray, i); + + const char *source = + obs_data_get_string(array_obj, "source"); + const char *scene = + obs_data_get_string(array_obj, "scene"); + const char *transition = + obs_data_get_string(array_obj, "transition"); + obs_media_state state = + (obs_media_state)obs_data_get_int(array_obj, + "state"); + time_restriction restriction = + (time_restriction)obs_data_get_int( + array_obj, "restriction"); + uint64_t time = obs_data_get_int(array_obj, "time"); + + switcher->mediaSwitches.emplace_back( + GetWeakSourceByName(scene), + GetWeakSourceByName(source), + GetWeakTransitionByName(transition), state, + restriction, time); + } + + string autoStopScene = + obs_data_get_string(obj, "autoStopSceneName"); + switcher->autoStopEnable = + obs_data_get_bool(obj, "autoStopEnable"); + switcher->autoStopScene = + GetWeakSourceByName(autoStopScene.c_str()); + + string idleSceneName = + obs_data_get_string(obj, "idleSceneName"); + 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"); + 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"); - switcher->idleData.usePreviousScene = (idleSceneName == PREVIOUS_SCENE_NAME); + switcher->idleData.usePreviousScene = + (idleSceneName == PREVIOUS_SCENE_NAME); 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"); + 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"); + switcher->fileIO.writeEnabled = + obs_data_get_bool(obj, "writeEnabled"); + switcher->fileIO.writePath = + obs_data_get_string(obj, "writePath"); obs_data_set_default_int(obj, "priority0", DEFAULT_PRIORITY_0); obs_data_set_default_int(obj, "priority1", DEFAULT_PRIORITY_1); @@ -924,21 +1222,37 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) 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); + obs_data_set_default_int(obj, "priority6", DEFAULT_PRIORITY_6); - 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); - switcher->functionNamesByPriority[1] = (DEFAULT_PRIORITY_1); - switcher->functionNamesByPriority[2] = (DEFAULT_PRIORITY_2); - switcher->functionNamesByPriority[3] = (DEFAULT_PRIORITY_3); - switcher->functionNamesByPriority[4] = (DEFAULT_PRIORITY_4); - switcher->functionNamesByPriority[5] = (DEFAULT_PRIORITY_5); + 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")); + switcher->functionNamesByPriority[6] = + (obs_data_get_int(obj, "priority6")); + if (!switcher->prioFuncsValid()) { + switcher->functionNamesByPriority[0] = + (DEFAULT_PRIORITY_0); + switcher->functionNamesByPriority[1] = + (DEFAULT_PRIORITY_1); + switcher->functionNamesByPriority[2] = + (DEFAULT_PRIORITY_2); + switcher->functionNamesByPriority[3] = + (DEFAULT_PRIORITY_3); + switcher->functionNamesByPriority[4] = + (DEFAULT_PRIORITY_4); + switcher->functionNamesByPriority[5] = + (DEFAULT_PRIORITY_5); + switcher->functionNamesByPriority[6] = + (DEFAULT_PRIORITY_6); } obs_data_array_release(array); @@ -964,7 +1278,6 @@ static void SaveSceneSwitcher(obs_data_t* save_data, bool saving, void*) } } - /******************************************************************************** * Main switcher thread ********************************************************************************/ @@ -976,8 +1289,7 @@ void SwitcherData::Thread() int sleep = 0; - while (true) - { + while (true) { startLoop: unique_lock lock(m); bool match = false; @@ -993,25 +1305,22 @@ void SwitcherData::Thread() writeSceneInfoToFile(); //sleep for a bit cv.wait_for(lock, duration); - if (switcher->stop) - { + if (switcher->stop) { break; } setDefaultSceneTransitions(); - if (autoStopEnable) - { + if (autoStopEnable) { autoStopStreamAndRecording(); } - if (checkPause()) - { + if (checkPause()) { continue; } - for (int switchFuncName : functionNamesByPriority) - { + for (int switchFuncName : functionNamesByPriority) { switch (switchFuncName) { case READ_FILE_FUNC: - checkSwitchInfoFromFile(match, scene, transition); + checkSwitchInfoFromFile(match, scene, + transition); checkFileContent(match, scene, transition); break; case IDLE_FUNC: @@ -1022,69 +1331,72 @@ void SwitcherData::Thread() break; case SCREEN_REGION_FUNC: - checkScreenRegionSwitch(match, scene, transition); + checkScreenRegionSwitch(match, scene, + transition); break; case WINDOW_TITLE_FUNC: - checkWindowTitleSwitch(match, scene, transition); + checkWindowTitleSwitch(match, scene, + transition); break; case ROUND_TRIP_FUNC: - checkSceneRoundTrip(match, scene, transition, lock); + checkSceneRoundTrip(match, scene, transition, + lock); if (sceneChangedDuringWait()) //scene might have changed during the sleep { goto startLoop; } + break; + case MEDIA_FUNC: + checkMediaSwitch(match, scene, transition); + break; } - if (switcher->stop) - { + if (switcher->stop) { goto endLoop; } - if (match) - { + if (match) { break; } } - if (!match && switchIfNotMatching == SWITCH && nonMatchingScene) - { + if (!match && switchIfNotMatching == SWITCH && + nonMatchingScene) { match = true; scene = nonMatchingScene; transition = nullptr; } - if (!match && switchIfNotMatching == RANDOM_SWITCH) - { + if (!match && switchIfNotMatching == RANDOM_SWITCH) { checkRandom(match, scene, transition, sleep); } - if (match) - { + if (match) { switchScene(scene, transition, lock); } } -endLoop: - ; +endLoop:; } -void switchScene(OBSWeakSource& scene, OBSWeakSource& transition, unique_lock& lock) +void switchScene(OBSWeakSource &scene, OBSWeakSource &transition, + unique_lock &lock) { - obs_source_t* source = obs_weak_source_get_source(scene); - obs_source_t* currentSource = obs_frontend_get_current_scene(); + obs_source_t *source = obs_weak_source_get_source(scene); + obs_source_t *currentSource = obs_frontend_get_current_scene(); - if (source && source != currentSource) - { - obs_weak_source_t* currentScene = obs_source_get_weak_source(currentSource); - obs_weak_source_t* nextTransitionWs = getNextTransition(currentScene, scene); + if (source && source != currentSource) { + obs_weak_source_t *currentScene = + obs_source_get_weak_source(currentSource); + obs_weak_source_t *nextTransitionWs = + getNextTransition(currentScene, scene); obs_weak_source_release(currentScene); - if (nextTransitionWs) - { - obs_source_t* nextTransition = obs_weak_source_get_source(nextTransitionWs); + if (nextTransitionWs) { + obs_source_t *nextTransition = + obs_weak_source_get_source(nextTransitionWs); lock.unlock(); obs_frontend_set_current_transition(nextTransition); lock.lock(); obs_source_release(nextTransition); - } - else if (transition) - { - obs_source_t* nextTransition = obs_weak_source_get_source(transition); + } else if (transition) { + obs_source_t *nextTransition = + obs_weak_source_get_source(transition); lock.unlock(); obs_frontend_set_current_transition(nextTransition); lock.lock(); @@ -1103,9 +1415,10 @@ void switchScene(OBSWeakSource& scene, OBSWeakSource& transition, unique_lockth = thread([]() - { - switcher->Thread(); - }); + switcher->th = thread([]() { switcher->Thread(); }); } } void SwitcherData::Stop() { - if (th.joinable()) - { + if (th.joinable()) { switcher->stop = true; transitionCv.notify_one(); cv.notify_one(); @@ -1138,7 +1446,6 @@ void SwitcherData::Stop() } } - /******************************************************************************** * OBS module setup ********************************************************************************/ @@ -1148,33 +1455,30 @@ extern "C" void FreeSceneSwitcher() switcher = nullptr; } -static void OBSEvent(enum obs_frontend_event event, void* switcher) +static void OBSEvent(enum obs_frontend_event event, void *switcher) { - switch (event){ + switch (event) { case OBS_FRONTEND_EVENT_EXIT: FreeSceneSwitcher(); break; - case OBS_FRONTEND_EVENT_SCENE_CHANGED: - { - SwitcherData* s = (SwitcherData*)switcher; + case OBS_FRONTEND_EVENT_SCENE_CHANGED: { + SwitcherData *s = (SwitcherData *)switcher; lock_guard lock(s->m); //stop waiting if scene was manually changed if (s->sceneChangedDuringWait()) s->cv.notify_one(); //set previous scene - obs_source_t* source = obs_frontend_get_current_scene(); - obs_weak_source_t* ws = obs_source_get_weak_source(source); + obs_source_t *source = obs_frontend_get_current_scene(); + obs_weak_source_t *ws = obs_source_get_weak_source(source); obs_source_release(source); obs_weak_source_release(ws); - if (source && s->PreviousScene2 != ws) - { + if (source && s->PreviousScene2 != ws) { s->previousScene = s->PreviousScene2; s->PreviousScene2 = ws; } - break; } default: @@ -1184,14 +1488,14 @@ static void OBSEvent(enum obs_frontend_event event, void* switcher) extern "C" void InitSceneSwitcher() { - QAction* action - = (QAction*)obs_frontend_add_tools_menu_qaction("Advanced Scene Switcher"); + QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction( + "Advanced Scene Switcher"); switcher = new SwitcherData; - auto cb = []() - { - QMainWindow* window = (QMainWindow*)obs_frontend_get_main_window(); + auto cb = []() { + QMainWindow *window = + (QMainWindow *)obs_frontend_get_main_window(); SceneSwitcher ss(window); ss.exec(); @@ -1202,21 +1506,24 @@ extern "C" void InitSceneSwitcher() action->connect(action, &QAction::triggered, cb); - char* path = obs_module_config_path(""); + char *path = obs_module_config_path(""); QDir dir(path); - if (!dir.exists()) - { + if (!dir.exists()) { dir.mkpath("."); } bfree(path); - obs_hotkey_id toggleHotkeyId = obs_hotkey_register_frontend("startStopToggleSwitcherHotkey", - "Toggle Start/Stop for the Advanced Scene Switcher", startStopToggleHotkeyFunc, NULL); + obs_hotkey_id toggleHotkeyId = obs_hotkey_register_frontend( + "startStopToggleSwitcherHotkey", + "Toggle Start/Stop for the Advanced Scene Switcher", + startStopToggleHotkeyFunc, NULL); loadKeybinding(toggleHotkeyId, TOGGLE_HOTKEY_PATH); - obs_hotkey_id startHotkeyId = obs_hotkey_register_frontend("startSwitcherHotkey", - "Start the Advanced Scene Switcher", startHotkeyFunc, NULL); + obs_hotkey_id startHotkeyId = obs_hotkey_register_frontend( + "startSwitcherHotkey", "Start the Advanced Scene Switcher", + startHotkeyFunc, NULL); loadKeybinding(startHotkeyId, START_HOTKEY_PATH); - obs_hotkey_id stopHotkeyId = obs_hotkey_register_frontend("stopSwitcherHotkey", - "Stop the Advanced Scene Switcher", stopHotkeyFunc, NULL); + obs_hotkey_id stopHotkeyId = obs_hotkey_register_frontend( + "stopSwitcherHotkey", "Stop the Advanced Scene Switcher", + stopHotkeyFunc, NULL); loadKeybinding(stopHotkeyId, STOP_HOTKEY_PATH); } diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index 7df69d71..88317c64 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -4,7 +4,7 @@ #include #include #include -#ifdef BUILD_OUT_OF_TREE +#ifdef BUILD_OUT_OF_TREE #include "../../forms/ui_advanced-scene-switcher.h" #else #include "ui_advanced-scene-switcher.h" @@ -13,7 +13,6 @@ class QCloseEvent; - /******************************************************************************* * Advanced Scene Switcher window *******************************************************************************/ @@ -37,16 +36,17 @@ public: int PauseWindowsFindByData(const QString &window); int IgnoreWindowsFindByData(const QString &window); int SceneRoundTripFindByData(const QString &scene1); - int SceneTransitionsFindByData(const QString &scene1, const QString &scene2); + int SceneTransitionsFindByData(const QString &scene1, + const QString &scene2); int DefaultTransitionsFindByData(const QString &scene); int executableFindByData(const QString &exe); - int IgnoreIdleWindowsFindByData(const QString& window); - int randomFindByData(const QString& scene); + int IgnoreIdleWindowsFindByData(const QString &window); + int randomFindByData(const QString &scene); void UpdateNonMatchingScene(const QString &name); void UpdateAutoStopScene(const QString &name); - void UpdateIdleDataTransition(const QString& name); - void UpdateIdleDataScene(const QString& name); + void UpdateIdleDataTransition(const QString &name); + void UpdateIdleDataScene(const QString &name); public slots: void on_switches_currentRowChanged(int idx); @@ -94,8 +94,8 @@ public slots: void on_browseButton_clicked(); void on_readFileCheckBox_stateChanged(int state); - void on_readPathLineEdit_textChanged(const QString & text); - void on_writePathLineEdit_textChanged(const QString & text); + void on_readPathLineEdit_textChanged(const QString &text); + void on_writePathLineEdit_textChanged(const QString &text); void on_browseButton_2_clicked(); void on_executableAdd_clicked(); @@ -103,8 +103,8 @@ public slots: void on_executables_currentRowChanged(int idx); void on_idleCheckBox_stateChanged(int state); - void on_idleTransitions_currentTextChanged(const QString& text); - void on_idleScenes_currentTextChanged(const QString& text); + void on_idleTransitions_currentTextChanged(const QString &text); + void on_idleScenes_currentTextChanged(const QString &text); void on_idleSpinBox_valueChanged(int i); void on_ignoreIdleWindows_currentRowChanged(int idx); void on_ignoreIdleAdd_clicked(); @@ -119,6 +119,9 @@ public slots: void on_fileScenesList_currentRowChanged(int idx); void on_browseButton_3_clicked(); + void on_mediaAdd_clicked(); + void on_mediaRemove_clicked(); + void on_priorityUp_clicked(); void on_priorityDown_clicked(); @@ -127,7 +130,6 @@ public slots: void on_close_clicked(); }; - /******************************************************************************** * Windowtitle helper ********************************************************************************/ @@ -135,35 +137,32 @@ void GetWindowList(std::vector &windows); void GetCurrentWindowTitle(std::string &title); bool isFullscreen(); - /******************************************************************************** * Screenregion helper ********************************************************************************/ pair getCursorPos(); - /******************************************************************************** * Idle detection helper ********************************************************************************/ int secondsSinceLastInput(); - /******************************************************************************** * Executable helper ********************************************************************************/ void GetProcessList(QStringList &processes); bool isInFocus(const QString &exeToCheck); - /******************************************************************************** * Sceneswitch helper ********************************************************************************/ struct obs_weak_source; typedef struct obs_weak_source obs_weak_source_t; -obs_weak_source_t* getNextTransition(obs_weak_source_t* scene1, obs_weak_source_t* scene2); -void switchScene(OBSWeakSource& scene, OBSWeakSource& transition, unique_lock& lock); - +obs_weak_source_t *getNextTransition(obs_weak_source_t *scene1, + obs_weak_source_t *scene2); +void switchScene(OBSWeakSource &scene, OBSWeakSource &transition, + unique_lock &lock); /******************************************************************************** * Hotkey helper @@ -173,14 +172,16 @@ void switchScene(OBSWeakSource& scene, OBSWeakSource& transition, unique_lock sceneTransitions; vector defaultSceneTransitions; + vector mediaSwitches; + vector functionNamesByPriority = vector{ - DEFAULT_PRIORITY_0, - DEFAULT_PRIORITY_1, - DEFAULT_PRIORITY_2, - DEFAULT_PRIORITY_3, - DEFAULT_PRIORITY_4, - DEFAULT_PRIORITY_5, - }; + DEFAULT_PRIORITY_0, DEFAULT_PRIORITY_1, DEFAULT_PRIORITY_2, + DEFAULT_PRIORITY_3, DEFAULT_PRIORITY_4, DEFAULT_PRIORITY_5, + DEFAULT_PRIORITY_6}; void Thread(); void Start(); @@ -278,101 +291,116 @@ struct SwitcherData void setDefaultSceneTransitions(); void autoStopStreamAndRecording(); bool checkPause(); - void checkSceneRoundTrip(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, unique_lock& lock); - void checkIdleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition); - void checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition); - 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); + void checkSceneRoundTrip(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition, + unique_lock &lock); + void checkIdleSwitch(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition); + void checkWindowTitleSwitch(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition); + 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); + void checkMediaSwitch(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition); void Prune() { - for (size_t i = 0; i < windowSwitches.size(); i++) - { - WindowSceneSwitch& s = windowSwitches[i]; - if (!WeakSourceValid(s.scene) || !WeakSourceValid(s.transition)) - windowSwitches.erase(windowSwitches.begin() + i--); + for (size_t i = 0; i < windowSwitches.size(); i++) { + WindowSceneSwitch &s = windowSwitches[i]; + if (!WeakSourceValid(s.scene) || + !WeakSourceValid(s.transition)) + windowSwitches.erase(windowSwitches.begin() + + i--); } - if (nonMatchingScene && !WeakSourceValid(nonMatchingScene)) - { + if (nonMatchingScene && !WeakSourceValid(nonMatchingScene)) { switchIfNotMatching = NO_SWITCH; nonMatchingScene = nullptr; } - for (size_t i = 0; i < randomSwitches.size(); i++) - { - RandomSwitch& s = randomSwitches[i]; - if (!WeakSourceValid(s.scene) || !WeakSourceValid(s.transition)) - randomSwitches.erase(randomSwitches.begin() + i--); + for (size_t i = 0; i < randomSwitches.size(); i++) { + RandomSwitch &s = randomSwitches[i]; + if (!WeakSourceValid(s.scene) || + !WeakSourceValid(s.transition)) + randomSwitches.erase(randomSwitches.begin() + + i--); } - for (size_t i = 0; i < screenRegionSwitches.size(); i++) - { - ScreenRegionSwitch& s = screenRegionSwitches[i]; - if (!WeakSourceValid(s.scene) || !WeakSourceValid(s.transition)) - screenRegionSwitches.erase(screenRegionSwitches.begin() + i--); + for (size_t i = 0; i < screenRegionSwitches.size(); i++) { + ScreenRegionSwitch &s = screenRegionSwitches[i]; + if (!WeakSourceValid(s.scene) || + !WeakSourceValid(s.transition)) + screenRegionSwitches.erase( + screenRegionSwitches.begin() + i--); } - for (size_t i = 0; i < pauseScenesSwitches.size(); i++) - { - OBSWeakSource& scene = pauseScenesSwitches[i]; + for (size_t i = 0; i < pauseScenesSwitches.size(); i++) { + OBSWeakSource &scene = pauseScenesSwitches[i]; if (!WeakSourceValid(scene)) - pauseScenesSwitches.erase(pauseScenesSwitches.begin() + i--); + pauseScenesSwitches.erase( + pauseScenesSwitches.begin() + i--); } - for (size_t i = 0; i < sceneRoundTripSwitches.size(); i++) - { - SceneRoundTripSwitch& s = sceneRoundTripSwitches[i]; - if (!WeakSourceValid(s.scene1) || (!s.usePreviousScene && !WeakSourceValid(s.scene2)) - || !WeakSourceValid(s.transition)) - sceneRoundTripSwitches.erase(sceneRoundTripSwitches.begin() + i--); + for (size_t i = 0; i < sceneRoundTripSwitches.size(); i++) { + SceneRoundTripSwitch &s = sceneRoundTripSwitches[i]; + if (!WeakSourceValid(s.scene1) || + (!s.usePreviousScene && + !WeakSourceValid(s.scene2)) || + !WeakSourceValid(s.transition)) + sceneRoundTripSwitches.erase( + sceneRoundTripSwitches.begin() + i--); } - if (!WeakSourceValid(autoStopScene)) - { + if (!WeakSourceValid(autoStopScene)) { autoStopScene = nullptr; autoStopEnable = false; } - for (size_t i = 0; i < sceneTransitions.size(); i++) - { - SceneTransition& s = sceneTransitions[i]; - if (!WeakSourceValid(s.scene1) || !WeakSourceValid(s.scene2) - || !WeakSourceValid(s.transition)) - sceneTransitions.erase(sceneTransitions.begin() + i--); + for (size_t i = 0; i < sceneTransitions.size(); i++) { + SceneTransition &s = sceneTransitions[i]; + if (!WeakSourceValid(s.scene1) || + !WeakSourceValid(s.scene2) || + !WeakSourceValid(s.transition)) + sceneTransitions.erase( + sceneTransitions.begin() + i--); } - for (size_t i = 0; i < defaultSceneTransitions.size(); i++) - { - DefaultSceneTransition& s = defaultSceneTransitions[i]; - if (!WeakSourceValid(s.scene) || !WeakSourceValid(s.transition)) - defaultSceneTransitions.erase(defaultSceneTransitions.begin() + i--); + for (size_t i = 0; i < defaultSceneTransitions.size(); i++) { + DefaultSceneTransition &s = defaultSceneTransitions[i]; + if (!WeakSourceValid(s.scene) || + !WeakSourceValid(s.transition)) + defaultSceneTransitions.erase( + defaultSceneTransitions.begin() + i--); } - for (size_t i = 0; i < executableSwitches.size(); i++) - { - ExecutableSceneSwitch& s = executableSwitches[i]; - if (!WeakSourceValid(s.mScene) || !WeakSourceValid(s.mTransition)) - executableSwitches.erase(executableSwitches.begin() + i--); + for (size_t i = 0; i < executableSwitches.size(); i++) { + ExecutableSceneSwitch &s = executableSwitches[i]; + if (!WeakSourceValid(s.mScene) || + !WeakSourceValid(s.mTransition)) + 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)) + 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 (!idleData.usePreviousScene && !WeakSourceValid(idleData.scene) || !WeakSourceValid(idleData.transition)) - { + if (!idleData.usePreviousScene && + !WeakSourceValid(idleData.scene) || + !WeakSourceValid(idleData.transition)) { idleData.idleEnable = false; } } - inline ~SwitcherData() - { - Stop(); - } + inline ~SwitcherData() { Stop(); } }; diff --git a/src/headers/utility.hpp b/src/headers/utility.hpp index cdc3985e..f1cca4f9 100644 --- a/src/headers/utility.hpp +++ b/src/headers/utility.hpp @@ -13,67 +13,85 @@ static inline bool WeakSourceValid(obs_weak_source_t* ws) return !!source; } -static inline QString MakeSwitchName( - const QString& scene, const QString& value, const QString& transition, bool fullscreen) +static inline QString MakeSwitchName(const QString &scene, const QString &value, + const QString &transition, bool fullscreen) { if (!fullscreen) - return QStringLiteral("[") + scene + QStringLiteral(", ") + transition - + QStringLiteral("]: ") + value; - return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + QStringLiteral("]: ") - + value + QStringLiteral(" (only if window is fullscreen)"); + return QStringLiteral("[") + scene + QStringLiteral(", ") + + transition + QStringLiteral("]: ") + value; + return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + + QStringLiteral("]: ") + value + + QStringLiteral(" (only if window is fullscreen)"); } -static inline QString MakeSwitchNameExecutable( - const QString& scene, const QString& value, const QString& transition, bool inFocus) +static inline QString MakeSwitchNameExecutable(const QString &scene, + const QString &value, + const QString &transition, + bool inFocus) { if (!inFocus) - return QStringLiteral("[") + scene + QStringLiteral(", ") + transition - + QStringLiteral("]: ") + value; - return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + QStringLiteral("]: ") - + value + QStringLiteral(" (only if window is focused)"); + return QStringLiteral("[") + scene + QStringLiteral(", ") + + transition + QStringLiteral("]: ") + value; + return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + + QStringLiteral("]: ") + value + + QStringLiteral(" (only if window is focused)"); } -static inline QString MakeScreenRegionSwitchName( - const QString& scene, const QString& transition, int minX, int minY, int maxX, int maxY) +static inline QString MakeScreenRegionSwitchName(const QString &scene, + const QString &transition, + int minX, int minY, int maxX, + int maxY) { - return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + QStringLiteral("]: ") - + QString::number(minX) + QStringLiteral(", ") + QString::number(minY) - + QStringLiteral(" x ") + QString::number(maxX) + QStringLiteral(", ") - + QString::number(maxY); + return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + + QStringLiteral("]: ") + QString::number(minX) + + QStringLiteral(", ") + QString::number(minY) + + QStringLiteral(" x ") + QString::number(maxX) + + QStringLiteral(", ") + QString::number(maxY); } -static inline QString MakeSceneRoundTripSwitchName( - const QString& scene1, const QString& scene2, const QString& transition, double delay) +static inline QString MakeSceneRoundTripSwitchName(const QString &scene1, + const QString &scene2, + const QString &transition, + double delay) { - return scene1 + QStringLiteral(" -> wait for ") + QString::number(delay) - + QStringLiteral(" seconds -> ") + scene2 + QStringLiteral(" (using ") + transition - + QStringLiteral(" transition)"); + return scene1 + QStringLiteral(" -> wait for ") + + QString::number(delay) + QStringLiteral(" seconds -> ") + + scene2 + QStringLiteral(" (using ") + transition + + QStringLiteral(" transition)"); } -static inline QString MakeSceneTransitionName( - const QString& scene1, const QString& scene2, const QString& transition) +static inline QString MakeSceneTransitionName(const QString &scene1, + const QString &scene2, + const QString &transition) { - return scene1 + QStringLiteral(" --- ") + transition + QStringLiteral(" --> ") + scene2; + return scene1 + QStringLiteral(" --- ") + transition + + QStringLiteral(" --> ") + scene2; } -static inline QString MakeDefaultSceneTransitionName( - const QString& scene, const QString& transition) +static inline QString MakeDefaultSceneTransitionName(const QString &scene, + const QString &transition) { return scene + QStringLiteral(" --> ") + transition; } -static inline QString MakeRandomSwitchName( - const QString& scene, const QString& transition, double& delay) +static inline QString MakeRandomSwitchName(const QString &scene, + const QString &transition, + double &delay) { - return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + QStringLiteral("]: ") - + QString::number(delay) + QStringLiteral(" seconds"); + return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + + QStringLiteral("]: ") + QString::number(delay) + + QStringLiteral(" seconds"); } -static inline QString MakeFileSwitchName( - const QString& scene, const QString& transition, const QString& fileName, const QString& text, bool useRegex, bool useTime) +static inline QString MakeFileSwitchName(const QString &scene, + const QString &transition, + const QString &fileName, + const QString &text, bool useRegex, + bool useTime) { - QString switchName = QStringLiteral("Switch to ") + scene + QStringLiteral(" using ") + transition + QStringLiteral(" if ") - + fileName; + QString switchName = QStringLiteral("Switch to ") + scene + + QStringLiteral(" using ") + transition + + QStringLiteral(" if ") + fileName; if (useTime) switchName += QStringLiteral(" was modified and"); switchName += QStringLiteral(" contains"); @@ -89,13 +107,64 @@ static inline QString MakeFileSwitchName( return switchName; } -static inline string GetWeakSourceName(obs_weak_source_t* weak_source) +typedef enum { + TIME_RESTRICTION_NONE, + TIME_RESTRICTION_SHORTER, + TIME_RESTRICTION_LONGER, + TIME_RESTRICTION_REMAINING_SHORTER, + TIME_RESTRICTION_REMAINING_LONGER, +} time_restriction; + +static inline QString +MakeMediaSwitchName(const QString &source, const QString &scene, + const QString &transition, obs_media_state state, + time_restriction restriction, uint64_t time) +{ + QString switchName = QStringLiteral("Switch to ") + scene + + QStringLiteral(" using ") + transition + + QStringLiteral(" if ") + source + + QStringLiteral(" state is "); + if (state == OBS_MEDIA_STATE_NONE) { + switchName += QStringLiteral("none"); + } else if (state == OBS_MEDIA_STATE_PLAYING) { + switchName += QStringLiteral("playing"); + } else if (state == OBS_MEDIA_STATE_OPENING) { + switchName += QStringLiteral("opening"); + } else if (state == OBS_MEDIA_STATE_BUFFERING) { + switchName += QStringLiteral("buffering"); + } else if (state == OBS_MEDIA_STATE_PAUSED) { + switchName += QStringLiteral("paused"); + } else if (state == OBS_MEDIA_STATE_STOPPED) { + switchName += QStringLiteral("stopped"); + } else if (state == OBS_MEDIA_STATE_ENDED) { + switchName += QStringLiteral("ended"); + } else if (state == OBS_MEDIA_STATE_ERROR) { + switchName += QStringLiteral("error"); + } + if (restriction == TIME_RESTRICTION_SHORTER) { + switchName += QStringLiteral(" and time shorter than "); + } else if (restriction == TIME_RESTRICTION_LONGER) { + switchName += QStringLiteral(" and time longer than "); + } else if (restriction == TIME_RESTRICTION_REMAINING_SHORTER) { + switchName += + QStringLiteral(" and time remaining shorter than "); + } else if (restriction == TIME_RESTRICTION_REMAINING_LONGER) { + switchName += + QStringLiteral(" and time remaining longer than "); + } + if (restriction != TIME_RESTRICTION_NONE) { + switchName += std::to_string(time).c_str(); + switchName += QStringLiteral(" ms"); + } + return switchName; +} + +static inline string GetWeakSourceName(obs_weak_source_t *weak_source) { string name; - obs_source_t* source = obs_weak_source_get_source(weak_source); - if (source) - { + obs_source_t *source = obs_weak_source_get_source(weak_source); + if (source) { name = obs_source_get_name(source); obs_source_release(source); } @@ -103,12 +172,11 @@ static inline string GetWeakSourceName(obs_weak_source_t* weak_source) return name; } -static inline OBSWeakSource GetWeakSourceByName(const char* name) +static inline OBSWeakSource GetWeakSourceByName(const char *name) { OBSWeakSource weak; - obs_source_t* source = obs_get_source_by_name(name); - if (source) - { + obs_source_t *source = obs_get_source_by_name(name); + if (source) { weak = obs_source_get_weak_source(source); obs_weak_source_release(weak); obs_source_release(source); @@ -117,18 +185,17 @@ static inline OBSWeakSource GetWeakSourceByName(const char* name) return weak; } -static inline OBSWeakSource GetWeakSourceByQString(const QString& name) +static inline OBSWeakSource GetWeakSourceByQString(const QString &name) { return GetWeakSourceByName(name.toUtf8().constData()); } -static inline OBSWeakSource GetWeakTransitionByName(const char* transitionName) +static inline OBSWeakSource GetWeakTransitionByName(const char *transitionName) { OBSWeakSource weak; - obs_source_t* source = nullptr; + obs_source_t *source = nullptr; - if (strcmp(transitionName, "Default") == 0) - { + if (strcmp(transitionName, "Default") == 0) { source = obs_frontend_get_current_transition(); weak = obs_source_get_weak_source(source); obs_source_release(source); @@ -136,22 +203,21 @@ static inline OBSWeakSource GetWeakTransitionByName(const char* transitionName) return weak; } - obs_frontend_source_list* transitions = new obs_frontend_source_list(); + obs_frontend_source_list *transitions = new obs_frontend_source_list(); obs_frontend_get_transitions(transitions); bool match = false; - for (size_t i = 0; i < transitions->sources.num; i++) - { - const char* name = obs_source_get_name(transitions->sources.array[i]); - if (strcmp(transitionName, name) == 0) - { + for (size_t i = 0; i < transitions->sources.num; i++) { + const char *name = + obs_source_get_name(transitions->sources.array[i]); + if (strcmp(transitionName, name) == 0) { match = true; source = transitions->sources.array[i]; break; } } - if (match){ + if (match) { weak = obs_source_get_weak_source(source); obs_weak_source_release(weak); } @@ -160,7 +226,7 @@ static inline OBSWeakSource GetWeakTransitionByName(const char* transitionName) return weak; } -static inline OBSWeakSource GetWeakTransitionByQString(const QString& name) +static inline OBSWeakSource GetWeakTransitionByQString(const QString &name) { return GetWeakTransitionByName(name.toUtf8().constData()); } diff --git a/src/media-switch.cpp b/src/media-switch.cpp new file mode 100644 index 00000000..08929aa3 --- /dev/null +++ b/src/media-switch.cpp @@ -0,0 +1,87 @@ +#include +#include "headers/advanced-scene-switcher.hpp" + +void SceneSwitcher::on_mediaAdd_clicked() +{ + QString sourceName = ui->mediaSources->currentText(); + QString sceneName = ui->mediaScenes->currentText(); + QString transitionName = ui->mediaTransitions->currentText(); + obs_media_state state = + (obs_media_state)ui->mediaStates->currentIndex(); + time_restriction restriction = + (time_restriction)ui->mediaTimeRestrictions->currentIndex(); + uint64_t time = ui->mediaTime->value(); + + if (sceneName.isEmpty() || transitionName.isEmpty() || + sourceName.isEmpty()) + return; + + OBSWeakSource source = GetWeakSourceByQString(sourceName); + OBSWeakSource scene = GetWeakSourceByQString(sceneName); + OBSWeakSource transition = GetWeakTransitionByQString(transitionName); + + QString switchText = MakeMediaSwitchName(sourceName, sceneName, + transitionName, state, + restriction, time); + QVariant v = QVariant::fromValue(switchText); + + QListWidgetItem *item = + new QListWidgetItem(switchText, ui->mediaSwitches); + item->setData(Qt::UserRole, v); + + lock_guard lock(switcher->m); + switcher->mediaSwitches.emplace_back(scene, source, transition, state, + restriction, time); +} + +void SceneSwitcher::on_mediaRemove_clicked() +{ + QListWidgetItem *item = ui->mediaSwitches->currentItem(); + if (!item) + return; + + int idx = ui->mediaSwitches->currentRow(); + if (idx == -1) + return; + + { + lock_guard lock(switcher->m); + + auto &switches = switcher->mediaSwitches; + switches.erase(switches.begin() + idx); + } + qDeleteAll(ui->mediaSwitches->selectedItems()); +} + +void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition) +{ + for (MediaSwitch &mediaSwitch : mediaSwitches) { + obs_source_t *source = + obs_weak_source_get_source(mediaSwitch.source); + auto duration = obs_source_media_get_duration(source); + auto time = obs_source_media_get_time(source); + obs_media_state state = obs_source_media_get_state(source); + bool matched = + state == mediaSwitch.state && + (mediaSwitch.restriction == TIME_RESTRICTION_NONE || + (mediaSwitch.restriction == TIME_RESTRICTION_LONGER && + time > mediaSwitch.time) || + (mediaSwitch.restriction == TIME_RESTRICTION_SHORTER && + time < mediaSwitch.time) || + (mediaSwitch.restriction == + TIME_RESTRICTION_REMAINING_SHORTER && + duration > time && + duration - time < mediaSwitch.time) || + (mediaSwitch.restriction == + TIME_RESTRICTION_REMAINING_LONGER && + duration > time && + duration - time > mediaSwitch.time)); + if (matched && !mediaSwitch.matched) { + match = true; + scene = mediaSwitch.scene; + transition = mediaSwitch.transition; + } + mediaSwitch.matched = matched; + } +} diff --git a/src/priority.cpp b/src/priority.cpp index a6734edb..caaf99bd 100644 --- a/src/priority.cpp +++ b/src/priority.cpp @@ -36,7 +36,7 @@ bool SwitcherData::prioFuncsValid() for (int p : functionNamesByPriority) { - if (p < 0 || p > 5) + if (p < 0 || p > 6) return false; } return true;