#include #include "headers/advanced-scene-switcher.hpp" #include "headers/utility.hpp" constexpr auto tab_count = 14; QMetaObject::Connection inactivePluse; void AdvSceneSwitcher::on_close_clicked() { done(0); } void AdvSceneSwitcher::UpdateNonMatchingScene(const QString &name) { obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData()); obs_weak_source_t *ws = obs_source_get_weak_source(scene); switcher->nonMatchingScene = ws; obs_weak_source_release(ws); obs_source_release(scene); } void AdvSceneSwitcher::on_noMatchDontSwitch_clicked() { if (loading) return; std::lock_guard lock(switcher->m); switcher->switchIfNotMatching = NO_SWITCH; ui->noMatchSwitchScene->setEnabled(false); ui->randomDisabledWarning->setVisible(true); } void AdvSceneSwitcher::on_noMatchSwitch_clicked() { if (loading) return; std::lock_guard lock(switcher->m); switcher->switchIfNotMatching = SWITCH; ui->noMatchSwitchScene->setEnabled(true); UpdateNonMatchingScene(ui->noMatchSwitchScene->currentText()); ui->randomDisabledWarning->setVisible(true); } void AdvSceneSwitcher::on_noMatchRandomSwitch_clicked() { if (loading) return; std::lock_guard lock(switcher->m); switcher->switchIfNotMatching = RANDOM_SWITCH; ui->noMatchSwitchScene->setEnabled(false); ui->randomDisabledWarning->setVisible(false); } void AdvSceneSwitcher::on_noMatchDelay_valueChanged(double i) { if (loading) return; std::lock_guard lock(switcher->m); switcher->noMatchDelay = i; } void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index) { if (loading) return; std::lock_guard lock(switcher->m); switcher->startupBehavior = (StartupBehavior)index; } void AdvSceneSwitcher::on_noMatchSwitchScene_currentTextChanged( const QString &text) { if (loading) return; std::lock_guard lock(switcher->m); UpdateNonMatchingScene(text); } void AdvSceneSwitcher::on_cooldownTime_valueChanged(double i) { if (loading) return; std::lock_guard lock(switcher->m); switcher->cooldown = i; } void AdvSceneSwitcher::on_checkInterval_valueChanged(int value) { if (loading) return; std::lock_guard lock(switcher->m); switcher->interval = value; } void AdvSceneSwitcher::SetStarted() { ui->toggleStartButton->setText( obs_module_text("AdvSceneSwitcher.generalTab.status.stop")); ui->pluginRunningText->setText( obs_module_text("AdvSceneSwitcher.status.active")); ui->pluginRunningText->disconnect(inactivePluse); } void AdvSceneSwitcher::SetStopped() { ui->toggleStartButton->setText( obs_module_text("AdvSceneSwitcher.generalTab.status.start")); ui->pluginRunningText->setText( obs_module_text("AdvSceneSwitcher.status.inactive")); inactivePluse = PulseWidget(ui->pluginRunningText, QColor(Qt::red), QColor(0, 0, 0, 0), "QLabel "); } void AdvSceneSwitcher::on_toggleStartButton_clicked() { if (switcher->th && switcher->th->isRunning()) { switcher->Stop(); SetStopped(); } else { switcher->Start(); SetStarted(); } } void AdvSceneSwitcher::closeEvent(QCloseEvent *) { obs_frontend_save(); } void AdvSceneSwitcher::on_autoStopScenes_currentTextChanged(const QString &text) { if (loading) return; std::lock_guard lock(switcher->m); UpdateAutoStopScene(text); } void AdvSceneSwitcher::on_autoStopSceneCheckBox_stateChanged(int state) { if (loading) return; std::lock_guard lock(switcher->m); if (!state) { ui->autoStopScenes->setDisabled(true); ui->autoStopType->setDisabled(true); switcher->autoStopEnable = false; } else { ui->autoStopScenes->setDisabled(false); ui->autoStopType->setDisabled(false); switcher->autoStopEnable = true; if (!switcher->autoStopScene) UpdateAutoStopScene(ui->autoStopScenes->currentText()); } } void AdvSceneSwitcher::on_autoStopType_currentIndexChanged(int index) { if (loading) return; std::lock_guard lock(switcher->m); switcher->autoStopType = (AutoStartStopType)index; } void AdvSceneSwitcher::UpdateAutoStopScene(const QString &name) { obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData()); obs_weak_source_t *ws = obs_source_get_weak_source(scene); switcher->autoStopScene = ws; obs_weak_source_release(ws); obs_source_release(scene); } void SwitcherData::autoStopStreamAndRecording() { obs_source_t *currentSource = obs_frontend_get_current_scene(); obs_weak_source_t *ws = obs_source_get_weak_source(currentSource); if (ws && autoStopScene == ws) { if ((switcher->autoStopType == STREAMING || switcher->autoStopType == RECORINDGSTREAMING) && obs_frontend_streaming_active()) { blog(LOG_INFO, "Stopping stream because scene '%s' is active", obs_source_get_name(currentSource)); obs_frontend_streaming_stop(); } if ((switcher->autoStopType == RECORDING || switcher->autoStopType == RECORINDGSTREAMING) && obs_frontend_recording_active()) { blog(LOG_INFO, "Stopping record because scene '%s' is active", obs_source_get_name(currentSource)); obs_frontend_recording_stop(); } } obs_source_release(currentSource); obs_weak_source_release(ws); } void AdvSceneSwitcher::on_autoStartType_currentIndexChanged(int index) { if (loading) return; std::lock_guard lock(switcher->m); switcher->autoStartType = (AutoStartStopType)index; } void AdvSceneSwitcher::on_autoStartScenes_currentTextChanged(const QString &text) { if (loading) return; std::lock_guard lock(switcher->m); UpdateAutoStartScene(text); } void AdvSceneSwitcher::on_autoStartSceneCheckBox_stateChanged(int state) { if (loading) return; std::lock_guard lock(switcher->m); if (!state) { ui->autoStartScenes->setDisabled(true); ui->autoStartType->setDisabled(true); switcher->autoStartEnable = false; } else { ui->autoStartScenes->setDisabled(false); ui->autoStartType->setDisabled(false); switcher->autoStartEnable = true; if (!switcher->autoStartScene) UpdateAutoStartScene( ui->autoStartScenes->currentText()); } } void AdvSceneSwitcher::UpdateAutoStartScene(const QString &name) { obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData()); obs_weak_source_t *ws = obs_source_get_weak_source(scene); switcher->autoStartScene = ws; obs_weak_source_release(ws); obs_source_release(scene); } void SwitcherData::autoStartStreamRecording() { if (autoStartedRecently) return; obs_source_t *currentSource = obs_frontend_get_current_scene(); obs_weak_source_t *ws = obs_source_get_weak_source(currentSource); if (ws && autoStartScene == ws) { if ((switcher->autoStartType == STREAMING || switcher->autoStartType == RECORINDGSTREAMING) && !obs_frontend_streaming_active()) { blog(LOG_INFO, "Starting stream because scene '%s' is active", obs_source_get_name(currentSource)); obs_frontend_streaming_start(); } if ((switcher->autoStartType == RECORDING || switcher->autoStartType == RECORINDGSTREAMING) && !obs_frontend_recording_active()) { blog(LOG_INFO, "Starting record because scene '%s' is active", obs_source_get_name(currentSource)); obs_frontend_recording_start(); } } obs_source_release(currentSource); obs_weak_source_release(ws); autoStartedRecently = true; } void AdvSceneSwitcher::on_verboseLogging_stateChanged(int state) { if (loading) return; switcher->verbose = state; } void AdvSceneSwitcher::on_uiHintsDisable_stateChanged(int state) { if (loading) return; switcher->disableHints = state; } void AdvSceneSwitcher::AskBackup(obs_data_t *obj) { bool backupSettings = DisplayMessage( obs_module_text("AdvSceneSwitcher.askBackup"), true); if (!backupSettings) return; QString directory = QFileDialog::getSaveFileName( nullptr, obs_module_text( "AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle"), QDir::currentPath(), obs_module_text( "AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType")); if (directory.isEmpty()) return; QFile file(directory); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; obs_data_save_json(obj, file.fileName().toUtf8().constData()); } void AdvSceneSwitcher::on_exportSettings_clicked() { QString directory = QFileDialog::getSaveFileName( this, tr(obs_module_text( "AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle")), QDir::currentPath(), tr(obs_module_text( "AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"))); if (directory.isEmpty()) return; QFile file(directory); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; obs_data_t *obj = obs_data_create(); switcher->saveWindowTitleSwitches(obj); switcher->saveScreenRegionSwitches(obj); switcher->savePauseSwitches(obj); switcher->saveSceneSequenceSwitches(obj); switcher->saveSceneTransitions(obj); switcher->saveIdleSwitches(obj); switcher->saveExecutableSwitches(obj); switcher->saveRandomSwitches(obj); switcher->saveFileSwitches(obj); switcher->saveMediaSwitches(obj); switcher->saveTimeSwitches(obj); switcher->saveAudioSwitches(obj); switcher->saveGeneralSettings(obj); switcher->saveHotkeys(obj); obs_data_save_json(obj, file.fileName().toUtf8().constData()); obs_data_release(obj); } void AdvSceneSwitcher::on_importSettings_clicked() { // scene switcher could be stuck in a sequence // so it needs to be stopped before importing new settings bool start = !switcher->stop; switcher->Stop(); std::lock_guard lock(switcher->m); QString directory = QFileDialog::getOpenFileName( this, tr(obs_module_text( "AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle")), QDir::currentPath(), tr(obs_module_text( "AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"))); if (directory.isEmpty()) return; QFile file(directory); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; obs_data_t *obj = obs_data_create_from_json_file( file.fileName().toUtf8().constData()); if (!obj) { (void)DisplayMessage(obs_module_text( "AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadFail")); return; } switcher->loadWindowTitleSwitches(obj); switcher->loadScreenRegionSwitches(obj); switcher->loadPauseSwitches(obj); switcher->loadSceneSequenceSwitches(obj); switcher->loadSceneTransitions(obj); switcher->loadIdleSwitches(obj); switcher->loadExecutableSwitches(obj); switcher->loadRandomSwitches(obj); switcher->loadFileSwitches(obj); switcher->loadMediaSwitches(obj); switcher->loadTimeSwitches(obj); switcher->loadAudioSwitches(obj); switcher->loadGeneralSettings(obj); switcher->loadHotkeys(obj); obs_data_release(obj); (void)DisplayMessage(obs_module_text( "AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess")); close(); // restart scene switcher if it was active if (start) switcher->Start(); } int findTabIndex(QTabWidget *tabWidget, int pos) { int at = -1; QString tabName = ""; switch (pos) { case 0: tabName = "generalTab"; break; case 1: tabName = "transitionsTab"; break; case 2: tabName = "pauseTab"; break; case 3: tabName = "windowTitleTab"; break; case 4: tabName = "executableTab"; break; case 5: tabName = "screenRegionTab"; break; case 6: tabName = "mediaTab"; break; case 7: tabName = "fileTab"; break; case 8: tabName = "randomTab"; break; case 9: tabName = "timeTab"; break; case 10: tabName = "idleTab"; break; case 11: tabName = "sceneSequenceTab"; break; case 12: tabName = "audioTab"; break; case 13: tabName = "sceneGroupTab"; break; } QWidget *page = tabWidget->findChild(tabName); if (page) { at = tabWidget->indexOf(page); } if (at == -1) blog(LOG_INFO, "failed to find tab %s", tabName.toUtf8().constData()); return at; } void AdvSceneSwitcher::setTabOrder() { QTabBar *bar = ui->tabWidget->tabBar(); for (int i = 0; i < bar->count(); ++i) { int curPos = findTabIndex(ui->tabWidget, switcher->tabOrder[i]); if (i != curPos && curPos != -1) bar->moveTab(curPos, i); } connect(bar, &QTabBar::tabMoved, this, &AdvSceneSwitcher::on_tabMoved); } void AdvSceneSwitcher::on_tabMoved(int from, int to) { if (loading) return; std::swap(switcher->tabOrder[from], switcher->tabOrder[to]); } void AdvSceneSwitcher::on_tabWidget_currentChanged(int index) { UNUSED_PARAMETER(index); switcher->showFrame = false; clearFrames(ui->screenRegionSwitches); SetShowFrames(); } void SwitcherData::saveGeneralSettings(obs_data_t *obj) { obs_data_set_int(obj, "interval", switcher->interval); std::string nonMatchingSceneName = GetWeakSourceName(switcher->nonMatchingScene); 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_double(obj, "noMatchDelay", switcher->noMatchDelay); obs_data_set_double(obj, "cooldown", switcher->cooldown); obs_data_set_bool(obj, "active", !switcher->stop); obs_data_set_int(obj, "startup_behavior", switcher->startupBehavior); std::string autoStopSceneName = GetWeakSourceName(switcher->autoStopScene); obs_data_set_bool(obj, "autoStopEnable", switcher->autoStopEnable); obs_data_set_int(obj, "autoStopType", switcher->autoStopType); obs_data_set_string(obj, "autoStopSceneName", autoStopSceneName.c_str()); std::string autoStartSceneName = GetWeakSourceName(switcher->autoStartScene); obs_data_set_bool(obj, "autoStartEnable", switcher->autoStartEnable); obs_data_set_int(obj, "autoStartType", switcher->autoStartType); obs_data_set_string(obj, "autoStartSceneName", autoStartSceneName.c_str()); obs_data_set_bool(obj, "verbose", switcher->verbose); obs_data_set_bool(obj, "disableHints", switcher->disableHints); 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_int(obj, "priority7", switcher->functionNamesByPriority[7]); obs_data_set_int(obj, "priority8", switcher->functionNamesByPriority[8]); obs_data_set_int(obj, "threadPriority", switcher->threadPriority); // After fresh install of OBS the vector can be empty // as save() might be called before first load() if (switcher->tabOrder.size() < tab_count) { switcher->tabOrder = std::vector(tab_count); std::iota(switcher->tabOrder.begin(), switcher->tabOrder.end(), 0); } obs_data_set_int(obj, "generalTabPos", switcher->tabOrder[0]); obs_data_set_int(obj, "transitionTabPos", switcher->tabOrder[1]); obs_data_set_int(obj, "pauseTabPos", switcher->tabOrder[2]); obs_data_set_int(obj, "titleTabPos", switcher->tabOrder[3]); obs_data_set_int(obj, "exeTabPos", switcher->tabOrder[4]); obs_data_set_int(obj, "regionTabPos", switcher->tabOrder[5]); obs_data_set_int(obj, "mediaTabPos", switcher->tabOrder[6]); obs_data_set_int(obj, "fileTabPos", switcher->tabOrder[7]); obs_data_set_int(obj, "randomTabPos", switcher->tabOrder[8]); obs_data_set_int(obj, "timeTabPos", switcher->tabOrder[9]); obs_data_set_int(obj, "idleTabPos", switcher->tabOrder[10]); obs_data_set_int(obj, "sequenceTabPos", switcher->tabOrder[11]); obs_data_set_int(obj, "audioTabPos", switcher->tabOrder[12]); obs_data_set_int(obj, "sceneGroupTabPos", switcher->tabOrder[13]); } void SwitcherData::loadGeneralSettings(obs_data_t *obj) { 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"); std::string nonMatchingScene = obs_data_get_string(obj, "non_matching_scene"); switcher->nonMatchingScene = GetWeakSourceByName(nonMatchingScene.c_str()); switcher->noMatchDelay = obs_data_get_double(obj, "noMatchDelay"); switcher->cooldown = obs_data_get_double(obj, "cooldown"); switcher->stop = !obs_data_get_bool(obj, "active"); switcher->startupBehavior = (StartupBehavior)obs_data_get_int(obj, "startup_behavior"); if (switcher->startupBehavior == START) switcher->stop = false; if (switcher->startupBehavior == STOP) switcher->stop = true; std::string autoStopScene = obs_data_get_string(obj, "autoStopSceneName"); switcher->autoStopEnable = obs_data_get_bool(obj, "autoStopEnable"); switcher->autoStopType = (AutoStartStopType)obs_data_get_int(obj, "autoStopType"); switcher->autoStopScene = GetWeakSourceByName(autoStopScene.c_str()); std::string autoStartScene = obs_data_get_string(obj, "autoStartSceneName"); switcher->autoStartEnable = obs_data_get_bool(obj, "autoStartEnable"); switcher->autoStartType = (AutoStartStopType)obs_data_get_int(obj, "autoStartType"); switcher->autoStartScene = GetWeakSourceByName(autoStartScene.c_str()); switcher->verbose = obs_data_get_bool(obj, "verbose"); switcher->disableHints = obs_data_get_bool(obj, "disableHints"); obs_data_set_default_int(obj, "priority0", default_priority_0); obs_data_set_default_int(obj, "priority1", default_priority_1); obs_data_set_default_int(obj, "priority2", default_priority_2); obs_data_set_default_int(obj, "priority3", default_priority_3); obs_data_set_default_int(obj, "priority4", default_priority_4); obs_data_set_default_int(obj, "priority5", default_priority_5); obs_data_set_default_int(obj, "priority6", default_priority_6); obs_data_set_default_int(obj, "priority7", default_priority_7); obs_data_set_default_int(obj, "priority8", default_priority_8); 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")); switcher->functionNamesByPriority[7] = (obs_data_get_int(obj, "priority7")); switcher->functionNamesByPriority[8] = (obs_data_get_int(obj, "priority8")); 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); switcher->functionNamesByPriority[7] = (default_priority_7); switcher->functionNamesByPriority[8] = (default_priority_8); } obs_data_set_default_int(obj, "threadPriority", QThread::NormalPriority); switcher->threadPriority = obs_data_get_int(obj, "threadPriority"); obs_data_set_default_int(obj, "generalTabPos", 0); obs_data_set_default_int(obj, "transitionTabPos", 1); obs_data_set_default_int(obj, "pauseTabPos", 2); obs_data_set_default_int(obj, "titleTabPos", 3); obs_data_set_default_int(obj, "exeTabPos", 4); obs_data_set_default_int(obj, "regionTabPos", 5); obs_data_set_default_int(obj, "mediaTabPos", 6); obs_data_set_default_int(obj, "fileTabPos", 7); obs_data_set_default_int(obj, "randomTabPos", 8); obs_data_set_default_int(obj, "timeTabPos", 9); obs_data_set_default_int(obj, "idleTabPos", 10); obs_data_set_default_int(obj, "sequenceTabPos", 11); obs_data_set_default_int(obj, "audioTabPos", 12); obs_data_set_default_int(obj, "sceneGroupTabPos", 13); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "generalTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "transitionTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "pauseTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "titleTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "exeTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "regionTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "mediaTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "fileTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "randomTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "timeTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "idleTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "sequenceTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "audioTabPos"))); switcher->tabOrder.emplace_back( (int)(obs_data_get_int(obj, "sceneGroupTabPos"))); } void SwitcherData::checkNoMatchSwitch(bool &match, OBSWeakSource &scene, OBSWeakSource &transition, int &sleep) { if (match) { noMatchCount = 0; return; } if ((noMatchCount * interval) / 1000.0 < noMatchDelay) { noMatchCount++; return; } if (switchIfNotMatching == SWITCH && nonMatchingScene) { match = true; scene = nonMatchingScene; transition = nullptr; } if (switchIfNotMatching == RANDOM_SWITCH) { checkRandom(match, scene, transition, sleep); } } void SwitcherData::checkSwitchCooldown(bool &match) { if (!match || cooldown == 0.) { return; } auto now = std::chrono::high_resolution_clock::now(); auto timePassed = std::chrono::duration_cast( now - lastMatchTime); if (timePassed.count() > cooldown * 1000) { lastMatchTime = now; return; } match = false; if (verbose) blog(LOG_INFO, "cooldown active - ignoring match"); } void populateAutoStartStopTypeSelection(QComboBox *cb) { cb->addItem(obs_module_text( "AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.recording")); cb->addItem(obs_module_text( "AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.streaming")); cb->addItem(obs_module_text( "AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.recordingAndStreaming")); } void AdvSceneSwitcher::setupGeneralTab() { populateSceneSelection(ui->noMatchSwitchScene, false); populateSceneSelection(ui->autoStopScenes, false); populateSceneSelection(ui->autoStartScenes, false); if (switcher->switchIfNotMatching == SWITCH) { ui->noMatchSwitch->setChecked(true); ui->noMatchSwitchScene->setEnabled(true); } else if (switcher->switchIfNotMatching == NO_SWITCH) { ui->noMatchDontSwitch->setChecked(true); ui->noMatchSwitchScene->setEnabled(false); } else { ui->noMatchRandomSwitch->setChecked(true); ui->noMatchSwitchScene->setEnabled(false); } ui->noMatchSwitchScene->setCurrentText( GetWeakSourceName(switcher->nonMatchingScene).c_str()); ui->noMatchDelay->setValue(switcher->noMatchDelay); ui->noMatchDelay->setToolTip(obs_module_text( "AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip")); ui->checkInterval->setValue(switcher->interval); ui->cooldownTime->setValue(switcher->cooldown); ui->cooldownTime->setToolTip(obs_module_text( "AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint")); populateAutoStartStopTypeSelection(ui->autoStopType); ui->autoStopSceneCheckBox->setChecked(switcher->autoStopEnable); ui->autoStopScenes->setCurrentText( GetWeakSourceName(switcher->autoStopScene).c_str()); ui->autoStopType->setCurrentIndex(switcher->autoStopType); if (ui->autoStopSceneCheckBox->checkState()) { ui->autoStopScenes->setDisabled(false); ui->autoStopType->setDisabled(false); } else { ui->autoStopScenes->setDisabled(true); ui->autoStopType->setDisabled(true); } populateAutoStartStopTypeSelection(ui->autoStartType); ui->autoStartSceneCheckBox->setChecked(switcher->autoStartEnable); ui->autoStartScenes->setCurrentText( GetWeakSourceName(switcher->autoStartScene).c_str()); ui->autoStartType->setCurrentIndex(switcher->autoStartType); if (ui->autoStartSceneCheckBox->checkState()) { ui->autoStartScenes->setDisabled(false); ui->autoStartType->setDisabled(false); } else { ui->autoStartScenes->setDisabled(true); ui->autoStartType->setDisabled(true); } ui->verboseLogging->setChecked(switcher->verbose); ui->uiHintsDisable->setChecked(switcher->disableHints); for (int p : switcher->functionNamesByPriority) { std::string s = ""; switch (p) { case read_file_func: s = obs_module_text( "AdvSceneSwitcher.generalTab.priority.fileContent"); break; case round_trip_func: s = obs_module_text( "AdvSceneSwitcher.generalTab.priority.sceneSequence"); break; case idle_func: s = obs_module_text( "AdvSceneSwitcher.generalTab.priority.idleDetection"); break; case exe_func: s = obs_module_text( "AdvSceneSwitcher.generalTab.priority.executable"); break; case screen_region_func: s = obs_module_text( "AdvSceneSwitcher.generalTab.priority.screenRegion"); break; case window_title_func: s = obs_module_text( "AdvSceneSwitcher.generalTab.priority.windowTitle"); break; case media_func: s = obs_module_text( "AdvSceneSwitcher.generalTab.priority.media"); break; case time_func: s = obs_module_text( "AdvSceneSwitcher.generalTab.priority.time"); break; case audio_func: s = obs_module_text( "AdvSceneSwitcher.generalTab.priority.audio"); break; } QString text(s.c_str()); QListWidgetItem *item = new QListWidgetItem(text, ui->priorityList); item->setData(Qt::UserRole, text); } for (int i = 0; i < (int)switcher->threadPriorities.size(); ++i) { ui->threadPriority->addItem( switcher->threadPriorities[i].name.c_str()); ui->threadPriority->setItemData( i, switcher->threadPriorities[i].description.c_str(), Qt::ToolTipRole); if (switcher->threadPriority == switcher->threadPriorities[i].value) { ui->threadPriority->setCurrentText( switcher->threadPriorities[i].name.c_str()); } } ui->startupBehavior->addItem(obs_module_text( "AdvSceneSwitcher.generalTab.status.onStartup.asLastRun")); ui->startupBehavior->addItem(obs_module_text( "AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart")); ui->startupBehavior->addItem(obs_module_text( "AdvSceneSwitcher.generalTab.status.onStartup.doNotStart")); ui->startupBehavior->setCurrentIndex(switcher->startupBehavior); if (switcher->th && switcher->th->isRunning()) SetStarted(); else SetStopped(); }