diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index ea4f2908..d4a2496f 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -44,597 +44,521 @@ General - - - - - - - WARNING! Condition checking interval must be greater than the duration of transitions to avoid scene locking - - - - - - - - - Qt::Horizontal - - - - - - - - - Qt::Vertical - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 0 - - - - - - - - - - Start - - - - - - - Check switch conditions every - - - - - - - Not Active - - - - - - - Advanced Scene Switcher is: - - - - - - - - 100 - 0 - - - - ms - - - 50 - - - 20000 - - - 300 - - - - - - - - - - - - - Don't switch - - - true - - - - - - - - - - - Switch to any scene in Random tab - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Switch to: - - - - - - - true - - - - 100 - 0 - - - - - - - - - - - - - 0 - 0 - - - - If no switch condition is met - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 0 - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 0 - - - - - - - - Qt::Vertical - - - - - - - On startup: - - - - - - - - - Qt::Horizontal - - - + - - - Order the different switching methods in order of their priority (with the highest priority being at the top): - - + + + + + Status + + + + + + + + Hotkeys can be defined in the OBS settings + + + + + + + Advanced Scene Switcher is: + + + + + + + On startup: + + + + + + + Start + + + + + + + + + + + 100 + 0 + + + + ms + + + 50 + + + 20000 + + + 300 + + + + + + + Check switch conditions every + + + + + + + + + Not Active + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + General behavior + + + + + + + + Automatically start + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + on scene + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Automatically stop streaming/recording on scene + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Enable verbose logging (Only needed for debugging) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Don't switch + + + true + + + + + + + + + + + Switch to any scene in Random tab + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Switch to: + + + + + + + true + + + + 100 + 0 + + + + + + + + + + + + + 0 + 0 + + + + If no switch condition is met + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + + + + - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - 22 - 22 - - - - - ../../../forms/images/up.png../../../forms/images/up.png - - - true - - - upArrowIconSmall - - - - - - - - 22 - 22 - - - - - ../../../forms/images/down.png../../../forms/images/down.png - - - true - - - downArrowIconSmall - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Automatically stop streaming/recording on scene - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Automatically start - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - on scene - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Horizontal - - - - - - - - - Use thread priority - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - (raising the priority higher than "Normal" is usually not recommended) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Horizontal - - - - - - - - - Export settings to file - - - - - - - Import settings from file - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Horizontal - - - - - - - (You can set a Hotkey to start and stop the scene switcher under Settings / Hotkeys / Toggle Start Stop for the Advanced Scene Switcher) - - - - - - - Qt::Horizontal - - - - - - - - - Enable verbose logging (Only needed for debugging) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + Priority + + + + + + Switching methods priority (Highest priority is at the top) + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 22 + 22 + + + + + ../../../forms/images/up.png../../../forms/images/up.png + + + true + + + upArrowIconSmall + + + + + + + + 22 + 22 + + + + + ../../../forms/images/down.png../../../forms/images/down.png + + + true + + + downArrowIconSmall + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Use thread priority + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + (Raising the priority above "Normal" is not recommended) + + + + + + + + + + Save / load settings + + + + + + Export + + + + + + + Import + + + + + + + diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index b246eef6..8fc3da57 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -34,45 +34,6 @@ SceneSwitcher::SceneSwitcher(QWidget *parent) loadUI(); } -void SceneSwitcher::populateSceneSelection(QComboBox *sel, bool addPrevious) -{ - BPtr scenes = obs_frontend_get_scene_names(); - char **temp = scenes; - while (*temp) { - const char *name = *temp; - sel->addItem(name); - temp++; - } - - if (addPrevious) - sel->addItem(previous_scene_name); -} - -void SceneSwitcher::populateTransitionSelection(QComboBox *sel) -{ - 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]); - sel->addItem(name); - } - - obs_frontend_source_list_free(transitions); -} - -void SceneSwitcher::populateWindowSelection(QComboBox *sel) -{ - std::vector windows; - GetWindowList(windows); - sort(windows.begin(), windows.end()); - - for (std::string &window : windows) { - sel->addItem(window.c_str()); - } -} - void SceneSwitcher::loadUI() { #if __APPLE__ @@ -237,7 +198,7 @@ void SwitcherData::Thread() break; case round_trip_func: checkSceneSequence(match, scene, transition, - lock); + lock); if (sceneChangedDuringWait()) //scene might have changed during the sleep { goto startLoop; @@ -343,6 +304,79 @@ void SwitcherData::Stop() } } +void SceneSwitcher::populateSceneSelection(QComboBox *sel, bool addPrevious) +{ + BPtr scenes = obs_frontend_get_scene_names(); + char **temp = scenes; + while (*temp) { + const char *name = *temp; + sel->addItem(name); + temp++; + } + + if (addPrevious) + sel->addItem(previous_scene_name); +} + +void SceneSwitcher::populateTransitionSelection(QComboBox *sel) +{ + 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]); + sel->addItem(name); + } + + obs_frontend_source_list_free(transitions); +} + +void SceneSwitcher::populateWindowSelection(QComboBox *sel) +{ + std::vector windows; + GetWindowList(windows); + sort(windows.begin(), windows.end()); + + for (std::string &window : windows) { + sel->addItem(window.c_str()); + } +} + +void SceneSwitcher::populateAudioSelection(QComboBox *sel) +{ + auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ + { + QComboBox *combo = reinterpret_cast(data); + uint32_t flags = obs_source_get_output_flags(source); + + if ((flags & OBS_SOURCE_AUDIO) != 0) { + const char *name = obs_source_get_name(source); + combo->addItem(name); + } + return true; + }; + + obs_enum_sources(sourceEnum, sel); +} + +void SceneSwitcher::populateMediaSelection(QComboBox *sel) +{ + auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ + { + QComboBox *combo = reinterpret_cast(data); + std::string sourceId = obs_source_get_id(source); + if (sourceId.compare("ffmpeg_source") == 0 || + sourceId.compare("vlc_source") == 0) { + const char *name = obs_source_get_name(source); + combo->addItem(name); + } + return true; + }; + + obs_enum_sources(sourceEnum, sel); +} + /******************************************************************************** * OBS module setup ********************************************************************************/ diff --git a/src/general.cpp b/src/general.cpp index 6111a74c..6c2e4137 100644 --- a/src/general.cpp +++ b/src/general.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "headers/advanced-scene-switcher.hpp" @@ -79,16 +81,52 @@ void SceneSwitcher::on_checkInterval_valueChanged(int value) switcher->interval = value; } +void SceneSwitcher::StartInactivePulse() +{ + ui->pluginRunningText->setStyleSheet("QLabel { \ + border-style: outset; \ + border-width: 2px; \ + border-radius: 10px; \ + border-color: rgb(0,0,0,0) \ + }"); + + QGraphicsColorizeEffect *eEffect = + new QGraphicsColorizeEffect(ui->pluginRunningText); + ui->pluginRunningText->setGraphicsEffect(eEffect); + QPropertyAnimation *paAnimation = + new QPropertyAnimation(eEffect, "color"); + paAnimation->setStartValue(QColor(0, 0, 0, 0)); + paAnimation->setEndValue(QColor(Qt::red)); + paAnimation->setDuration(1000); + + connect(paAnimation, &QPropertyAnimation::finished, [paAnimation]() { + if (switcher->stop) + QTimer::singleShot(1000, [paAnimation] { + paAnimation->start(); + }); + }); + + paAnimation->start(); +} + +void SceneSwitcher::ResetInactivePulse() +{ + ui->pluginRunningText->setStyleSheet( + "QLabel { background-color: rgb(0,0,0,0); }"); +} + void SceneSwitcher::SetStarted() { ui->toggleStartButton->setText("Stop"); ui->pluginRunningText->setText("Active"); + ResetInactivePulse(); } void SceneSwitcher::SetStopped() { ui->toggleStartButton->setText("Start"); ui->pluginRunningText->setText("Inactive"); + StartInactivePulse(); } void SceneSwitcher::on_toggleStartButton_clicked() diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index 8dc31914..509ca26d 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -55,9 +55,6 @@ public: void SetAudioVolumeMeter(const QString &name); void loadUI(); - void populateSceneSelection(QComboBox *sel, bool addPrevious); - void populateTransitionSelection(QComboBox *sel); - void populateWindowSelection(QComboBox *sel); void setupGeneralTab(); void setupTitleTab(); void setupExecutableTab(); @@ -73,6 +70,13 @@ public: void setupAudioTab(); void setTabOrder(); + static void populateSceneSelection(QComboBox *sel, + bool addPrevious = false); + static void populateTransitionSelection(QComboBox *sel); + static void populateWindowSelection(QComboBox *sel); + static void populateAudioSelection(QComboBox *sel); + static void populateMediaSelection(QComboBox *sel); + public slots: void on_switches_currentRowChanged(int idx); void on_up_clicked(); @@ -85,6 +89,8 @@ public slots: void on_startupBehavior_currentIndexChanged(int index); void on_noMatchSwitchScene_currentTextChanged(const QString &text); void on_checkInterval_valueChanged(int value); + void StartInactivePulse(); + void ResetInactivePulse(); void on_toggleStartButton_clicked(); void on_tabMoved(int from, int to); diff --git a/src/headers/switch-audio.hpp b/src/headers/switch-audio.hpp index d7627fb9..c1fb6b75 100644 --- a/src/headers/switch-audio.hpp +++ b/src/headers/switch-audio.hpp @@ -1,7 +1,12 @@ #pragma once +#include +#include +#include #include + #include "utility.hpp" #include "switch-generic.hpp" +#include "volume-control.hpp" constexpr auto audio_func = 8; constexpr auto default_priority_8 = audio_func; @@ -113,3 +118,27 @@ static inline QString MakeAudioSwitchName(const QString &scene, const QString &transition, const QString &audioSrouce, const int &volume); + +class AudioSwitchWidget : public QWidget { + Q_OBJECT + +public: + AudioSwitchWidget(QWidget *parent = nullptr, + const QString &audioScene = "", + const QString &audioTransition = "", + const QString &audioSource = "", + const int &threshold = 0); + +private: + QComboBox *audioScenes; + QComboBox *audioTransitions; + QComboBox *audioSources; + QSpinBox *audioVolumeThreshold; + + VolControl *volMeter; + + QLabel *whenLabel; + QLabel *aboveLabel; + QLabel *switchLabel; + QLabel *usingLabel; +}; diff --git a/src/switch-audio.cpp b/src/switch-audio.cpp index 60812ddd..f32cb5f9 100644 --- a/src/switch-audio.cpp +++ b/src/switch-audio.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "headers/advanced-scene-switcher.hpp" #include "headers/volume-control.hpp" @@ -289,20 +292,7 @@ void SceneSwitcher::setupAudioTab() { populateSceneSelection(ui->audioScenes, true); populateTransitionSelection(ui->audioTransitions); - - auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ - { - QComboBox *combo = reinterpret_cast(data); - uint32_t flags = obs_source_get_output_flags(source); - - if ((flags & OBS_SOURCE_AUDIO) != 0) { - const char *name = obs_source_get_name(source); - combo->addItem(name); - } - return true; - }; - - obs_enum_sources(sourceEnum, ui->audioSources); + populateAudioSelection(ui->audioSources); for (auto &s : switcher->audioSwitches) { std::string sceneName = (s.usePreviousScene) @@ -315,9 +305,18 @@ void SceneSwitcher::setupAudioTab() audioSourceName.c_str(), s.volumeThreshold); - QListWidgetItem *item = - new QListWidgetItem(listText, ui->audioSwitches); - item->setData(Qt::UserRole, listText); + //QListWidgetItem *item = + // new QListWidgetItem(listText, ui->audioSwitches); + //item->setData(Qt::UserRole, listText); + + QListWidgetItem *item; + item = new QListWidgetItem(ui->audioSwitches); + ui->audioSwitches->addItem(item); + AudioSwitchWidget *sw = new AudioSwitchWidget( + nullptr, sceneName.c_str(), transitionName.c_str(), + audioSourceName.c_str(), s.volumeThreshold); + item->setSizeHint(sw->minimumSizeHint()); + ui->audioSwitches->setItemWidget(item, sw); } } @@ -333,3 +332,64 @@ static inline QString MakeAudioSwitchName(const QString &scene, QStringLiteral(" using ") + transition; return switchName; } + +AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, const QString &audioScene, + const QString &audioTransition, + const QString &audioSource, + const int &threshold) + : QWidget(parent) +{ + audioScenes = new QComboBox(); + audioTransitions = new QComboBox(); + audioSources = new QComboBox(); + audioVolumeThreshold = new QSpinBox(); + + obs_source_t *soruce = + obs_get_source_by_name(audioSource.toUtf8().constData()); + volMeter = new VolControl(soruce); + obs_source_release(soruce); + + whenLabel = new QLabel("When the volume of"); + aboveLabel = new QLabel("is above"); + switchLabel = new QLabel("switch to"); + usingLabel = new QLabel("using"); + + audioVolumeThreshold->setSuffix("%"); + audioVolumeThreshold->setMaximum(100); + audioVolumeThreshold->setMinimum(0); + + QWidget::connect(volMeter->GetSlider(), SIGNAL(valueChanged(int)), + audioVolumeThreshold, SLOT(setValue(int))); + QWidget::connect(audioVolumeThreshold, SIGNAL(valueChanged(int)), + volMeter->GetSlider(), SLOT(setValue(int))); + + SceneSwitcher::populateSceneSelection(audioScenes, true); + SceneSwitcher::populateTransitionSelection(audioTransitions); + SceneSwitcher::populateAudioSelection(audioSources); + + audioScenes->setCurrentText(audioScene); + audioTransitions->setCurrentText(audioTransition); + audioSources->setCurrentText(audioSource); + audioVolumeThreshold->setValue(threshold); + + setStyleSheet("* { background-color: transparent; }"); + + QHBoxLayout *switchLayout = new QHBoxLayout; + + switchLayout->addWidget(whenLabel); + switchLayout->addWidget(audioSources); + switchLayout->addWidget(aboveLabel); + switchLayout->addWidget(audioVolumeThreshold); + switchLayout->addWidget(switchLabel); + switchLayout->addWidget(audioScenes); + switchLayout->addWidget(usingLabel); + switchLayout->addWidget(audioTransitions); + switchLayout->addStretch(); + + QVBoxLayout *mainLayout = new QVBoxLayout; + + mainLayout->addLayout(switchLayout); + mainLayout->addWidget(volMeter); + + setLayout(mainLayout); +} diff --git a/src/switch-media.cpp b/src/switch-media.cpp index 26574aeb..b5e7e552 100644 --- a/src/switch-media.cpp +++ b/src/switch-media.cpp @@ -254,20 +254,7 @@ void SceneSwitcher::setupMediaTab() { populateSceneSelection(ui->mediaScenes, true); populateTransitionSelection(ui->mediaTransitions); - - auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */ - { - QComboBox *combo = reinterpret_cast(data); - std::string sourceId = obs_source_get_id(source); - if (sourceId.compare("ffmpeg_source") == 0 || - sourceId.compare("vlc_source") == 0) { - const char *name = obs_source_get_name(source); - combo->addItem(name); - } - return true; - }; - - obs_enum_sources(sourceEnum, ui->mediaSources); + populateMediaSelection(ui->mediaSources); ui->mediaStates->addItem("None"); ui->mediaStates->addItem("Playing");