From b80c16a446c68902666892d55cae11535f49cf15 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Mon, 17 May 2021 20:49:28 +0200 Subject: [PATCH] Add macro action filter --- CMakeLists.txt | 2 + data/locale/en-US.ini | 6 + src/headers/macro-action-filter.hpp | 61 +++++++++ src/macro-action-filter.cpp | 198 ++++++++++++++++++++++++++++ 4 files changed, 267 insertions(+) create mode 100644 src/headers/macro-action-filter.hpp create mode 100644 src/macro-action-filter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 54524cfe..39e4f3ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ set(advanced-scene-switcher_HEADERS src/headers/switch-video.hpp src/headers/switch-generic.hpp src/headers/macro-action-edit.hpp + src/headers/macro-action-filter.hpp src/headers/macro-action-audio.hpp src/headers/macro-action-recording.hpp src/headers/macro-action-replay-buffer.hpp @@ -138,6 +139,7 @@ set(advanced-scene-switcher_SOURCES src/switch-video.cpp src/switch-generic.cpp src/macro-action-edit.cpp + src/macro-action-filter.cpp src/macro-action-audio.cpp src/macro-action-recording.cpp src/macro-action-replay-buffer.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index bec3c457..4ba0c843 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -159,6 +159,10 @@ AdvSceneSwitcher.action.sceneVisibility="Scene visibility" AdvSceneSwitcher.action.sceneVisibility.type.show="Show" AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide" AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sources}}" +AdvSceneSwitcher.action.filter="Filter" +AdvSceneSwitcher.action.filter.type.enable="Enable" +AdvSceneSwitcher.action.filter.type.disable="Disable" +AdvSceneSwitcher.action.filter.entry="On {{sources}} {{actions}} {{filters}}" ; Transition Tab @@ -409,10 +413,12 @@ AdvSceneSwitcher.selectPreviousScene="Previous Scene" AdvSceneSwitcher.currentTransition="Current Transition" AdvSceneSwitcher.selectTransition="--select transition--" AdvSceneSwitcher.selectWindow="--select window--" +AdvSceneSwitcher.selectSource="--select source--" AdvSceneSwitcher.selectAudioSource="--select audio source--" AdvSceneSwitcher.selectVideoSource="--select video source--" AdvSceneSwitcher.selectMediaSource="--select media source--" AdvSceneSwitcher.selectProcess="--select process--" +AdvSceneSwitcher.selectFilter="--select filter--" AdvSceneSwitcher.selectItem="--select item--" AdvSceneSwitcher.enterPath="--enter path--" AdvSceneSwitcher.enterText="--enter text--" diff --git a/src/headers/macro-action-filter.hpp b/src/headers/macro-action-filter.hpp new file mode 100644 index 00000000..64c91e60 --- /dev/null +++ b/src/headers/macro-action-filter.hpp @@ -0,0 +1,61 @@ +#pragma once +#include +#include "macro-action-edit.hpp" + +enum class FilterAction { + ENABLE, + DISABLE, +}; + +class MacroActionFilter : public MacroAction { +public: + bool PerformAction(); + void LogAction(); + bool Save(obs_data_t *obj); + bool Load(obs_data_t *obj); + int GetId() { return id; }; + static std::shared_ptr Create() + { + return std::make_shared(); + } + + OBSWeakSource _source; + OBSWeakSource _filter; + FilterAction _action = FilterAction::ENABLE; + +private: + static bool _registered; + static const int id; +}; + +class MacroActionFilterEdit : public QWidget { + Q_OBJECT + +public: + MacroActionFilterEdit( + QWidget *parent, + std::shared_ptr entryData = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr action) + { + return new MacroActionFilterEdit( + parent, + std::dynamic_pointer_cast(action)); + } + +private slots: + void SourceChanged(const QString &text); + void FilterChanged(const QString &text); + void ActionChanged(int value); + +protected: + QComboBox *_sources; + QComboBox *_filters; + QComboBox *_actions; + std::shared_ptr _entryData; + +private: + QHBoxLayout *_mainLayout; + bool _loading = true; +}; diff --git a/src/macro-action-filter.cpp b/src/macro-action-filter.cpp new file mode 100644 index 00000000..39447aff --- /dev/null +++ b/src/macro-action-filter.cpp @@ -0,0 +1,198 @@ +#include "headers/macro-action-filter.hpp" +#include "headers/advanced-scene-switcher.hpp" +#include "headers/utility.hpp" + +const int MacroActionFilter::id = 8; + +bool MacroActionFilter::_registered = MacroActionFactory::Register( + MacroActionFilter::id, + {MacroActionFilter::Create, MacroActionFilterEdit::Create, + "AdvSceneSwitcher.action.filter"}); + +const static std::map actionTypes = { + {FilterAction::ENABLE, "AdvSceneSwitcher.action.filter.type.enable"}, + {FilterAction::DISABLE, "AdvSceneSwitcher.action.filter.type.disable"}, +}; + +bool MacroActionFilter::PerformAction() +{ + auto s = obs_weak_source_get_source(_filter); + switch (_action) { + case FilterAction::ENABLE: + obs_source_set_enabled(s, true); + break; + case FilterAction::DISABLE: + obs_source_set_enabled(s, false); + break; + default: + break; + } + obs_source_release(s); + return true; +} + +void MacroActionFilter::LogAction() +{ + auto it = actionTypes.find(_action); + if (it != actionTypes.end()) { + vblog(LOG_INFO, + "performed action \"%s\" for filter \"%s\" on source \"%s\"", + it->second.c_str(), GetWeakSourceName(_filter).c_str(), + GetWeakSourceName(_source).c_str()); + } else { + blog(LOG_WARNING, "ignored unknown filter action %d", + static_cast(_action)); + } +} + +bool MacroActionFilter::Save(obs_data_t *obj) +{ + MacroAction::Save(obj); + obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str()); + obs_data_set_string(obj, "filter", GetWeakSourceName(_filter).c_str()); + obs_data_set_int(obj, "action", static_cast(_action)); + return true; +} + +bool MacroActionFilter::Load(obs_data_t *obj) +{ + MacroAction::Load(obj); + const char *sourceName = obs_data_get_string(obj, "source"); + _source = GetWeakSourceByName(sourceName); + const char *filterName = obs_data_get_string(obj, "filter"); + _filter = GetWeakFilterByQString(_source, filterName); + _action = static_cast(obs_data_get_int(obj, "action")); + return true; +} + +static inline void populateActionSelection(QComboBox *list) +{ + for (auto entry : actionTypes) { + list->addItem(obs_module_text(entry.second.c_str())); + } +} + +static inline void populateFilters(QComboBox *list, + OBSWeakSource weakSource = nullptr) +{ + auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *ptr) { + QComboBox *list = reinterpret_cast(ptr); + auto name = obs_source_get_name(filter); + list->addItem(name); + }; + + list->clear(); + list->addItem(obs_module_text("AdvSceneSwitcher.selectFilter")); + auto s = obs_weak_source_get_source(weakSource); + obs_source_enum_filters(s, enumFilters, list); + obs_source_release(s); +} + +static inline void hasFilterEnum(obs_source_t *, obs_source_t *filter, + void *ptr) +{ + if (!filter) { + return; + } + bool *hasFilter = reinterpret_cast(ptr); + *hasFilter = true; +} + +static inline void populateSourcesWithFilter(QComboBox *list) +{ + auto enumSourcesWithFilters = [](void *param, obs_source_t *source) { + if (!source) { + return true; + } + QComboBox *list = reinterpret_cast(param); + bool hasFilter = false; + obs_source_enum_filters(source, hasFilterEnum, &hasFilter); + if (hasFilter) { + list->addItem(obs_source_get_name(source)); + } + return true; + }; + + list->clear(); + list->addItem(obs_module_text("AdvSceneSwitcher.selectSource")); + obs_enum_sources(enumSourcesWithFilters, list); +} + +MacroActionFilterEdit::MacroActionFilterEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent) +{ + _sources = new QComboBox(); + _filters = new QComboBox(); + _actions = new QComboBox(); + + populateActionSelection(_actions); + populateSourcesWithFilter(_sources); + + QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, + SLOT(ActionChanged(int))); + QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)), + this, SLOT(SourceChanged(const QString &))); + QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)), + this, SLOT(FilterChanged(const QString &))); + + QHBoxLayout *mainLayout = new QHBoxLayout; + std::unordered_map widgetPlaceholders = { + {"{{sources}}", _sources}, + {"{{filters}}", _filters}, + {"{{actions}}", _actions}, + }; + placeWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"), + mainLayout, widgetPlaceholders); + setLayout(mainLayout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroActionFilterEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _actions->setCurrentIndex(static_cast(_entryData->_action)); + _sources->setCurrentText( + GetWeakSourceName(_entryData->_source).c_str()); + populateFilters(_filters, _entryData->_source); + _filters->setCurrentText( + GetWeakSourceName(_entryData->_filter).c_str()); +} + +void MacroActionFilterEdit::SourceChanged(const QString &text) +{ + if (_loading || !_entryData) { + return; + } + { + std::lock_guard lock(switcher->m); + _entryData->_source = GetWeakSourceByQString(text); + } + populateFilters(_filters, _entryData->_source); +} + +void MacroActionFilterEdit::FilterChanged(const QString &text) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_filter = GetWeakFilterByQString(_entryData->_source, text); +} + +void MacroActionFilterEdit::ActionChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_action = static_cast(value); +}