diff --git a/BUILDING.md b/BUILDING.md index 7c89e1608..26a2d95ae 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -4,11 +4,13 @@ You have the option to ... - either add the plugin to the OBS source tree directly and build the plugin while building OBS itself. (**in tree**) - or you can move the sources of this plugin outside of the OBS source tree and build it separately from OBS. (**out of tree**) -As both methods require you to have a working [OBS Studio development environment](https://obsproject.com/wiki/Building-OBS-Studio) and [CMake](https://cmake.org/download/) it is recommended to build the plugin in tree as it is easier to set up and will enable straightforward debugging. +Both methods require [CMake](https://cmake.org/download/). -The plugin can be compiled for OBS 25 and above, although using the latest version of OBS is recommended to support all features. +The plugin can be compiled for OBS 27 and above, although using the latest version of OBS is recommended to support all features. ## Compiling in tree (recommended for development) +This section assumes that you have a working [OBS Studio development environment](https://obsproject.com/wiki/Building-OBS-Studio). + Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/: ``` cd obs-studio/UI/frontend-plugins/ @@ -46,12 +48,12 @@ cmake -DOpenCV_DIR="C:/Users/BuildUser/Documents/OBS/opencv/build/" -DLeptonica_ First you will need to clone the plugin sources by running the following command: ``` git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git -cd SceneSwitcher ``` -Next you will need [CMake](https://cmake.org/download/) and run the command with suitable arguments for your particular platform. +Next you will need [CMake](https://cmake.org/download/) and run it with suitable arguments for your particular platform. For example, on Windows you might want to run this command: ``` +cd SceneSwitcher cmake --preset windows-x64 ``` Next, you can build the plugin and install the files into a folder named release using the following commands: @@ -72,7 +74,7 @@ cd SceneSwitcher cmake -DOpenCV_DIR="C:/Users/BuildUser/Documents/OBS/opencv/build/" -DLeptonica_DIR="C:/Users/BuildUser/Documents/OBS/leptonica/build" -DTesseract_DIR="C:/Users/BuildUser/Documents/OBS/tesseract/build/lib/cmake/tesseract" --preset windows-x64 ``` -You can rely on the CI scripts to build the dependencies for you, although it is not guaranteed that they will work in every environment: +You can rely on the CI scripts to build the dependencies for you, although it is not guaranteed that they will function in every environment: | Platform | Command | | ----------- | ----------- | @@ -83,10 +85,10 @@ You can rely on the CI scripts to build the dependencies for you, although it is # Contributing -Contributions to the plugin are always welcome and if you need any assistance do not hesitate to reach out. +Contributions to the plugin are always welcome and if you need any assistance do not hesitate to reach out! If you would like to expand upon the macro system by adding a new condition or action type have a look at the examples in `plugins/base`. -In general changes in the `lib/legacy` folder should be avoided. +In general changes in the `lib/legacy` folder should be avoided, if possible. ## Macro condition Macro conditions should inherit from the `MacroCondition` class and must implement the following functions: @@ -97,12 +99,12 @@ public: MacroConditionExample(Macro *m) : MacroCondition(m) {} // This function should perform the condition check bool CheckCondition(); - // This function should store the required condition data to "obj" + // This function should store the required condition data to "data" // For example called on OBS shutdown - bool Save(obs_data_t *obj); - // This function should load the condition data from "obj" + bool Save(obs_data_t *data); + // This function should load the condition data from "data" // For example called on OBS startup - bool Load(obs_data_t *obj); + bool Load(obs_data_t *data); // This function should return a unique id for this condition type // The _id is defined below std::string GetId() { return _id; }; @@ -120,7 +122,7 @@ private: static const std::string _id; }; ``` -When defining the widget used to control the settings of the condition type, it is important to add a static `Create()` method. +When defining the widget used to control the settings of the condition type, a static `Create()` method is required. It will be called whenever a new condition MacroConditionExample is created. (See `MacroConditionFactory::Register()`) ``` class MacroConditionExampleEdit : public QWidget { @@ -151,7 +153,7 @@ bool MacroConditionExample::_registered = MacroConditionFactory::Register( MacroConditionExample::id, // Unique string identifying this condition type { MacroConditionExample::Create, // Function called to create the object performing the condition - MacroConditionExampleEdit::Create, // Function called to create the widget configure the condition + MacroConditionExampleEdit::Create, // Function called to create the widget to configure the settings "AdvSceneSwitcher.condition.example", // User facing name of the condition type (will be translated) true // Condition type supports duration modifiers (default true) } @@ -167,16 +169,18 @@ The differences are highlighted in the comments below. class MacroActionExample : public MacroAction { public: MacroActionExample(Macro *m) : MacroAction(m) {} + static std::shared_ptr Create(Macro *m); + // Used to create a copy of the action (used for action queues) + std::shared_ptr Copy() const; // This function should perform the action // If false is returned the macro will aborted bool PerformAction(); - bool Save(obs_data_t *obj); - bool Load(obs_data_t *obj); + bool Save(obs_data_t *data); + bool Load(obs_data_t *data); std::string GetId() { return _id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + // Optional: + // Might be called when action is inserted to action queue + void ResolveVariablesToFixedValues(); private: static bool _registered; @@ -207,11 +211,11 @@ MacroActionFactory::Register( MacroActionExample::id, // Unique string identifying this action type { MacroActionExample::Create, // Function called to create the object performing the action - MacroActionExampleEdit::Create, // Function called to create the widget configure the action + MacroActionExampleEdit::Create, // Function called to create the widget to configure the settings "AdvSceneSwitcher.action.example" // User facing name of the action type } ); ``` ## External dependencies -If your intention is to add macro functionality which depends on external libraries, which is likely not to exist on all user setups, have a look at the folders in the `plugins/` directory, which are not named base. -For example `plugins/video` will only be loaded if the `OpenCV` dependencies are met. +If your intention is to add macro functionality which depends on external libraries, which might not exist on all user environments, have a look at the folders in the `plugins/` directory, which are not named `base`. +For example, `plugins/video` will only be loaded if the `OpenCV` dependencies are met. diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index b4a9bff4b..dc5773ff0 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -26,6 +26,10 @@ AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Switch to an AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Switch to:" AdvSceneSwitcher.generalTab.generalBehavior.cooldown="After performing actions skip performing actions for" AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="During this time potential matches will be ignored!" +AdvSceneSwitcher.generalTab.generalBehavior.logLevel="Log level:" +AdvSceneSwitcher.generalTab.generalBehavior.logLevel.default="Default" +AdvSceneSwitcher.generalTab.generalBehavior.logLevel.printActions="Log performed actions" +AdvSceneSwitcher.generalTab.generalBehavior.logLevel.verbose="Verbose logging" AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Enable verbose logging" AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size" AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Show system tray notifications" @@ -968,6 +972,9 @@ AdvSceneSwitcher.action.window.type.maximizeWindow="Maximize window" AdvSceneSwitcher.action.window.type.minimizeWindow="Minimize window" AdvSceneSwitcher.action.window.type.closeWindow="Close window" AdvSceneSwitcher.action.window.entry="{{actions}}{{windows}}{{regex}}" +AdvSceneSwitcher.action.log="Log" +AdvSceneSwitcher.action.log.placeholder="My log message!" +AdvSceneSwitcher.action.log.entry="Write to OBS log:{{logMessage}}" ; Hotkey AdvSceneSwitcher.hotkey.startSwitcherHotkey="Start the Advanced Scene Switcher" @@ -1040,6 +1047,7 @@ AdvSceneSwitcher.actionQueues.configure="Configure action queue settings" AdvSceneSwitcher.actionQueues.invalid="Invalid action queue selection" AdvSceneSwitcher.actionQueues.name="Name:" AdvSceneSwitcher.actionQueues.runOnStartup="Run action queue when starting the plugin" +AdvSceneSwitcher.actionQueues.resolveVariablesOnAdd="Resolve variables when action is inserted into the queue" AdvSceneSwitcher.actionQueues.running="Queue is running" AdvSceneSwitcher.actionQueues.stopped="Queue is stopped" AdvSceneSwitcher.actionQueues.start="Start action queue" diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index c9e788a22..7494a9b68 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -163,12 +163,31 @@ - + - AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging + AdvSceneSwitcher.generalTab.generalBehavior.logLevel + + + + + AdvSceneSwitcher.generalTab.generalBehavior.logLevel.default + + + + + AdvSceneSwitcher.generalTab.generalBehavior.logLevel.printActions + + + + + AdvSceneSwitcher.generalTab.generalBehavior.logLevel.verbose + + + + @@ -5078,7 +5097,7 @@ checkInterval startupBehavior autoStartEvent - verboseLogging + logLevel saveWindowGeo showTrayNotifications uiHintsDisable diff --git a/lib/advanced-scene-switcher.hpp b/lib/advanced-scene-switcher.hpp index 90556315f..f075d2d2c 100644 --- a/lib/advanced-scene-switcher.hpp +++ b/lib/advanced-scene-switcher.hpp @@ -55,6 +55,7 @@ public slots: void NoMatchDelayDurationChanged(const Duration &); void CooldownDurationChanged(const Duration &); void on_startupBehavior_currentIndexChanged(int index); + void on_logLevel_currentIndexChanged(int index); void on_autoStartEvent_currentIndexChanged(int index); void on_noMatchSwitchScene_currentTextChanged(const QString &text); void on_checkInterval_valueChanged(int value); @@ -62,7 +63,6 @@ public slots: void on_tabWidget_currentChanged(int index); void on_exportSettings_clicked(); void on_importSettings_clicked(); - void on_verboseLogging_stateChanged(int state); void on_saveWindowGeo_stateChanged(int state); void on_showTrayNotifications_stateChanged(int state); void on_uiHintsDisable_stateChanged(int state); diff --git a/lib/general.cpp b/lib/general.cpp index f8d33af0a..499905b8c 100644 --- a/lib/general.cpp +++ b/lib/general.cpp @@ -112,6 +112,14 @@ void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index) static_cast(index); } +void AdvSceneSwitcher::on_logLevel_currentIndexChanged(int value) +{ + if (loading) { + return; + } + switcher->logLevel = static_cast(value); +} + void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index) { if (loading) { @@ -157,15 +165,6 @@ void AdvSceneSwitcher::closeEvent(QCloseEvent *) obs_frontend_save(); } -void AdvSceneSwitcher::on_verboseLogging_stateChanged(int state) -{ - if (loading) { - return; - } - - switcher->verbose = state; -} - void AdvSceneSwitcher::on_saveWindowGeo_stateChanged(int state) { if (loading) { @@ -598,7 +597,7 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj) obs_data_set_int(obj, "autoStartEvent", static_cast(autoStartEvent)); - obs_data_set_bool(obj, "verbose", verbose); + obs_data_set_int(obj, "logLevel", static_cast(logLevel)); obs_data_set_bool(obj, "showSystemTrayNotifications", showSystemTrayNotifications); obs_data_set_bool(obj, "disableHints", disableHints); @@ -649,7 +648,7 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj) autoStartEvent = static_cast(obs_data_get_int(obj, "autoStartEvent")); - verbose = obs_data_get_bool(obj, "verbose"); + logLevel = static_cast(obs_data_get_int(obj, "logLevel")); showSystemTrayNotifications = obs_data_get_bool(obj, "showSystemTrayNotifications"); disableHints = obs_data_get_bool(obj, "disableHints"); @@ -940,7 +939,8 @@ void AdvSceneSwitcher::SetupGeneralTab() SIGNAL(DurationChanged(const Duration &)), this, SLOT(CooldownDurationChanged(const Duration &))); - ui->verboseLogging->setChecked(switcher->verbose); + ui->logLevel->setCurrentIndex(static_cast(switcher->logLevel)); + ui->saveWindowGeo->setChecked(switcher->saveWindowGeo); ui->showTrayNotifications->setChecked( switcher->showSystemTrayNotifications); diff --git a/lib/legacy/switch-audio.cpp b/lib/legacy/switch-audio.cpp index 88d1fdba6..e92c9d4a7 100644 --- a/lib/legacy/switch-audio.cpp +++ b/lib/legacy/switch-audio.cpp @@ -104,7 +104,7 @@ void SwitcherData::checkAudioSwitchFallback(OBSWeakSource &scene, scene = audioFallback.getScene(); transition = audioFallback.transition; - if (verbose) { + if (VerboseLoggingEnabled()) { audioFallback.logMatch(); } } @@ -165,7 +165,7 @@ bool SwitcherData::checkAudioSwitch(OBSWeakSource &scene, transition = s.transition; match = true; - if (verbose) { + if (VerboseLoggingEnabled()) { s.logMatch(); } diff --git a/lib/legacy/switch-executable.cpp b/lib/legacy/switch-executable.cpp index 09185f16b..48d86197b 100644 --- a/lib/legacy/switch-executable.cpp +++ b/lib/legacy/switch-executable.cpp @@ -119,7 +119,7 @@ bool SwitcherData::checkExeSwitch(OBSWeakSource &scene, scene = s.getScene(); transition = s.transition; - if (verbose) { + if (VerboseLoggingEnabled()) { s.logMatch(); } break; diff --git a/lib/legacy/switch-file.cpp b/lib/legacy/switch-file.cpp index b3b321802..7cede7309 100644 --- a/lib/legacy/switch-file.cpp +++ b/lib/legacy/switch-file.cpp @@ -274,7 +274,7 @@ bool SwitcherData::checkFileContent(OBSWeakSource &scene, transition = s.transition; match = true; - if (verbose) { + if (VerboseLoggingEnabled()) { s.logMatch(); } break; diff --git a/lib/legacy/switch-idle.cpp b/lib/legacy/switch-idle.cpp index 8801d9206..40caa891e 100644 --- a/lib/legacy/switch-idle.cpp +++ b/lib/legacy/switch-idle.cpp @@ -53,7 +53,7 @@ bool SwitcherData::checkIdleSwitch(OBSWeakSource &scene, match = true; idleData.alreadySwitched = true; - if (verbose) { + if (VerboseLoggingEnabled()) { idleData.logMatch(); } } else { diff --git a/lib/legacy/switch-media.cpp b/lib/legacy/switch-media.cpp index 4b08e7edb..973ef77bb 100644 --- a/lib/legacy/switch-media.cpp +++ b/lib/legacy/switch-media.cpp @@ -193,7 +193,7 @@ bool SwitcherData::checkMediaSwitch(OBSWeakSource &scene, scene = mediaSwitch.getScene(); transition = mediaSwitch.transition; - if (verbose) { + if (VerboseLoggingEnabled()) { mediaSwitch.logMatch(); } } diff --git a/lib/legacy/switch-network.cpp b/lib/legacy/switch-network.cpp index 5633b9568..e5beb774f 100644 --- a/lib/legacy/switch-network.cpp +++ b/lib/legacy/switch-network.cpp @@ -253,7 +253,7 @@ void WSServer::sendMessage(SceneSwitchInfo sceneSwitch, bool preview) } } - if (switcher->verbose) { + if (VerboseLoggingEnabled()) { blog(LOG_INFO, "server sent message:\n%s", message.c_str()); } } @@ -305,7 +305,7 @@ std::string processMessage(std::string payload) std::string ret = "message ok"; auto transition = GetWeakTransitionByName(transitionName.c_str()); - if (switcher->verbose && !transition) { + if (VerboseLoggingEnabled() && !transition) { ret += " - ignoring invalid transition: '" + transitionName + "'"; } @@ -481,7 +481,7 @@ void WSClient::onMessage(connection_hdl hdl, client::message_ptr message) errorCodeMessage.c_str()); } - if (switcher->verbose) { + if (VerboseLoggingEnabled()) { blog(LOG_INFO, "client sent message:\n%s", response.c_str()); } } diff --git a/lib/legacy/switch-random.cpp b/lib/legacy/switch-random.cpp index 7b9160419..94bc13490 100644 --- a/lib/legacy/switch-random.cpp +++ b/lib/legacy/switch-random.cpp @@ -76,7 +76,7 @@ bool SwitcherData::checkRandom(OBSWeakSource &scene, OBSWeakSource &transition, lastRandomScene = r.scene; lastRandomSceneGroup = r.group; - if (verbose) { + if (VerboseLoggingEnabled()) { r.logMatch(); } break; diff --git a/lib/legacy/switch-screen-region.cpp b/lib/legacy/switch-screen-region.cpp index 9eba3c26d..5eee08240 100644 --- a/lib/legacy/switch-screen-region.cpp +++ b/lib/legacy/switch-screen-region.cpp @@ -183,7 +183,7 @@ bool SwitcherData::checkScreenRegionSwitch(OBSWeakSource &scene, transition = s.transition; minRegionSize = regionSize; - if (verbose) { + if (VerboseLoggingEnabled()) { s.logMatch(); } break; diff --git a/lib/legacy/switch-sequence.cpp b/lib/legacy/switch-sequence.cpp index fad0ef819..5b407c215 100644 --- a/lib/legacy/switch-sequence.cpp +++ b/lib/legacy/switch-sequence.cpp @@ -225,13 +225,13 @@ bool SwitcherData::checkSceneSequence(OBSWeakSource &scene, scene = s.getScene(); transition = s.transition; setPrevSceneAfterLinger = s.usePreviousScene; - if (verbose) { + if (VerboseLoggingEnabled()) { s.logMatch(); } } s.advanceActiveSequence(); - if (verbose) { + if (VerboseLoggingEnabled()) { s.logAdvanceSequence(); } diff --git a/lib/legacy/switch-time.cpp b/lib/legacy/switch-time.cpp index b89054f79..f6964a143 100644 --- a/lib/legacy/switch-time.cpp +++ b/lib/legacy/switch-time.cpp @@ -142,7 +142,7 @@ bool SwitcherData::checkTimeSwitch(OBSWeakSource &scene, transition = s.transition; match = true; - if (verbose) { + if (VerboseLoggingEnabled()) { s.logMatch(); } break; diff --git a/lib/legacy/switch-transitions.cpp b/lib/legacy/switch-transitions.cpp index 320d8f4b4..bdf5d5833 100644 --- a/lib/legacy/switch-transitions.cpp +++ b/lib/legacy/switch-transitions.cpp @@ -168,7 +168,7 @@ void SwitcherData::checkDefaultSceneTransitions() for (auto &t : defaultSceneTransitions) { if (t.checkMatch(currentScene)) { - if (verbose) { + if (VerboseLoggingEnabled()) { t.logMatch(); } t.setTransition(); @@ -427,7 +427,8 @@ DefTransitionSwitchWidget::DefTransitionSwitchWidget(QWidget *parent, { QHBoxLayout *mainLayout = new QHBoxLayout; std::unordered_map widgetPlaceholders = { - {"{{scenes}}", scenes}, {"{{transitions}}", transitions}}; + {"{{scenes}}", scenes}, + {"{{transitions}}", transitions}}; PlaceWidgets( obs_module_text( "AdvSceneSwitcher.transitionTab.defaultTransitionEntry"), diff --git a/lib/legacy/switch-video.cpp b/lib/legacy/switch-video.cpp index 237c34bd8..451f9c807 100644 --- a/lib/legacy/switch-video.cpp +++ b/lib/legacy/switch-video.cpp @@ -148,7 +148,7 @@ bool SwitcherData::checkVideoSwitch(OBSWeakSource &scene, match = true; scene = s.getScene(); transition = s.transition; - if (verbose) { + if (VerboseLoggingEnabled()) { s.logMatch(); } } diff --git a/lib/legacy/switch-window.cpp b/lib/legacy/switch-window.cpp index 57a2b70f5..190b27546 100644 --- a/lib/legacy/switch-window.cpp +++ b/lib/legacy/switch-window.cpp @@ -249,7 +249,7 @@ bool SwitcherData::checkWindowTitleSwitch(OBSWeakSource &scene, } if (match) { - if (verbose) { + if (VerboseLoggingEnabled()) { s.logMatch(); } break; diff --git a/lib/macro/macro-action-edit.cpp b/lib/macro/macro-action-edit.cpp index 59d61ab83..bedee1838 100644 --- a/lib/macro/macro-action-edit.cpp +++ b/lib/macro/macro-action-edit.cpp @@ -3,6 +3,7 @@ #include "macro-helpers.hpp" #include "macro-properties.hpp" #include "macro.hpp" +#include "plugin-state-helpers.hpp" #include "section.hpp" #include "switch-button.hpp" @@ -88,6 +89,7 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text) *_entryData = MacroActionFactory::Create(id, macro); (*_entryData)->SetIndex(idx); (*_entryData)->PostLoad(); + RunPostLoadSteps(); } auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData); QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)), @@ -185,9 +187,10 @@ void AdvSceneSwitcher::AddMacroAction(int idx) auto data = obs_data_create(); macro->Actions().at(idx - 1)->Save(data); macro->Actions().at(idx)->Load(data); - macro->Actions().at(idx)->PostLoad(); obs_data_release(data); } + macro->Actions().at(idx)->PostLoad(); + RunPostLoadSteps(); macro->UpdateActionIndices(); ui->actionsList->Insert( idx, @@ -475,6 +478,7 @@ void AdvSceneSwitcher::AddMacroElseAction(int idx) macro->ElseActions().at(idx)->Load(data); } macro->ElseActions().at(idx)->PostLoad(); + RunPostLoadSteps(); macro->UpdateElseActionIndices(); ui->elseActionsList->Insert( idx, new MacroActionEdit( diff --git a/lib/macro/macro-action-macro.cpp b/lib/macro/macro-action-macro.cpp index 4851b100c..49928ba66 100644 --- a/lib/macro/macro-action-macro.cpp +++ b/lib/macro/macro-action-macro.cpp @@ -88,32 +88,32 @@ void MacroActionMacro::LogAction() const } switch (_action) { case Action::PAUSE: - vblog(LOG_INFO, "paused \"%s\"", macro->Name().c_str()); + ablog(LOG_INFO, "paused \"%s\"", macro->Name().c_str()); break; case Action::UNPAUSE: - vblog(LOG_INFO, "unpaused \"%s\"", macro->Name().c_str()); + ablog(LOG_INFO, "unpaused \"%s\"", macro->Name().c_str()); break; case Action::RESET_COUNTER: - vblog(LOG_INFO, "reset counter for \"%s\"", + ablog(LOG_INFO, "reset counter for \"%s\"", macro->Name().c_str()); break; case Action::RUN: - vblog(LOG_INFO, "run nested macro \"%s\"", + ablog(LOG_INFO, "run nested macro \"%s\"", macro->Name().c_str()); break; case Action::STOP: - vblog(LOG_INFO, "stopped macro \"%s\"", macro->Name().c_str()); + ablog(LOG_INFO, "stopped macro \"%s\"", macro->Name().c_str()); break; case Action::DISABLE_ACTION: - vblog(LOG_INFO, "disabled action %d of macro \"%s\"", + ablog(LOG_INFO, "disabled action %d of macro \"%s\"", _actionIndex.GetValue(), macro->Name().c_str()); break; case Action::ENABLE_ACTION: - vblog(LOG_INFO, "enabled action %d of macro \"%s\"", + ablog(LOG_INFO, "enabled action %d of macro \"%s\"", _actionIndex.GetValue(), macro->Name().c_str()); break; case Action::TOGGLE_ACTION: - vblog(LOG_INFO, "toggled action %d of macro \"%s\"", + ablog(LOG_INFO, "toggled action %d of macro \"%s\"", _actionIndex.GetValue(), macro->Name().c_str()); break; default: @@ -145,6 +145,21 @@ std::string MacroActionMacro::GetShortDesc() const return _macro.Name(); } +std::shared_ptr MacroActionMacro::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionMacro::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionMacro::ResolveVariablesToFixedValues() +{ + _actionIndex.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (auto entry : actionTypes) { diff --git a/lib/macro/macro-action-macro.hpp b/lib/macro/macro-action-macro.hpp index d64c06e6d..7b36835de 100644 --- a/lib/macro/macro-action-macro.hpp +++ b/lib/macro/macro-action-macro.hpp @@ -16,10 +16,9 @@ class MacroActionMacro : public MacroRefAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Action { PAUSE, diff --git a/lib/macro/macro-action-queue.cpp b/lib/macro/macro-action-queue.cpp index 34db2d3d6..a85e9185a 100644 --- a/lib/macro/macro-action-queue.cpp +++ b/lib/macro/macro-action-queue.cpp @@ -69,20 +69,20 @@ void MacroActionQueue::LogAction() const } switch (_action) { case Action::ADD_TO_QUEUE: - vblog(LOG_INFO, "queued actions of \"%s\" to \"%s\"", + ablog(LOG_INFO, "queued actions of \"%s\" to \"%s\"", GetMacroName(macro.get()).c_str(), GetActionQueueName(_queue).c_str()); break; case Action::START_QUEUE: - vblog(LOG_INFO, "start queue \"%s\"", + ablog(LOG_INFO, "start queue \"%s\"", GetActionQueueName(_queue).c_str()); break; case Action::STOP_QUEUE: - vblog(LOG_INFO, "stop queue \"%s\"", + ablog(LOG_INFO, "stop queue \"%s\"", GetActionQueueName(_queue).c_str()); break; case Action::CLEAR_QUEUE: - vblog(LOG_INFO, "cleared queue \"%s\"", + ablog(LOG_INFO, "cleared queue \"%s\"", GetActionQueueName(_queue).c_str()); break; default: @@ -114,6 +114,16 @@ std::string MacroActionQueue::GetShortDesc() const return GetActionQueueName(_queue); } +std::shared_ptr MacroActionQueue::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionQueue::Copy() const +{ + return std::make_shared(*this); +} + static inline void populateActionSelection(QComboBox *list) { for (const auto &[_, name] : actionTypes) { diff --git a/lib/macro/macro-action-queue.hpp b/lib/macro/macro-action-queue.hpp index 3d60ee5d5..5932c45c1 100644 --- a/lib/macro/macro-action-queue.hpp +++ b/lib/macro/macro-action-queue.hpp @@ -16,10 +16,8 @@ class MacroActionQueue : public MacroRefAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; enum class Action { ADD_TO_QUEUE, diff --git a/lib/macro/macro-action-variable.cpp b/lib/macro/macro-action-variable.cpp index f3594a027..ffbfea88d 100644 --- a/lib/macro/macro-action-variable.cpp +++ b/lib/macro/macro-action-variable.cpp @@ -198,7 +198,8 @@ void MacroActionVariable::SetToSceneItemName(Variable *var) struct AskForInputParams { AskForInputParams(const QString &prompt_, const QString &placeholder_) - : prompt(prompt_), placeholder(placeholder_){}; + : prompt(prompt_), + placeholder(placeholder_){}; QString prompt; QString placeholder; std::optional result; @@ -422,6 +423,16 @@ std::string MacroActionVariable::GetShortDesc() const return GetWeakVariableName(_variable); } +std::shared_ptr MacroActionVariable::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionVariable::Copy() const +{ + return std::make_shared(*this); +} + void MacroActionVariable::SetSegmentIndexValue(int value) { DecrementCurrentSegmentVariableRef(); @@ -485,6 +496,19 @@ int MacroActionVariable::GetSegmentIndexValue() const return -1; } +void MacroActionVariable::ResolveVariablesToFixedValues() +{ + _strValue.ResolveVariables(); + _findStr.ResolveVariables(); + _replaceStr.ResolveVariables(); + _mathExpression.ResolveVariables(); + _inputPrompt.ResolveVariables(); + _inputPlaceholder.ResolveVariables(); + _envVariableName.ResolveVariables(); + _scene.ResolveVariables(); + _sceneItemIndex.ResolveVariables(); +} + void MacroActionVariable::DecrementCurrentSegmentVariableRef() { auto segment = _macroSegment.lock(); diff --git a/lib/macro/macro-action-variable.hpp b/lib/macro/macro-action-variable.hpp index 7eeb2b1b9..e9b809d7b 100644 --- a/lib/macro/macro-action-variable.hpp +++ b/lib/macro/macro-action-variable.hpp @@ -20,12 +20,11 @@ class MacroActionVariable : public MacroAction { bool PostLoad() override; std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; void SetSegmentIndexValue(int); int GetSegmentIndexValue() const; + void ResolveVariablesToFixedValues(); enum class Type { SET_FIXED_VALUE, diff --git a/lib/macro/macro-action.cpp b/lib/macro/macro-action.cpp index 95c5f24a9..ce40ffff7 100644 --- a/lib/macro/macro-action.cpp +++ b/lib/macro/macro-action.cpp @@ -25,7 +25,7 @@ bool MacroAction::Load(obs_data_t *obj) void MacroAction::LogAction() const { - vblog(LOG_INFO, "performed action %s", GetId().c_str()); + ablog(LOG_INFO, "performed action %s", GetId().c_str()); } void MacroAction::SetEnabled(bool value) @@ -38,6 +38,8 @@ bool MacroAction::Enabled() const return _enabled; } +void MacroAction::ResolveVariablesToFixedValues() {} + std::string_view MacroAction::GetDefaultID() { return "scene_switch"; diff --git a/lib/macro/macro-action.hpp b/lib/macro/macro-action.hpp index 73fed9c4c..81e8b05e7 100644 --- a/lib/macro/macro-action.hpp +++ b/lib/macro/macro-action.hpp @@ -8,10 +8,17 @@ class EXPORT MacroAction : public MacroSegment { public: MacroAction(Macro *m, bool supportsVariableValue = false); virtual ~MacroAction() = default; + virtual std::shared_ptr Copy() const = 0; + virtual bool PerformAction() = 0; + virtual void LogAction() const; + virtual bool Save(obs_data_t *obj) const = 0; virtual bool Load(obs_data_t *obj) = 0; - virtual void LogAction() const; + + // Used to resolve variables before actions are added to action queues + virtual void ResolveVariablesToFixedValues(); + void SetEnabled(bool); bool Enabled() const; diff --git a/lib/macro/macro-condition-edit.cpp b/lib/macro/macro-condition-edit.cpp index 30541045f..7f25d4903 100644 --- a/lib/macro/macro-condition-edit.cpp +++ b/lib/macro/macro-condition-edit.cpp @@ -3,6 +3,7 @@ #include "macro-properties.hpp" #include "macro.hpp" #include "path-helpers.hpp" +#include "plugin-state-helpers.hpp" #include "section.hpp" #include "ui-helpers.hpp" #include "utility.hpp" @@ -254,6 +255,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text) (*_entryData)->SetIndex(idx); (*_entryData)->SetLogicType(logic); (*_entryData)->PostLoad(); + RunPostLoadSteps(); } auto widget = MacroConditionFactory::CreateWidget(id, this, *_entryData); @@ -325,6 +327,7 @@ void AdvSceneSwitcher::AddMacroCondition(int idx) obs_data_release(data); } macro->Conditions().at(idx)->PostLoad(); + RunPostLoadSteps(); (*cond)->SetLogicType(logic); macro->UpdateConditionIndices(); ui->conditionsList->Insert( diff --git a/lib/macro/macro-segment.cpp b/lib/macro/macro-segment.cpp index bd612c615..8a6602592 100644 --- a/lib/macro/macro-segment.cpp +++ b/lib/macro/macro-segment.cpp @@ -4,7 +4,6 @@ #include "section.hpp" #include "ui-helpers.hpp" -#include #include #include #include diff --git a/lib/macro/macro-segment.hpp b/lib/macro/macro-segment.hpp index a3ba79acb..d54a877f3 100644 --- a/lib/macro/macro-segment.hpp +++ b/lib/macro/macro-segment.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include class QLabel; @@ -116,8 +116,8 @@ protected slots: void ShowDropLine(DropLineState); - // The reason for using two separate frame widget each with their own - // stylesheet and changing their visibility vs. using a single frame + // The reason for using two separate frame widgets, each with their own + // stylesheet, and changing their visibility vs. using a single frame // and changing the stylesheet at runtime is that the operation of // adjusting the stylesheet is very expensive and can take multiple // hundred milliseconds per widget. diff --git a/lib/macro/macro.hpp b/lib/macro/macro.hpp index 0fdaff634..7187e70ea 100644 --- a/lib/macro/macro.hpp +++ b/lib/macro/macro.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include namespace advss { diff --git a/lib/switcher-data.hpp b/lib/switcher-data.hpp index a83c2bf42..0d2e98a7a 100644 --- a/lib/switcher-data.hpp +++ b/lib/switcher-data.hpp @@ -141,7 +141,9 @@ class SwitcherData { bool showSystemTrayNotifications = false; bool transitionOverrideOverride = false; bool adjustActiveTransitionType = true; - bool verbose = false; + + enum class LogLevel { DEFAULT, PRINT_ACTION, VERBOSE }; + LogLevel logLevel = LogLevel::DEFAULT; /* --- End of General tab section --- */ diff --git a/lib/utils/action-queue.cpp b/lib/utils/action-queue.cpp index 2ed761adb..331a4b89d 100644 --- a/lib/utils/action-queue.cpp +++ b/lib/utils/action-queue.cpp @@ -33,6 +33,7 @@ void ActionQueue::Save(obs_data_t *obj) const { obs_data_set_string(obj, "name", _name.c_str()); obs_data_set_bool(obj, "runOnStartup", _runOnStartup); + obs_data_set_bool(obj, "resolveVariablesOnAdd", _resolveVariablesOnAdd); } void ActionQueue::Load(obs_data_t *obj) @@ -40,6 +41,8 @@ void ActionQueue::Load(obs_data_t *obj) std::lock_guard lock(_mutex); _name = obs_data_get_string(obj, "name"); _runOnStartup = obs_data_get_bool(obj, "runOnStartup"); + _resolveVariablesOnAdd = + obs_data_get_bool(obj, "resolveVariablesOnAdd"); if (_runOnStartup) { Start(); @@ -80,10 +83,21 @@ void ActionQueue::Clear() _actions.clear(); } -void ActionQueue::Add(const std::shared_ptr &actions) +void ActionQueue::Add(const std::shared_ptr &action) { std::lock_guard lock(_mutex); - _actions.emplace_back(actions); + if (_resolveVariablesOnAdd) { + auto copy = action->Copy(); + copy->GetMacro(); + OBSDataAutoRelease data = obs_data_create(); + action->Save(data); + copy->Load(data); + copy->PostLoad(); + copy->ResolveVariablesToFixedValues(); + _actions.emplace_back(copy); + } else { + _actions.emplace_back(action); + } _cv.notify_all(); } @@ -120,8 +134,11 @@ void ActionQueue::RunActions() continue; } - vblog(LOG_INFO, "Performing action '%s' in queue '%s'", - action->GetId().c_str(), _name.c_str()); + if (ActionLoggingEnabled()) { + blog(LOG_INFO, "Performing action '%s' in queue '%s'", + action->GetId().c_str(), _name.c_str()); + action->LogAction(); + } action->PerformAction(); } } @@ -139,6 +156,7 @@ ActionQueueSettingsDialog::ActionQueueSettingsDialog(QWidget *parent, _clear(new QPushButton( obs_module_text("AdvSceneSwitcher.actionQueues.clear"))), _runOnStartup(new QCheckBox()), + _resolveVariablesOnAdd(new QCheckBox()), _queue(settings) { QWidget::connect(_startStopToggle, SIGNAL(clicked()), this, @@ -146,6 +164,7 @@ ActionQueueSettingsDialog::ActionQueueSettingsDialog(QWidget *parent, QWidget::connect(_clear, SIGNAL(clicked()), this, SLOT(ClearClicked())); _runOnStartup->setChecked(settings._runOnStartup); + _resolveVariablesOnAdd->setChecked(settings._resolveVariablesOnAdd); UpdateLabels(); auto layout = new QGridLayout(); @@ -167,6 +186,14 @@ ActionQueueSettingsDialog::ActionQueueSettingsDialog(QWidget *parent, _runOnStartup->setToolTip( obs_module_text("AdvSceneSwitcher.actionQueues.runOnStartup")); ++row; + layout->addWidget( + new QLabel(obs_module_text( + "AdvSceneSwitcher.actionQueues.resolveVariablesOnAdd")), + row, 0); + layout->addWidget(_resolveVariablesOnAdd, row, 1); + _resolveVariablesOnAdd->setToolTip(obs_module_text( + "AdvSceneSwitcher.actionQueues.resolveVariablesOnAdd")); + ++row; layout->addWidget(_queueRunStatus, row, 0); layout->addWidget(_startStopToggle, row, 1); ++row; @@ -194,6 +221,8 @@ bool ActionQueueSettingsDialog::AskForSettings(QWidget *parent, settings._name = dialog._name->text().toStdString(); settings._runOnStartup = dialog._runOnStartup->isChecked(); + settings._resolveVariablesOnAdd = + dialog._resolveVariablesOnAdd->isChecked(); return true; } diff --git a/lib/utils/action-queue.hpp b/lib/utils/action-queue.hpp index fa27c45b7..2dd7f403b 100644 --- a/lib/utils/action-queue.hpp +++ b/lib/utils/action-queue.hpp @@ -38,6 +38,7 @@ class ActionQueue : public Item { void RunActions(); bool _runOnStartup = true; + bool _resolveVariablesOnAdd = true; std::atomic_bool _stop = {false}; std::mutex _mutex; std::condition_variable _cv; @@ -66,6 +67,7 @@ private slots: QLabel *_queueSize; QPushButton *_clear; QCheckBox *_runOnStartup; + QCheckBox *_resolveVariablesOnAdd; ActionQueue &_queue; }; diff --git a/lib/utils/curl-helper.cpp b/lib/utils/curl-helper.cpp index 5ffed82ae..2ade8aa22 100644 --- a/lib/utils/curl-helper.cpp +++ b/lib/utils/curl-helper.cpp @@ -1,9 +1,9 @@ #include "curl-helper.hpp" +#include "log-helper.hpp" #include #include #include -#include namespace advss { diff --git a/lib/utils/duration.cpp b/lib/utils/duration.cpp index eb1851dc1..11fde9d07 100644 --- a/lib/utils/duration.cpp +++ b/lib/utils/duration.cpp @@ -165,4 +165,9 @@ void Duration::SetUnit(Unit u) _value = _value * (prevMultiplier / newMultiplier); } +void Duration::ResolveVariables() +{ + _value.ResolveVariables(); +} + } // namespace advss diff --git a/lib/utils/duration.hpp b/lib/utils/duration.hpp index 3a8ab0900..b4263f64e 100644 --- a/lib/utils/duration.hpp +++ b/lib/utils/duration.hpp @@ -34,8 +34,10 @@ class Duration { // Only use this function if you intend to convert old settings formats EXPORT void SetUnit(Unit u); + EXPORT void ResolveVariables(); + private: - NumberVariable _value = 0.; + DoubleVariable _value = 0.; Unit _unit = Unit::SECONDS; std::chrono::high_resolution_clock::time_point _startTime; diff --git a/lib/utils/log-helper.cpp b/lib/utils/log-helper.cpp index 0acf7e907..e014a07bc 100644 --- a/lib/utils/log-helper.cpp +++ b/lib/utils/log-helper.cpp @@ -5,7 +5,16 @@ namespace advss { bool VerboseLoggingEnabled() { - return GetSwitcher() && GetSwitcher()->verbose; + return GetSwitcher() && + GetSwitcher()->logLevel == SwitcherData::LogLevel::VERBOSE; +} + +bool ActionLoggingEnabled() +{ + return GetSwitcher() && + (GetSwitcher()->logLevel == + SwitcherData::LogLevel::PRINT_ACTION || + GetSwitcher()->logLevel == SwitcherData::LogLevel::VERBOSE); } } // namespace advss diff --git a/lib/utils/log-helper.hpp b/lib/utils/log-helper.hpp index 473b79210..4bb290d2f 100644 --- a/lib/utils/log-helper.hpp +++ b/lib/utils/log-helper.hpp @@ -3,14 +3,26 @@ namespace advss { +// Print log with "[adv-ss] " prefix #define blog(level, msg, ...) blog(level, "[adv-ss] " msg, ##__VA_ARGS__) +// Print log with "[adv-ss] " if log level is set to "verbose" #define vblog(level, msg, ...) \ do { \ if (VerboseLoggingEnabled()) { \ blog(level, msg, ##__VA_ARGS__); \ } \ } while (0) +// Print log with "[adv-ss] " if log level is set to "action" or "verbose" +#define ablog(level, msg, ...) \ + do { \ + if (ActionLoggingEnabled()) { \ + blog(level, msg, ##__VA_ARGS__); \ + } \ + } while (0) +// Returns true if log level is set to "verbose" EXPORT bool VerboseLoggingEnabled(); +// Returns true if log level is set to "action" or "verbose" +EXPORT bool ActionLoggingEnabled(); } // namespace advss diff --git a/lib/utils/scene-selection.cpp b/lib/utils/scene-selection.cpp index eb4ddb58e..16b7b0518 100644 --- a/lib/utils/scene-selection.cpp +++ b/lib/utils/scene-selection.cpp @@ -181,6 +181,12 @@ std::string SceneSelection::ToString(bool resolve) const return ""; } +void SceneSelection::ResolveVariables() +{ + _scene = GetScene(); + _type = Type::SCENE; +} + SceneSelection SceneSelectionWidget::CurrentSelection() { SceneSelection s; diff --git a/lib/utils/scene-selection.hpp b/lib/utils/scene-selection.hpp index 6fa6201a8..fe581265d 100644 --- a/lib/utils/scene-selection.hpp +++ b/lib/utils/scene-selection.hpp @@ -26,6 +26,7 @@ class SceneSelection { EXPORT Type GetType() const { return _type; } EXPORT OBSWeakSource GetScene(bool advance = true) const; EXPORT std::string ToString(bool resolve = false) const; + EXPORT void ResolveVariables(); private: OBSWeakSource _scene; diff --git a/lib/utils/selection-helpers.hpp b/lib/utils/selection-helpers.hpp index c0c411ec5..db9d69880 100644 --- a/lib/utils/selection-helpers.hpp +++ b/lib/utils/selection-helpers.hpp @@ -2,7 +2,6 @@ #include "export-symbol-helper.hpp" #include -#include #include #include #include diff --git a/lib/utils/source-selection.cpp b/lib/utils/source-selection.cpp index 4ea4a1931..15feeafc9 100644 --- a/lib/utils/source-selection.cpp +++ b/lib/utils/source-selection.cpp @@ -88,6 +88,11 @@ void SourceSelection::SetSource(OBSWeakSource source) _source = source; } +void SourceSelection::ResolveVariables() +{ + SetSource(GetSource()); +} + std::string SourceSelection::ToString(bool resolve) const { switch (_type) { diff --git a/lib/utils/source-selection.hpp b/lib/utils/source-selection.hpp index f5a7579ab..9fc50b1f2 100644 --- a/lib/utils/source-selection.hpp +++ b/lib/utils/source-selection.hpp @@ -19,6 +19,7 @@ class SourceSelection { EXPORT Type GetType() const { return _type; } EXPORT OBSWeakSource GetSource() const; EXPORT void SetSource(OBSWeakSource); + EXPORT void ResolveVariables(); EXPORT std::string ToString(bool resolve = false) const; EXPORT bool operator==(const SourceSelection &) const; diff --git a/lib/utils/temp-variable.hpp b/lib/utils/temp-variable.hpp index cebed162d..b2758e15b 100644 --- a/lib/utils/temp-variable.hpp +++ b/lib/utils/temp-variable.hpp @@ -1,7 +1,7 @@ #pragma once #include "filter-combo-box.hpp" -#include +#include #include #include #include diff --git a/lib/utils/ui-helpers.cpp b/lib/utils/ui-helpers.cpp index 05e512b2c..dd5f6ed2a 100644 --- a/lib/utils/ui-helpers.cpp +++ b/lib/utils/ui-helpers.cpp @@ -3,7 +3,6 @@ #include "obs-module-helper.hpp" #include -#include #include #include #include diff --git a/lib/variables/variable-number.hpp b/lib/variables/variable-number.hpp index 8c0011e02..3edd81dbc 100644 --- a/lib/variables/variable-number.hpp +++ b/lib/variables/variable-number.hpp @@ -1,8 +1,6 @@ #pragma once #include "variable.hpp" -#include - namespace advss { template class NumberVariable { @@ -24,6 +22,7 @@ template class NumberVariable { Type GetType() const { return _type; } bool IsFixedType() const { return _type == Type::FIXED_VALUE; } std::weak_ptr GetVariable() const { return _variable; } + void ResolveVariables(); private: Type _type = Type::FIXED_VALUE; diff --git a/lib/variables/variable-number.tpp b/lib/variables/variable-number.tpp index 9608546db..db67d144a 100644 --- a/lib/variables/variable-number.tpp +++ b/lib/variables/variable-number.tpp @@ -93,3 +93,9 @@ template NumberVariable::operator T() const { return GetValue(); } + +template void NumberVariable::ResolveVariables() +{ + _value = GetValue(); + _type = Type::FIXED_VALUE; +} diff --git a/lib/variables/variable-string.cpp b/lib/variables/variable-string.cpp index 3d6c11863..386088d64 100644 --- a/lib/variables/variable-string.cpp +++ b/lib/variables/variable-string.cpp @@ -50,6 +50,12 @@ void StringVariable::Save(obs_data_t *obj, const char *name) const obs_data_set_string(obj, name, _value.c_str()); } +void StringVariable::ResolveVariables() +{ + Resolve(); + _value = _resolvedValue; +} + const char *StringVariable::c_str() { Resolve(); diff --git a/lib/variables/variable-string.hpp b/lib/variables/variable-string.hpp index df73e31cf..53acf2ce7 100644 --- a/lib/variables/variable-string.hpp +++ b/lib/variables/variable-string.hpp @@ -2,7 +2,7 @@ #include "variable.hpp" #include -#include +#include namespace advss { @@ -27,6 +27,8 @@ class StringVariable { EXPORT void Load(obs_data_t *obj, const char *name); EXPORT void Save(obs_data_t *obj, const char *name) const; + EXPORT void ResolveVariables(); + private: void Resolve() const; diff --git a/lib/variables/variable.cpp b/lib/variables/variable.cpp index 3773be6b3..edcfc3303 100644 --- a/lib/variables/variable.cpp +++ b/lib/variables/variable.cpp @@ -267,6 +267,7 @@ bool VariableSettingsDialog::AskForSettings(QWidget *parent, Variable &settings) dialog._defaultValue->toPlainText().toStdString(); settings._saveAction = static_cast(dialog._save->currentIndex()); + lastVariableChange = std::chrono::high_resolution_clock::now(); return true; } @@ -274,7 +275,6 @@ static bool AskForSettingsWrapper(QWidget *parent, Item &settings) { Variable &VariableSettings = dynamic_cast(settings); if (VariableSettingsDialog::AskForSettings(parent, VariableSettings)) { - lastVariableChange = std::chrono::high_resolution_clock::now(); return true; } return false; diff --git a/plugins/base/CMakeLists.txt b/plugins/base/CMakeLists.txt index ba2f4ee98..9f2b8b7b0 100644 --- a/plugins/base/CMakeLists.txt +++ b/plugins/base/CMakeLists.txt @@ -17,6 +17,8 @@ target_sources( macro-action-hotkey.hpp macro-action-http.cpp macro-action-http.hpp + macro-action-log.cpp + macro-action-log.hpp macro-action-media.cpp macro-action-media.hpp macro-action-osc.cpp diff --git a/plugins/base/macro-action-audio.cpp b/plugins/base/macro-action-audio.cpp index 6108b34eb..274937ccc 100644 --- a/plugins/base/macro-action-audio.cpp +++ b/plugins/base/macro-action-audio.cpp @@ -244,7 +244,7 @@ void MacroActionAudio::LogAction() const auto it = actionTypes.find(_action); if (it != actionTypes.end()) { auto &[_, action] = *it; - vblog(LOG_INFO, + ablog(LOG_INFO, "performed action \"%s\" for source \"%s\" with volume %f with fade %d %f", action.c_str(), _audioSource.ToString(true).c_str(), GetVolume(), _fade, _duration.Seconds()); @@ -328,6 +328,27 @@ std::string MacroActionAudio::GetShortDesc() const return _audioSource.ToString(); } +std::shared_ptr MacroActionAudio::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionAudio::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionAudio::ResolveVariablesToFixedValues() +{ + _audioSource.ResolveVariables(); + _syncOffset.ResolveVariables(); + _balance.ResolveVariables(); + _volume.ResolveVariables(); + _volumeDB.ResolveVariables(); + _duration.ResolveVariables(); + _rate.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (const auto &[action, name] : actionTypes) { diff --git a/plugins/base/macro-action-audio.hpp b/plugins/base/macro-action-audio.hpp index 3f55a65fe..4ae74dca1 100644 --- a/plugins/base/macro-action-audio.hpp +++ b/plugins/base/macro-action-audio.hpp @@ -20,10 +20,9 @@ class MacroActionAudio : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); SourceSelection _audioSource; @@ -44,15 +43,15 @@ class MacroActionAudio : public MacroAction { Action _action = Action::MUTE; FadeType _fadeType = FadeType::DURATION; - NumberVariable _syncOffset = 0; + IntVariable _syncOffset = 0; obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE; - NumberVariable _balance = 0.5; + DoubleVariable _balance = 0.5; bool _useDb = false; - NumberVariable _volume = 0; - NumberVariable _volumeDB = 0.0; + IntVariable _volume = 0; + DoubleVariable _volumeDB = 0.0; bool _fade = false; Duration _duration; - NumberVariable _rate = 100.; + DoubleVariable _rate = 100.; bool _wait = false; bool _abortActiveFade = false; diff --git a/plugins/base/macro-action-clipboard.cpp b/plugins/base/macro-action-clipboard.cpp index f5720f96c..606f2423f 100644 --- a/plugins/base/macro-action-clipboard.cpp +++ b/plugins/base/macro-action-clipboard.cpp @@ -1,6 +1,7 @@ #include "macro-action-clipboard.hpp" #include "curl-helper.hpp" +#include #include #include #include @@ -92,6 +93,16 @@ static void copyImageFromUrl(void *param) setMimeTypeParams(params, clipboard); } +std::shared_ptr MacroActionClipboard::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionClipboard::Copy() const +{ + return std::make_shared(*this); +} + bool MacroActionClipboard::PerformAction() { switch (_action) { @@ -158,6 +169,12 @@ bool MacroActionClipboard::Load(obs_data_t *obj) return true; } +void MacroActionClipboard::ResolveVariablesToFixedValues() +{ + _text.ResolveVariables(); + _url.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (const auto &[action, name] : actionTypes) { diff --git a/plugins/base/macro-action-clipboard.hpp b/plugins/base/macro-action-clipboard.hpp index c7f22f5d7..1ff53b74b 100644 --- a/plugins/base/macro-action-clipboard.hpp +++ b/plugins/base/macro-action-clipboard.hpp @@ -22,16 +22,16 @@ struct ClipboardImageQueueParams : ClipboardQueueParams { class MacroActionClipboard : public MacroAction { public: MacroActionClipboard(Macro *m) : MacroAction(m) {} - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; std::string GetId() const { return id; }; bool PerformAction(); bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); + void ResolveVariablesToFixedValues(); + enum class Action { COPY_TEXT, COPY_IMAGE, diff --git a/plugins/base/macro-action-file.cpp b/plugins/base/macro-action-file.cpp index b566b7d7f..d8e0b8159 100644 --- a/plugins/base/macro-action-file.cpp +++ b/plugins/base/macro-action-file.cpp @@ -14,9 +14,11 @@ bool MacroActionFile::_registered = MacroActionFactory::Register( {MacroActionFile::Create, MacroActionFileEdit::Create, "AdvSceneSwitcher.action.file"}); -const static std::map actionTypes = { - {FileAction::WRITE, "AdvSceneSwitcher.action.file.type.write"}, - {FileAction::APPEND, "AdvSceneSwitcher.action.file.type.append"}, +static const std::map actionTypes = { + {MacroActionFile::Action::WRITE, + "AdvSceneSwitcher.action.file.type.write"}, + {MacroActionFile::Action::APPEND, + "AdvSceneSwitcher.action.file.type.append"}, }; bool MacroActionFile::PerformAction() @@ -25,10 +27,10 @@ bool MacroActionFile::PerformAction() QFile file(path); bool open = false; switch (_action) { - case FileAction::WRITE: + case Action::WRITE: open = file.open(QIODevice::WriteOnly); break; - case FileAction::APPEND: + case Action::APPEND: open = file.open(QIODevice::WriteOnly | QIODevice::Append); break; default: @@ -45,7 +47,7 @@ void MacroActionFile::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, "performed action \"%s\" for file \"%s\"", + ablog(LOG_INFO, "performed action \"%s\" for file \"%s\"", it->second.c_str(), _file.c_str()); } else { blog(LOG_WARNING, "ignored unknown file action %d", @@ -67,7 +69,7 @@ bool MacroActionFile::Load(obs_data_t *obj) MacroAction::Load(obj); _file.Load(obj, "file"); _text.Load(obj, "text"); - _action = static_cast(obs_data_get_int(obj, "action")); + _action = static_cast(obs_data_get_int(obj, "action")); return true; } @@ -76,21 +78,36 @@ std::string MacroActionFile::GetShortDesc() const return _file.UnresolvedValue(); } +std::shared_ptr MacroActionFile::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionFile::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionFile::ResolveVariablesToFixedValues() +{ + _file.ResolveVariables(); + _text.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { - for (auto entry : actionTypes) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : actionTypes) { + list->addItem(obs_module_text(name.c_str())); } } MacroActionFileEdit::MacroActionFileEdit( QWidget *parent, std::shared_ptr entryData) - : QWidget(parent) + : QWidget(parent), + _filePath(new FileSelection(FileSelection::Type::WRITE)), + _text(new VariableTextEdit(this)), + _actions(new QComboBox()) { - _filePath = new FileSelection(FileSelection::Type::WRITE); - _text = new VariableTextEdit(this); - _actions = new QComboBox(); - populateActionSelection(_actions); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, @@ -166,7 +183,7 @@ void MacroActionFileEdit::ActionChanged(int value) } auto lock = LockContext(); - _entryData->_action = static_cast(value); + _entryData->_action = static_cast(value); } } // namespace advss diff --git a/plugins/base/macro-action-file.hpp b/plugins/base/macro-action-file.hpp index 760096e92..700fd31c5 100644 --- a/plugins/base/macro-action-file.hpp +++ b/plugins/base/macro-action-file.hpp @@ -7,11 +7,6 @@ namespace advss { -enum class FileAction { - WRITE, - APPEND, -}; - class MacroActionFile : public MacroAction { public: MacroActionFile(Macro *m) : MacroAction(m) {} @@ -21,14 +16,18 @@ class MacroActionFile : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); StringVariable _file = obs_module_text("AdvSceneSwitcher.enterPath"); StringVariable _text = obs_module_text("AdvSceneSwitcher.enterText"); - FileAction _action = FileAction::WRITE; + + enum class Action { + WRITE, + APPEND, + }; + Action _action = Action::WRITE; private: static bool _registered; @@ -58,13 +57,12 @@ private slots: signals: void HeaderInfoChanged(const QString &); -protected: +private: FileSelection *_filePath; VariableTextEdit *_text; QComboBox *_actions; - std::shared_ptr _entryData; -private: + std::shared_ptr _entryData; bool _loading = true; }; diff --git a/plugins/base/macro-action-filter.cpp b/plugins/base/macro-action-filter.cpp index a7b8bc5f6..2398086f7 100644 --- a/plugins/base/macro-action-filter.cpp +++ b/plugins/base/macro-action-filter.cpp @@ -94,7 +94,7 @@ void MacroActionFilter::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, + ablog(LOG_INFO, "performed action \"%s\" for filter \"%s\" on source \"%s\"", it->second.c_str(), _filter.ToString().c_str(), _source.ToString(true).c_str()); @@ -158,6 +158,24 @@ std::string MacroActionFilter::GetShortDesc() const return ""; } +std::shared_ptr MacroActionFilter::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionFilter::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionFilter::ResolveVariablesToFixedValues() +{ + _source.ResolveVariables(); + _filter.ResolveVariables(); + _settingsString.ResolveVariables(); + _manualSettingValue.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (auto entry : actionTypes) { diff --git a/plugins/base/macro-action-filter.hpp b/plugins/base/macro-action-filter.hpp index fcfa420ae..3c3fae4fe 100644 --- a/plugins/base/macro-action-filter.hpp +++ b/plugins/base/macro-action-filter.hpp @@ -20,10 +20,9 @@ class MacroActionFilter : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Action { ENABLE, diff --git a/plugins/base/macro-action-hotkey.cpp b/plugins/base/macro-action-hotkey.cpp index 02cf83f8b..0baebc7dc 100644 --- a/plugins/base/macro-action-hotkey.cpp +++ b/plugins/base/macro-action-hotkey.cpp @@ -371,7 +371,7 @@ bool MacroActionHotkey::PerformAction() void MacroActionHotkey::LogAction() const { - vblog(LOG_INFO, "sent hotkey type %d", static_cast(_action)); + ablog(LOG_INFO, "sent hotkey type %d", static_cast(_action)); } bool MacroActionHotkey::Save(obs_data_t *obj) const @@ -425,6 +425,16 @@ bool MacroActionHotkey::Load(obs_data_t *obj) return true; } +std::shared_ptr MacroActionHotkey::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionHotkey::Copy() const +{ + return std::make_shared(*this); +} + static inline void populateKeySelection(QComboBox *list) { list->addItems({"No key", diff --git a/plugins/base/macro-action-hotkey.hpp b/plugins/base/macro-action-hotkey.hpp index fd1c0a319..13df865c1 100644 --- a/plugins/base/macro-action-hotkey.hpp +++ b/plugins/base/macro-action-hotkey.hpp @@ -18,10 +18,8 @@ class MacroActionHotkey : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; enum class Action { OBS_HOTKEY, diff --git a/plugins/base/macro-action-http.cpp b/plugins/base/macro-action-http.cpp index 73ff3c6ce..8e63ab974 100644 --- a/plugins/base/macro-action-http.cpp +++ b/plugins/base/macro-action-http.cpp @@ -95,7 +95,7 @@ void MacroActionHttp::LogAction() const { auto it = methods.find(_method); if (it != methods.end()) { - vblog(LOG_INFO, + ablog(LOG_INFO, "sent http request \"%s\" to \"%s\" with data \"%s\"", it->second.c_str(), _url.c_str(), _data.c_str()); } else { @@ -133,6 +133,24 @@ std::string MacroActionHttp::GetShortDesc() const return _url.UnresolvedValue(); } +std::shared_ptr MacroActionHttp::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionHttp::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionHttp::ResolveVariablesToFixedValues() +{ + _url.ResolveVariables(); + _data.ResolveVariables(); + _headers.ResolveVariables(); + _timeout.ResolveVariables(); +} + static inline void populateMethodSelection(QComboBox *list) { for (auto entry : methods) { diff --git a/plugins/base/macro-action-http.hpp b/plugins/base/macro-action-http.hpp index eab70abb5..eb74f8456 100644 --- a/plugins/base/macro-action-http.hpp +++ b/plugins/base/macro-action-http.hpp @@ -20,10 +20,9 @@ class MacroActionHttp : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Method { GET = 0, diff --git a/plugins/base/macro-action-log.cpp b/plugins/base/macro-action-log.cpp new file mode 100644 index 000000000..00ba3a5ce --- /dev/null +++ b/plugins/base/macro-action-log.cpp @@ -0,0 +1,89 @@ +#include "macro-action-log.hpp" +#include "layout-helpers.hpp" + +namespace advss { + +const std::string MacroActionLog::id = "log"; + +bool MacroActionLog::_registered = MacroActionFactory::Register( + MacroActionLog::id, {MacroActionLog::Create, MacroActionLogEdit::Create, + "AdvSceneSwitcher.action.log"}); + +bool MacroActionLog::PerformAction() +{ + blog(LOG_INFO, "%s", std::string(_logMessage).c_str()); + return true; +} + +bool MacroActionLog::Save(obs_data_t *obj) const +{ + MacroAction::Save(obj); + _logMessage.Save(obj, "logMessage"); + return true; +} + +bool MacroActionLog::Load(obs_data_t *obj) +{ + MacroAction::Load(obj); + _logMessage.Load(obj, "logMessage"); + return true; +} + +std::shared_ptr MacroActionLog::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionLog::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionLog::ResolveVariablesToFixedValues() +{ + _logMessage.ResolveVariables(); +} + +MacroActionLogEdit::MacroActionLogEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent), + _logMessage(new VariableTextEdit(this, 5, 1, 1)) +{ + QWidget::connect(_logMessage, SIGNAL(textChanged()), this, + SLOT(LogMessageChanged())); + + auto layout = new QHBoxLayout(); + PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.log.entry"), + layout, {{"{{logMessage}}", _logMessage}}, false); + setLayout(layout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroActionLogEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _logMessage->setPlainText(_entryData->_logMessage); + adjustSize(); + updateGeometry(); +} + +void MacroActionLogEdit::LogMessageChanged() +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_logMessage = _logMessage->toPlainText().toStdString(); + + adjustSize(); + updateGeometry(); +} + +} // namespace advss diff --git a/plugins/base/macro-action-log.hpp b/plugins/base/macro-action-log.hpp new file mode 100644 index 000000000..7e57a0b0a --- /dev/null +++ b/plugins/base/macro-action-log.hpp @@ -0,0 +1,50 @@ +#pragma once +#include "macro-action-edit.hpp" +#include "variable-text-edit.hpp" + +namespace advss { + +class MacroActionLog : public MacroAction { +public: + MacroActionLog(Macro *m) : MacroAction(m) {} + bool PerformAction(); + bool Save(obs_data_t *obj) const; + bool Load(obs_data_t *obj); + std::string GetId() const { return id; }; + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); + + StringVariable _logMessage = + obs_module_text("AdvSceneSwitcher.action.log.placeholder"); + +private: + static bool _registered; + static const std::string id; +}; + +class MacroActionLogEdit : public QWidget { + Q_OBJECT + +public: + MacroActionLogEdit(QWidget *parent, + std::shared_ptr entryData = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr action) + { + return new MacroActionLogEdit( + parent, + std::dynamic_pointer_cast(action)); + } + +private slots: + void LogMessageChanged(); + +private: + VariableTextEdit *_logMessage; + std::shared_ptr _entryData; + bool _loading = true; +}; + +} // namespace advss diff --git a/plugins/base/macro-action-media.cpp b/plugins/base/macro-action-media.cpp index e4e3e28c9..52dd91bcf 100644 --- a/plugins/base/macro-action-media.cpp +++ b/plugins/base/macro-action-media.cpp @@ -38,6 +38,16 @@ static const std::map "AdvSceneSwitcher.action.media.selectionType.sceneItem"}, }; +std::shared_ptr MacroActionMedia::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionMedia::Copy() const +{ + return std::make_shared(*this); +} + std::string MacroActionMedia::GetShortDesc() const { if (_selection == SelectionType::SOURCE) { @@ -112,7 +122,7 @@ void MacroActionMedia::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, "performed action \"%s\" for source \"%s\"", + ablog(LOG_INFO, "performed action \"%s\" for source \"%s\"", it->second.c_str(), _selection == SelectionType::SOURCE ? _mediaSource.ToString(true).c_str() @@ -150,6 +160,15 @@ bool MacroActionMedia::Load(obs_data_t *obj) return true; } +void MacroActionMedia::ResolveVariablesToFixedValues() +{ + _seekDuration.ResolveVariables(); + _seekPercentage.ResolveVariables(); + _mediaSource.ResolveVariables(); + _sceneItem.ResolveVariables(); + _scene.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (const auto &[_, name] : actionTypes) { diff --git a/plugins/base/macro-action-media.hpp b/plugins/base/macro-action-media.hpp index f4bd5183f..0147c134c 100644 --- a/plugins/base/macro-action-media.hpp +++ b/plugins/base/macro-action-media.hpp @@ -11,10 +11,8 @@ namespace advss { class MacroActionMedia : public MacroAction { public: MacroActionMedia(Macro *m) : MacroAction(m) {} - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; std::string GetId() const { return id; }; std::string GetShortDesc() const; @@ -22,6 +20,7 @@ class MacroActionMedia : public MacroAction { void LogAction() const; bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); + void ResolveVariablesToFixedValues(); enum class Action { PLAY, diff --git a/plugins/base/macro-action-osc.cpp b/plugins/base/macro-action-osc.cpp index 552664eb8..43b8f90b2 100644 --- a/plugins/base/macro-action-osc.cpp +++ b/plugins/base/macro-action-osc.cpp @@ -1,5 +1,6 @@ #include "macro-action-osc.hpp" +#include #include #include @@ -146,7 +147,7 @@ bool MacroActionOSC::PerformAction() void MacroActionOSC::LogAction() const { - vblog(LOG_INFO, "sending OSC message '%s' to %s %s %d", + ablog(LOG_INFO, "sending OSC message '%s' to %s %s %d", _message.ToString().c_str(), _protocol == Protocol::UDP ? "UDP" : "TCP", _ip.c_str(), _port.GetValue()); @@ -172,6 +173,21 @@ bool MacroActionOSC::Load(obs_data_t *obj) return true; } +std::shared_ptr MacroActionOSC::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionOSC::Copy() const +{ + auto result = Create(GetMacro()); + OBSDataAutoRelease data = obs_data_create(); + Save(data); + result->Load(data); + result->PostLoad(); + return result; +} + void MacroActionOSC::SetProtocol(Protocol p) { _protocol = p; @@ -190,6 +206,13 @@ void MacroActionOSC::SetPortNr(IntVariable port) _reconnect = true; } +void MacroActionOSC::ResolveVariablesToFixedValues() +{ + _ip.ResolveVariables(); + _port.ResolveVariables(); + _message.ResolveVariables(); +} + static void populateProtocolSelection(QComboBox *list) { list->addItem("TCP"); diff --git a/plugins/base/macro-action-osc.hpp b/plugins/base/macro-action-osc.hpp index 6457cebeb..f8f1cb6a9 100644 --- a/plugins/base/macro-action-osc.hpp +++ b/plugins/base/macro-action-osc.hpp @@ -15,10 +15,8 @@ class MacroActionOSC : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; enum class Protocol { TCP, @@ -31,6 +29,7 @@ class MacroActionOSC : public MacroAction { StringVariable GetIP() const { return _ip; } void SetPortNr(IntVariable); IntVariable GetPortNr() { return _port; } + void ResolveVariablesToFixedValues(); OSCMessage _message; diff --git a/plugins/base/macro-action-plugin-state.cpp b/plugins/base/macro-action-plugin-state.cpp index 2eb8d2cfe..fc6d01078 100644 --- a/plugins/base/macro-action-plugin-state.cpp +++ b/plugins/base/macro-action-plugin-state.cpp @@ -174,14 +174,14 @@ void MacroActionPluginState::LogAction() const blog(LOG_INFO, "stop() called by macro"); break; case PluginStateAction::NO_MATCH_BEHAVIOUR: - vblog(LOG_INFO, "setting no match to %d", _value); + ablog(LOG_INFO, "setting no match to %d", _value); break; case PluginStateAction::IMPORT_SETTINGS: - vblog(LOG_INFO, "importing settings from %s", + ablog(LOG_INFO, "importing settings from %s", _settingsPath.c_str()); break; case PluginStateAction::TERMINATE: - vblog(LOG_INFO, "sending terminate signal to OBS in 10s"); + ablog(LOG_INFO, "sending terminate signal to OBS in 10s"); break; default: blog(LOG_WARNING, "ignored unknown pluginState action %d", @@ -212,10 +212,25 @@ bool MacroActionPluginState::Load(obs_data_t *obj) return true; } +std::shared_ptr MacroActionPluginState::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionPluginState::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionPluginState::ResolveVariablesToFixedValues() +{ + _settingsPath = std::string(_settingsPath); +} + static inline void populateActionSelection(QComboBox *list) { - for (auto entry : actionTypes) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : actionTypes) { + list->addItem(obs_module_text(name.c_str())); } } @@ -223,8 +238,8 @@ static inline void populateValueSelection(QComboBox *list, PluginStateAction action) { if (action == PluginStateAction::NO_MATCH_BEHAVIOUR) { - for (auto entry : noMatchValues) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : noMatchValues) { + list->addItem(obs_module_text(name.c_str())); } } } diff --git a/plugins/base/macro-action-plugin-state.hpp b/plugins/base/macro-action-plugin-state.hpp index d111a8e05..174370d11 100644 --- a/plugins/base/macro-action-plugin-state.hpp +++ b/plugins/base/macro-action-plugin-state.hpp @@ -2,6 +2,7 @@ #include "macro-action-edit.hpp" #include "file-selection.hpp" +#include #include #include @@ -22,10 +23,9 @@ class MacroActionPluginState : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); PluginStateAction _action = PluginStateAction::STOP; int _value = 0; diff --git a/plugins/base/macro-action-profile.cpp b/plugins/base/macro-action-profile.cpp index ea7d92ac5..1b4bc0e76 100644 --- a/plugins/base/macro-action-profile.cpp +++ b/plugins/base/macro-action-profile.cpp @@ -21,7 +21,7 @@ bool MacroActionProfile::PerformAction() void MacroActionProfile::LogAction() const { - vblog(LOG_INFO, "set profile type to \"%s\"", _profile.c_str()); + ablog(LOG_INFO, "set profile type to \"%s\"", _profile.c_str()); } bool MacroActionProfile::Save(obs_data_t *obj) const @@ -43,6 +43,16 @@ std::string MacroActionProfile::GetShortDesc() const return _profile; } +std::shared_ptr MacroActionProfile::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionProfile::Copy() const +{ + return std::make_shared(*this); +} + MacroActionProfileEdit::MacroActionProfileEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent) diff --git a/plugins/base/macro-action-profile.hpp b/plugins/base/macro-action-profile.hpp index a8ccad015..2e23eef74 100644 --- a/plugins/base/macro-action-profile.hpp +++ b/plugins/base/macro-action-profile.hpp @@ -14,10 +14,8 @@ class MacroActionProfile : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; std::string _profile; diff --git a/plugins/base/macro-action-projector.cpp b/plugins/base/macro-action-projector.cpp index 097eb11b5..64bf05717 100644 --- a/plugins/base/macro-action-projector.cpp +++ b/plugins/base/macro-action-projector.cpp @@ -75,7 +75,7 @@ void MacroActionProjector::LogAction() const { auto it = selectionTypes.find(_type); if (it != selectionTypes.end()) { - vblog(LOG_INFO, + ablog(LOG_INFO, "performed projector action \"%s\" with" "source \"%s\"," "scene \"%s\"," @@ -119,6 +119,22 @@ bool MacroActionProjector::Load(obs_data_t *obj) return true; } +std::shared_ptr MacroActionProjector::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionProjector::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionProjector::ResolveVariablesToFixedValues() +{ + _source.ResolveVariables(); + _scene.ResolveVariables(); +} + void MacroActionProjector::SetMonitor(int idx) { _monitor = idx; diff --git a/plugins/base/macro-action-projector.hpp b/plugins/base/macro-action-projector.hpp index 22ccbc997..dc9583c38 100644 --- a/plugins/base/macro-action-projector.hpp +++ b/plugins/base/macro-action-projector.hpp @@ -13,10 +13,9 @@ class MacroActionProjector : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); void SetMonitor(int); int GetMonitor() const; diff --git a/plugins/base/macro-action-random.cpp b/plugins/base/macro-action-random.cpp index 6180a8d8d..3408ed98e 100644 --- a/plugins/base/macro-action-random.cpp +++ b/plugins/base/macro-action-random.cpp @@ -64,7 +64,7 @@ bool MacroActionRandom::PerformAction() void MacroActionRandom::LogAction() const { - vblog(LOG_INFO, "running random macro"); + ablog(LOG_INFO, "running random macro"); } bool MacroActionRandom::Save(obs_data_t *obj) const @@ -83,6 +83,16 @@ bool MacroActionRandom::Load(obs_data_t *obj) return true; } +std::shared_ptr MacroActionRandom::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionRandom::Copy() const +{ + return std::make_shared(*this); +} + MacroActionRandomEdit::MacroActionRandomEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), diff --git a/plugins/base/macro-action-random.hpp b/plugins/base/macro-action-random.hpp index 7b6ec4186..f1a81ac9b 100644 --- a/plugins/base/macro-action-random.hpp +++ b/plugins/base/macro-action-random.hpp @@ -16,10 +16,8 @@ class MacroActionRandom : public MultiMacroRefAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; bool _allowRepeat = false; diff --git a/plugins/base/macro-action-recording.cpp b/plugins/base/macro-action-recording.cpp index 2054c836c..0feec5d3e 100644 --- a/plugins/base/macro-action-recording.cpp +++ b/plugins/base/macro-action-recording.cpp @@ -97,7 +97,7 @@ void MacroActionRecord::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, "performed action \"%s\"", it->second.c_str()); + ablog(LOG_INFO, "performed action \"%s\"", it->second.c_str()); } else { blog(LOG_WARNING, "ignored unknown recording action %d", static_cast(_action)); @@ -122,10 +122,26 @@ bool MacroActionRecord::Load(obs_data_t *obj) return true; } +std::shared_ptr MacroActionRecord::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionRecord::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionRecord::ResolveVariablesToFixedValues() +{ + _folder.ResolveVariables(); + _fileFormat.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { - for (auto entry : actionTypes) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : actionTypes) { + list->addItem(obs_module_text(name.c_str())); } } diff --git a/plugins/base/macro-action-recording.hpp b/plugins/base/macro-action-recording.hpp index 3af471f77..c8d0d96c5 100644 --- a/plugins/base/macro-action-recording.hpp +++ b/plugins/base/macro-action-recording.hpp @@ -17,10 +17,9 @@ class MacroActionRecord : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Action { STOP, diff --git a/plugins/base/macro-action-replay-buffer.cpp b/plugins/base/macro-action-replay-buffer.cpp index 7f6de1cc8..6e35b1423 100644 --- a/plugins/base/macro-action-replay-buffer.cpp +++ b/plugins/base/macro-action-replay-buffer.cpp @@ -47,7 +47,7 @@ void MacroActionReplayBuffer::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, "performed action \"%s\"", it->second.c_str()); + ablog(LOG_INFO, "performed action \"%s\"", it->second.c_str()); } else { blog(LOG_WARNING, "ignored unknown replay buffer action %d", static_cast(_action)); @@ -69,10 +69,20 @@ bool MacroActionReplayBuffer::Load(obs_data_t *obj) return true; } +std::shared_ptr MacroActionReplayBuffer::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionReplayBuffer::Copy() const +{ + return std::make_shared(*this); +} + static inline void populateActionSelection(QComboBox *list) { - for (auto entry : actionTypes) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : actionTypes) { + list->addItem(obs_module_text(name.c_str())); } } diff --git a/plugins/base/macro-action-replay-buffer.hpp b/plugins/base/macro-action-replay-buffer.hpp index e21974fab..bf7bc2e10 100644 --- a/plugins/base/macro-action-replay-buffer.hpp +++ b/plugins/base/macro-action-replay-buffer.hpp @@ -20,10 +20,8 @@ class MacroActionReplayBuffer : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; ReplayBufferAction _action = ReplayBufferAction::STOP; diff --git a/plugins/base/macro-action-run.cpp b/plugins/base/macro-action-run.cpp index c53da0aff..e5f73e938 100644 --- a/plugins/base/macro-action-run.cpp +++ b/plugins/base/macro-action-run.cpp @@ -33,7 +33,7 @@ bool MacroActionRun::PerformAction() void MacroActionRun::LogAction() const { - vblog(LOG_INFO, "run \"%s\"", _procConfig.UnresolvedPath().c_str()); + ablog(LOG_INFO, "run \"%s\"", _procConfig.UnresolvedPath().c_str()); } bool MacroActionRun::Save(obs_data_t *obj) const @@ -64,6 +64,22 @@ std::string MacroActionRun::GetShortDesc() const return _procConfig.UnresolvedPath(); } +std::shared_ptr MacroActionRun::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionRun::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionRun::ResolveVariablesToFixedValues() +{ + _procConfig.ResolveVariables(); + _timeout.ResolveVariables(); +} + MacroActionRunEdit::MacroActionRunEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), diff --git a/plugins/base/macro-action-run.hpp b/plugins/base/macro-action-run.hpp index a17f5065c..b1f1f5a06 100644 --- a/plugins/base/macro-action-run.hpp +++ b/plugins/base/macro-action-run.hpp @@ -16,10 +16,9 @@ class MacroActionRun : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); ProcessConfig _procConfig; bool _wait = false; diff --git a/plugins/base/macro-action-scene-collection.cpp b/plugins/base/macro-action-scene-collection.cpp index 29ec56c20..1530db186 100644 --- a/plugins/base/macro-action-scene-collection.cpp +++ b/plugins/base/macro-action-scene-collection.cpp @@ -31,7 +31,7 @@ bool MacroActionSceneCollection::PerformAction() void MacroActionSceneCollection::LogAction() const { - vblog(LOG_INFO, "set scene collection type to \"%s\"", + ablog(LOG_INFO, "set scene collection type to \"%s\"", _sceneCollection.c_str()); } @@ -54,6 +54,16 @@ std::string MacroActionSceneCollection::GetShortDesc() const return _sceneCollection; } +std::shared_ptr MacroActionSceneCollection::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSceneCollection::Copy() const +{ + return std::make_shared(*this); +} + void populateSceneCollectionSelection(QComboBox *box) { auto sceneCollections = obs_frontend_get_scene_collections(); diff --git a/plugins/base/macro-action-scene-collection.hpp b/plugins/base/macro-action-scene-collection.hpp index 6969e18b1..a6deab9c9 100644 --- a/plugins/base/macro-action-scene-collection.hpp +++ b/plugins/base/macro-action-scene-collection.hpp @@ -14,10 +14,8 @@ class MacroActionSceneCollection : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; std::string _sceneCollection; diff --git a/plugins/base/macro-action-scene-lock.cpp b/plugins/base/macro-action-scene-lock.cpp index 53cd871b8..1d0028289 100644 --- a/plugins/base/macro-action-scene-lock.cpp +++ b/plugins/base/macro-action-scene-lock.cpp @@ -37,7 +37,6 @@ static void setSceneItemLock(obs_sceneitem_t *item, bool MacroActionSceneLock::PerformAction() { - auto items = _source.GetSceneItems(_scene); for (const auto &item : items) { setSceneItemLock(item, _action); @@ -50,7 +49,7 @@ void MacroActionSceneLock::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, + ablog(LOG_INFO, "performed action \"%s\" for source \"%s\" on scene \"%s\"", it->second.c_str(), _source.ToString(true).c_str(), _scene.ToString(true).c_str()); @@ -87,6 +86,16 @@ std::string MacroActionSceneLock::GetShortDesc() const return ""; } +std::shared_ptr MacroActionSceneLock::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSceneLock::Copy() const +{ + return std::make_shared(*this); +} + static inline void populateActionSelection(QComboBox *list) { for (const auto &[_, name] : actionTypes) { @@ -94,6 +103,12 @@ static inline void populateActionSelection(QComboBox *list) } } +void MacroActionSceneLock::ResolveVariablesToFixedValues() +{ + _scene.ResolveVariables(); + _source.ResolveVariables(); +} + MacroActionSceneLockEdit::MacroActionSceneLockEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), diff --git a/plugins/base/macro-action-scene-lock.hpp b/plugins/base/macro-action-scene-lock.hpp index 5b4ea22f1..a3d0071ac 100644 --- a/plugins/base/macro-action-scene-lock.hpp +++ b/plugins/base/macro-action-scene-lock.hpp @@ -14,10 +14,9 @@ class MacroActionSceneLock : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Action { LOCK, diff --git a/plugins/base/macro-action-scene-order.cpp b/plugins/base/macro-action-scene-order.cpp index f3adb58c7..279173cb4 100644 --- a/plugins/base/macro-action-scene-order.cpp +++ b/plugins/base/macro-action-scene-order.cpp @@ -96,7 +96,7 @@ void MacroActionSceneOrder::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, + ablog(LOG_INFO, "performed order action \"%s\" for source \"%s\" on scene \"%s\"", it->second.c_str(), _source.ToString(true).c_str(), _scene.ToString(true).c_str()); @@ -142,6 +142,22 @@ std::string MacroActionSceneOrder::GetShortDesc() const return _scene.ToString() + " - " + _source.ToString(); } +std::shared_ptr MacroActionSceneOrder::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSceneOrder::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionSceneOrder::ResolveVariablesToFixedValues() +{ + _scene.ResolveVariables(); + _source.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (const auto &entry : actionTypes) { diff --git a/plugins/base/macro-action-scene-order.hpp b/plugins/base/macro-action-scene-order.hpp index f932953ff..f214de07b 100644 --- a/plugins/base/macro-action-scene-order.hpp +++ b/plugins/base/macro-action-scene-order.hpp @@ -24,10 +24,9 @@ class MacroActionSceneOrder : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); SceneSelection _scene; SceneItemSelection _source; diff --git a/plugins/base/macro-action-scene-switch.cpp b/plugins/base/macro-action-scene-switch.cpp index 536fe4931..bbddb0a17 100644 --- a/plugins/base/macro-action-scene-switch.cpp +++ b/plugins/base/macro-action-scene-switch.cpp @@ -164,7 +164,7 @@ bool MacroActionSwitchScene::PerformAction() void MacroActionSwitchScene::LogAction() const { - vblog(LOG_INFO, "switch%s scene to '%s'", + ablog(LOG_INFO, "switch%s scene to '%s'", _sceneType == SceneType::PREVIEW ? " preview" : "", _scene.ToString(true).c_str()); } @@ -198,6 +198,22 @@ std::string MacroActionSwitchScene::GetShortDesc() const return _scene.ToString(); } +std::shared_ptr MacroActionSwitchScene::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSwitchScene::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionSwitchScene::ResolveVariablesToFixedValues() +{ + _scene.ResolveVariables(); + _duration.ResolveVariables(); +} + static inline void populateTypeSelection(QComboBox *list) { for (const auto &[_, name] : sceneTypes) { diff --git a/plugins/base/macro-action-scene-switch.hpp b/plugins/base/macro-action-scene-switch.hpp index 5df5e47da..36eab5cfd 100644 --- a/plugins/base/macro-action-scene-switch.hpp +++ b/plugins/base/macro-action-scene-switch.hpp @@ -17,11 +17,9 @@ class MacroActionSwitchScene : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class SceneType { PROGRAM, PREVIEW }; SceneType _sceneType = SceneType::PROGRAM; diff --git a/plugins/base/macro-action-scene-transform.cpp b/plugins/base/macro-action-scene-transform.cpp index 22d8d235d..22d09c278 100644 --- a/plugins/base/macro-action-scene-transform.cpp +++ b/plugins/base/macro-action-scene-transform.cpp @@ -257,7 +257,7 @@ bool MacroActionSceneTransform::PerformAction() void MacroActionSceneTransform::LogAction() const { - vblog(LOG_INFO, + ablog(LOG_INFO, "performed transform action %d for source \"%s\" on scene \"%s\"", static_cast(_action), _source.ToString(true).c_str(), _scene.ToString(true).c_str()); @@ -312,6 +312,24 @@ std::string MacroActionSceneTransform::GetShortDesc() const return _scene.ToString() + " - " + _source.ToString(); } +std::shared_ptr MacroActionSceneTransform::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSceneTransform::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionSceneTransform::ResolveVariablesToFixedValues() +{ + _scene.ResolveVariables(); + _source.ResolveVariables(); + _settings.ResolveVariables(); + _rotation.ResolveVariables(); +} + std::string MacroActionSceneTransform::ConvertSettings() { auto data = obs_data_create(); diff --git a/plugins/base/macro-action-scene-transform.hpp b/plugins/base/macro-action-scene-transform.hpp index c61bb83c1..08a7de581 100644 --- a/plugins/base/macro-action-scene-transform.hpp +++ b/plugins/base/macro-action-scene-transform.hpp @@ -18,10 +18,9 @@ class MacroActionSceneTransform : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Action { RESET, diff --git a/plugins/base/macro-action-scene-visibility.cpp b/plugins/base/macro-action-scene-visibility.cpp index d7ce252f9..0a6b57bfd 100644 --- a/plugins/base/macro-action-scene-visibility.cpp +++ b/plugins/base/macro-action-scene-visibility.cpp @@ -50,7 +50,7 @@ void MacroActionSceneVisibility::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, + ablog(LOG_INFO, "performed visibility action \"%s\" for source \"%s\" on scene \"%s\"", it->second.c_str(), _source.ToString(true).c_str(), _scene.ToString(true).c_str()); @@ -101,6 +101,22 @@ std::string MacroActionSceneVisibility::GetShortDesc() const return ""; } +std::shared_ptr MacroActionSceneVisibility::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSceneVisibility::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionSceneVisibility::ResolveVariablesToFixedValues() +{ + _scene.ResolveVariables(); + _source.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (const auto &entry : actionTypes) { diff --git a/plugins/base/macro-action-scene-visibility.hpp b/plugins/base/macro-action-scene-visibility.hpp index c78baff82..40f4fc154 100644 --- a/plugins/base/macro-action-scene-visibility.hpp +++ b/plugins/base/macro-action-scene-visibility.hpp @@ -16,10 +16,9 @@ class MacroActionSceneVisibility : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); SceneSelection _scene; SceneItemSelection _source; diff --git a/plugins/base/macro-action-screenshot.cpp b/plugins/base/macro-action-screenshot.cpp index 1139705f2..974bb7821 100644 --- a/plugins/base/macro-action-screenshot.cpp +++ b/plugins/base/macro-action-screenshot.cpp @@ -6,8 +6,6 @@ namespace advss { -const uint32_t MacroActionScreenshot::_version = 1; - const std::string MacroActionScreenshot::id = "screenshot"; bool MacroActionScreenshot::_registered = MacroActionFactory::Register( @@ -71,15 +69,15 @@ void MacroActionScreenshot::LogAction() const { switch (_targetType) { case MacroActionScreenshot::TargetType::SOURCE: - vblog(LOG_INFO, "trigger screenshot of \"%s\"", + ablog(LOG_INFO, "trigger screenshot of \"%s\"", _source.ToString(true).c_str()); break; case MacroActionScreenshot::TargetType::SCENE: - vblog(LOG_INFO, "trigger screenshot of \"%s\"", + ablog(LOG_INFO, "trigger screenshot of \"%s\"", _scene.ToString(true).c_str()); break; case MacroActionScreenshot::TargetType::MAIN_OUTPUT: - vblog(LOG_INFO, "trigger screenshot of main output"); + ablog(LOG_INFO, "trigger screenshot of main output"); break; } } @@ -92,7 +90,7 @@ bool MacroActionScreenshot::Save(obs_data_t *obj) const obs_data_set_int(obj, "saveType", static_cast(_saveType)); obs_data_set_int(obj, "targetType", static_cast(_targetType)); _path.Save(obj, "savePath"); - obs_data_set_int(obj, "version", _version); + obs_data_set_int(obj, "version", 1); return true; } @@ -125,6 +123,28 @@ std::string MacroActionScreenshot::GetShortDesc() const return ""; } +std::shared_ptr MacroActionScreenshot::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionScreenshot::Copy() const +{ + auto result = Create(GetMacro()); + OBSDataAutoRelease data = obs_data_create(); + Save(data); + result->Load(data); + result->PostLoad(); + return result; +} + +void MacroActionScreenshot::ResolveVariablesToFixedValues() +{ + _scene.ResolveVariables(); + _source.ResolveVariables(); + _path.ResolveVariables(); +} + static void populateSaveTypeSelection(QComboBox *list) { list->addItem(obs_module_text( diff --git a/plugins/base/macro-action-screenshot.hpp b/plugins/base/macro-action-screenshot.hpp index 13b6cfd1c..959f6f8f6 100644 --- a/plugins/base/macro-action-screenshot.hpp +++ b/plugins/base/macro-action-screenshot.hpp @@ -18,15 +18,16 @@ class MacroActionScreenshot : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); + enum class SaveType { OBS_DEFAULT, CUSTOM, }; SaveType _saveType = SaveType::OBS_DEFAULT; + enum class TargetType { SOURCE, SCENE, @@ -43,7 +44,6 @@ class MacroActionScreenshot : public MacroAction { ScreenshotHelper _screenshot; - const static uint32_t _version; static bool _registered; static const std::string id; }; diff --git a/plugins/base/macro-action-sequence.cpp b/plugins/base/macro-action-sequence.cpp index a05be7efa..316156c42 100644 --- a/plugins/base/macro-action-sequence.cpp +++ b/plugins/base/macro-action-sequence.cpp @@ -66,6 +66,21 @@ MacroRef MacroActionSequence::GetNextMacro(bool advance) return res; } +std::shared_ptr MacroActionSequence::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSequence::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionSequence::ResolveVariablesToFixedValues() +{ + _resetIndex.ResolveVariables(); +} + bool MacroActionSequence::RunSequence() { if (_macros.size() == 0) { @@ -122,7 +137,7 @@ bool MacroActionSequence::PerformAction() void MacroActionSequence::LogAction() const { if (_action == Action::RUN_SEQUENCE) { - vblog(LOG_INFO, "running macro sequence"); + ablog(LOG_INFO, "running macro sequence"); } else { vblog(LOG_INFO, "set sequences of macro '%s' to index %d", _macro.Name().c_str(), _resetIndex.GetValue()); diff --git a/plugins/base/macro-action-sequence.hpp b/plugins/base/macro-action-sequence.hpp index 15a2ecbf8..080bee7f3 100644 --- a/plugins/base/macro-action-sequence.hpp +++ b/plugins/base/macro-action-sequence.hpp @@ -14,7 +14,9 @@ namespace advss { class MacroActionSequence : public MultiMacroRefAction, public MacroRefAction { public: MacroActionSequence(Macro *m) - : MacroAction(m), MultiMacroRefAction(m), MacroRefAction(m) + : MacroAction(m), + MultiMacroRefAction(m), + MacroRefAction(m) { } bool PerformAction(); @@ -24,10 +26,9 @@ class MacroActionSequence : public MultiMacroRefAction, public MacroRefAction { bool PostLoad() override; std::string GetId() const { return id; }; MacroRef GetNextMacro(bool advance = true); - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Action { RUN_SEQUENCE, diff --git a/plugins/base/macro-action-source.cpp b/plugins/base/macro-action-source.cpp index 668ad9701..35d7d066a 100644 --- a/plugins/base/macro-action-source.cpp +++ b/plugins/base/macro-action-source.cpp @@ -209,7 +209,7 @@ void MacroActionSource::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, "performed action \"%s\" for Source \"%s\"", + ablog(LOG_INFO, "performed action \"%s\" for Source \"%s\"", it->second.c_str(), _source.ToString(true).c_str()); } else { blog(LOG_WARNING, "ignored unknown source action %d", @@ -266,6 +266,23 @@ std::string MacroActionSource::GetShortDesc() const return ""; } +std::shared_ptr MacroActionSource::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSource::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionSource::ResolveVariablesToFixedValues() +{ + _source.ResolveVariables(); + _settingsString.ResolveVariables(); + _manualSettingValue.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (auto &[actionType, name] : actionTypes) { diff --git a/plugins/base/macro-action-source.hpp b/plugins/base/macro-action-source.hpp index e90bc8302..444433242 100644 --- a/plugins/base/macro-action-source.hpp +++ b/plugins/base/macro-action-source.hpp @@ -29,10 +29,9 @@ class MacroActionSource : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); SourceSelection _source; SourceSettingButton _button; diff --git a/plugins/base/macro-action-streaming.cpp b/plugins/base/macro-action-streaming.cpp index f00bdd762..6087c4e2e 100644 --- a/plugins/base/macro-action-streaming.cpp +++ b/plugins/base/macro-action-streaming.cpp @@ -128,7 +128,7 @@ void MacroActionStream::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, "performed action \"%s\"", it->second.c_str()); + ablog(LOG_INFO, "performed action \"%s\"", it->second.c_str()); } else { blog(LOG_WARNING, "ignored unknown streaming action %d", static_cast(_action)); @@ -153,6 +153,22 @@ bool MacroActionStream::Load(obs_data_t *obj) return true; } +std::shared_ptr MacroActionStream::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionStream::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionStream::ResolveVariablesToFixedValues() +{ + _keyFrameInterval.ResolveVariables(); + _stringValue.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (auto entry : actionTypes) { diff --git a/plugins/base/macro-action-streaming.hpp b/plugins/base/macro-action-streaming.hpp index 45950b489..83a110b86 100644 --- a/plugins/base/macro-action-streaming.hpp +++ b/plugins/base/macro-action-streaming.hpp @@ -18,10 +18,9 @@ class MacroActionStream : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Action { STOP, diff --git a/plugins/base/macro-action-studio-mode.cpp b/plugins/base/macro-action-studio-mode.cpp index 567f1957e..2289b247a 100644 --- a/plugins/base/macro-action-studio-mode.cpp +++ b/plugins/base/macro-action-studio-mode.cpp @@ -69,7 +69,7 @@ void MacroActionSudioMode::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, "performed action \"%s\" with scene \"%s\"", + ablog(LOG_INFO, "performed action \"%s\" with scene \"%s\"", it->second.c_str(), _scene.ToString(true).c_str()); } else { blog(LOG_WARNING, "ignored unknown studio mode action %d", @@ -101,6 +101,21 @@ std::string MacroActionSudioMode::GetShortDesc() const return ""; } +std::shared_ptr MacroActionSudioMode::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSudioMode::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionSudioMode::ResolveVariablesToFixedValues() +{ + _scene.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (const auto &[id, name] : actionTypes) { diff --git a/plugins/base/macro-action-studio-mode.hpp b/plugins/base/macro-action-studio-mode.hpp index a43489c1e..9f782f9bb 100644 --- a/plugins/base/macro-action-studio-mode.hpp +++ b/plugins/base/macro-action-studio-mode.hpp @@ -13,10 +13,9 @@ class MacroActionSudioMode : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Action { SWAP_SCENE, diff --git a/plugins/base/macro-action-systray.cpp b/plugins/base/macro-action-systray.cpp index 99c8400b8..0e54cc3da 100644 --- a/plugins/base/macro-action-systray.cpp +++ b/plugins/base/macro-action-systray.cpp @@ -24,7 +24,7 @@ bool MacroActionSystray::PerformAction() void MacroActionSystray::LogAction() const { - vblog(LOG_INFO, "display systray message \"%s\":\n%s", _title.c_str(), + ablog(LOG_INFO, "display systray message \"%s\":\n%s", _title.c_str(), _message.c_str()); } @@ -50,6 +50,23 @@ bool MacroActionSystray::Load(obs_data_t *obj) return true; } +std::shared_ptr MacroActionSystray::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionSystray::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionSystray::ResolveVariablesToFixedValues() +{ + _message.ResolveVariables(); + _title.ResolveVariables(); + _iconPath.ResolveVariables(); +} + MacroActionSystrayEdit::MacroActionSystrayEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), diff --git a/plugins/base/macro-action-systray.hpp b/plugins/base/macro-action-systray.hpp index 2608acd6f..b9654e275 100644 --- a/plugins/base/macro-action-systray.hpp +++ b/plugins/base/macro-action-systray.hpp @@ -15,10 +15,9 @@ class MacroActionSystray : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); StringVariable _message = ""; StringVariable _title = obs_module_text("AdvSceneSwitcher.pluginName"); diff --git a/plugins/base/macro-action-timer.cpp b/plugins/base/macro-action-timer.cpp index 456a8912c..14b3da30e 100644 --- a/plugins/base/macro-action-timer.cpp +++ b/plugins/base/macro-action-timer.cpp @@ -14,11 +14,14 @@ bool MacroActionTimer::_registered = MacroActionFactory::Register( {MacroActionTimer::Create, MacroActionTimerEdit::Create, "AdvSceneSwitcher.action.timer"}); -const static std::map timerActions = { - {TimerAction::PAUSE, "AdvSceneSwitcher.action.timer.type.pause"}, - {TimerAction::CONTINUE, "AdvSceneSwitcher.action.timer.type.continue"}, - {TimerAction::RESET, "AdvSceneSwitcher.action.timer.type.reset"}, - {TimerAction::SET_TIME_REMAINING, +const static std::map timerActions = { + {MacroActionTimer::Action::PAUSE, + "AdvSceneSwitcher.action.timer.type.pause"}, + {MacroActionTimer::Action::CONTINUE, + "AdvSceneSwitcher.action.timer.type.continue"}, + {MacroActionTimer::Action::RESET, + "AdvSceneSwitcher.action.timer.type.reset"}, + {MacroActionTimer::Action::SET_TIME_REMAINING, "AdvSceneSwitcher.action.timer.type.setTimeRemaining"}, }; @@ -40,16 +43,16 @@ bool MacroActionTimer::PerformAction() } switch (_actionType) { - case TimerAction::PAUSE: + case Action::PAUSE: timerCondition->Pause(); break; - case TimerAction::CONTINUE: + case Action::CONTINUE: timerCondition->Continue(); break; - case TimerAction::RESET: + case Action::RESET: timerCondition->Reset(); break; - case TimerAction::SET_TIME_REMAINING: + case Action::SET_TIME_REMAINING: timerCondition->_duration.SetTimeRemaining( _duration.Seconds()); break; @@ -67,20 +70,20 @@ void MacroActionTimer::LogAction() const return; } switch (_actionType) { - case TimerAction::PAUSE: - vblog(LOG_INFO, "paused timers on \"%s\"", + case Action::PAUSE: + ablog(LOG_INFO, "paused timers on \"%s\"", GetMacroName(macro.get()).c_str()); break; - case TimerAction::CONTINUE: - vblog(LOG_INFO, "continued timers on \"%s\"", + case Action::CONTINUE: + ablog(LOG_INFO, "continued timers on \"%s\"", GetMacroName(macro.get()).c_str()); break; - case TimerAction::RESET: - vblog(LOG_INFO, "reset timers on \"%s\"", + case Action::RESET: + ablog(LOG_INFO, "reset timers on \"%s\"", GetMacroName(macro.get()).c_str()); break; - case TimerAction::SET_TIME_REMAINING: - vblog(LOG_INFO, + case Action::SET_TIME_REMAINING: + ablog(LOG_INFO, "set time remaining of timers on \"%s\" to \"%s\"", GetMacroName(macro.get()).c_str(), _duration.ToString().c_str()); @@ -104,8 +107,7 @@ bool MacroActionTimer::Load(obs_data_t *obj) MacroAction::Load(obj); _macro.Load(obj); _duration.Load(obj); - _actionType = - static_cast(obs_data_get_int(obj, "actionType")); + _actionType = static_cast(obs_data_get_int(obj, "actionType")); return true; } @@ -114,10 +116,25 @@ std::string MacroActionTimer::GetShortDesc() const return _macro.Name(); } +std::shared_ptr MacroActionTimer::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionTimer::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionTimer::ResolveVariablesToFixedValues() +{ + _duration.ResolveVariables(); +} + static inline void populateTypeSelection(QComboBox *list) { - for (auto entry : timerActions) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : timerActions) { + list->addItem(obs_module_text(name.c_str())); } } @@ -173,7 +190,7 @@ void MacroActionTimerEdit::ActionTypeChanged(int value) } auto lock = LockContext(); - _entryData->_actionType = static_cast(value); + _entryData->_actionType = static_cast(value); SetWidgetVisibility(); } @@ -183,7 +200,7 @@ void MacroActionTimerEdit::SetWidgetVisibility() return; } _duration->setVisible(_entryData->_actionType == - TimerAction::SET_TIME_REMAINING); + MacroActionTimer::Action::SET_TIME_REMAINING); adjustSize(); } diff --git a/plugins/base/macro-action-timer.hpp b/plugins/base/macro-action-timer.hpp index 75bee4945..8b3fbd7d0 100644 --- a/plugins/base/macro-action-timer.hpp +++ b/plugins/base/macro-action-timer.hpp @@ -8,13 +8,6 @@ namespace advss { -enum class TimerAction { - PAUSE, - CONTINUE, - RESET, - SET_TIME_REMAINING, -}; - class MacroActionTimer : public MacroRefAction { public: MacroActionTimer(Macro *m) : MacroAction(m), MacroRefAction(m) {} @@ -24,12 +17,19 @@ class MacroActionTimer : public MacroRefAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); + Duration _duration; - TimerAction _actionType = TimerAction::PAUSE; + + enum class Action { + PAUSE, + CONTINUE, + RESET, + SET_TIME_REMAINING, + }; + Action _actionType = Action::PAUSE; private: static bool _registered; diff --git a/plugins/base/macro-action-transition.cpp b/plugins/base/macro-action-transition.cpp index 413b6d507..fb1ddf30b 100644 --- a/plugins/base/macro-action-transition.cpp +++ b/plugins/base/macro-action-transition.cpp @@ -156,11 +156,11 @@ void MacroActionTransition::LogAction() const break; } if (_setDuration) { - vblog(LOG_INFO, "%s duration to %s", msgBegin.c_str(), + ablog(LOG_INFO, "%s duration to %s", msgBegin.c_str(), _duration.ToString().c_str()); } if (_setTransitionType) { - vblog(LOG_INFO, "%s type to \"%s\"", msgBegin.c_str(), + ablog(LOG_INFO, "%s type to \"%s\"", msgBegin.c_str(), _transition.ToString().c_str()); } } @@ -209,10 +209,27 @@ std::string MacroActionTransition::GetShortDesc() const return ""; } +std::shared_ptr MacroActionTransition::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionTransition::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionTransition::ResolveVariablesToFixedValues() +{ + _source.ResolveVariables(); + _scene.ResolveVariables(); + _duration.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { - for (const auto &entry : actionTypes) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : actionTypes) { + list->addItem(obs_module_text(name.c_str())); } } diff --git a/plugins/base/macro-action-transition.hpp b/plugins/base/macro-action-transition.hpp index daca5e4a9..a10b96e66 100644 --- a/plugins/base/macro-action-transition.hpp +++ b/plugins/base/macro-action-transition.hpp @@ -19,10 +19,9 @@ class MacroActionTransition : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Type { SCENE, diff --git a/plugins/base/macro-action-virtual-cam.cpp b/plugins/base/macro-action-virtual-cam.cpp index 25efe7e92..d93f00155 100644 --- a/plugins/base/macro-action-virtual-cam.cpp +++ b/plugins/base/macro-action-virtual-cam.cpp @@ -12,21 +12,23 @@ bool MacroActionVCam::_registered = MacroActionFactory::Register( {MacroActionVCam::Create, MacroActionVCamEdit::Create, "AdvSceneSwitcher.action.virtualCamera"}); -const static std::map actionTypes = { - {VCamAction::STOP, "AdvSceneSwitcher.action.virtualCamera.type.stop"}, - {VCamAction::START, "AdvSceneSwitcher.action.virtualCamera.type.start"}, +static const std::map actionTypes = { + {MacroActionVCam::Action::STOP, + "AdvSceneSwitcher.action.virtualCamera.type.stop"}, + {MacroActionVCam::Action::START, + "AdvSceneSwitcher.action.virtualCamera.type.start"}, }; bool MacroActionVCam::PerformAction() { #if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(27, 0, 0) switch (_action) { - case VCamAction::STOP: + case Action::STOP: if (obs_frontend_virtualcam_active()) { obs_frontend_stop_virtualcam(); } break; - case VCamAction::START: + case Action::START: if (!obs_frontend_virtualcam_active()) { obs_frontend_start_virtualcam(); } @@ -42,7 +44,7 @@ void MacroActionVCam::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, "performed action \"%s\"", it->second.c_str()); + ablog(LOG_INFO, "performed action \"%s\"", it->second.c_str()); } else { blog(LOG_WARNING, "ignored unknown virtual camera action %d", static_cast(_action)); @@ -59,14 +61,24 @@ bool MacroActionVCam::Save(obs_data_t *obj) const bool MacroActionVCam::Load(obs_data_t *obj) { MacroAction::Load(obj); - _action = static_cast(obs_data_get_int(obj, "action")); + _action = static_cast(obs_data_get_int(obj, "action")); return true; } +std::shared_ptr MacroActionVCam::Create(Macro *m) +{ + return std::shared_ptr(); +} + +std::shared_ptr MacroActionVCam::Copy() const +{ + return std::shared_ptr(); +} + static inline void populateActionSelection(QComboBox *list) { - for (auto entry : actionTypes) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : actionTypes) { + list->addItem(obs_module_text(name.c_str())); } } @@ -110,7 +122,7 @@ void MacroActionVCamEdit::ActionChanged(int value) } auto lock = LockContext(); - _entryData->_action = static_cast(value); + _entryData->_action = static_cast(value); } } // namespace advss diff --git a/plugins/base/macro-action-virtual-cam.hpp b/plugins/base/macro-action-virtual-cam.hpp index 2bd5be2f2..0eade7f1a 100644 --- a/plugins/base/macro-action-virtual-cam.hpp +++ b/plugins/base/macro-action-virtual-cam.hpp @@ -6,11 +6,6 @@ namespace advss { -enum class VCamAction { - STOP, - START, -}; - class MacroActionVCam : public MacroAction { public: MacroActionVCam(Macro *m) : MacroAction(m) {} @@ -19,12 +14,14 @@ class MacroActionVCam : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } - - VCamAction _action = VCamAction::STOP; + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + + enum class Action { + STOP, + START, + }; + Action _action = Action::STOP; private: static bool _registered; diff --git a/plugins/base/macro-action-wait.cpp b/plugins/base/macro-action-wait.cpp index 61ede4094..41f7f6759 100644 --- a/plugins/base/macro-action-wait.cpp +++ b/plugins/base/macro-action-wait.cpp @@ -97,10 +97,26 @@ std::string MacroActionWait::GetShortDesc() const return _duration.ToString() + " - " + _duration2.ToString(); } +std::shared_ptr MacroActionWait::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionWait::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionWait::ResolveVariablesToFixedValues() +{ + _duration.ResolveVariables(); + _duration2.ResolveVariables(); +} + static inline void populateTypeSelection(QComboBox *list) { - for (const auto &entry : waitTypes) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : waitTypes) { + list->addItem(obs_module_text(name.c_str())); } } diff --git a/plugins/base/macro-action-wait.hpp b/plugins/base/macro-action-wait.hpp index c99034577..ba576c3ed 100644 --- a/plugins/base/macro-action-wait.hpp +++ b/plugins/base/macro-action-wait.hpp @@ -15,10 +15,10 @@ class MacroActionWait : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); + Duration _duration; Duration _duration2; diff --git a/plugins/base/macro-action-websocket.cpp b/plugins/base/macro-action-websocket.cpp index 3ab470fdd..3f35691e9 100644 --- a/plugins/base/macro-action-websocket.cpp +++ b/plugins/base/macro-action-websocket.cpp @@ -56,7 +56,7 @@ bool MacroActionWebsocket::PerformAction() void MacroActionWebsocket::LogAction() const { if (_api == API::GENERIC_WEBSOCKET) { - vblog(LOG_INFO, + ablog(LOG_INFO, "sent generic websocket message \"%s\" via \"%s\"", _message.c_str(), GetWeakConnectionName(_connection).c_str()); @@ -64,7 +64,7 @@ void MacroActionWebsocket::LogAction() const } if (_api == API::OBS_WEBSOCKET) { - vblog(LOG_INFO, "sent obs websocket message \"%s\" via \"%s\"", + ablog(LOG_INFO, "sent obs websocket message \"%s\" via \"%s\"", _message.c_str(), GetWeakConnectionName(_connection).c_str()); return; @@ -72,12 +72,12 @@ void MacroActionWebsocket::LogAction() const switch (_type) { case MacroActionWebsocket::MessageType::REQUEST: - vblog(LOG_INFO, "sent scene switcher message \"%s\" via \"%s\"", + ablog(LOG_INFO, "sent scene switcher message \"%s\" via \"%s\"", _message.c_str(), GetWeakConnectionName(_connection).c_str()); break; case MacroActionWebsocket::MessageType::EVENT: - vblog(LOG_INFO, + ablog(LOG_INFO, "sent scene switcher event \"%s\" to connected clients", _message.c_str()); break; @@ -116,6 +116,21 @@ std::string MacroActionWebsocket::GetShortDesc() const return ""; } +std::shared_ptr MacroActionWebsocket::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionWebsocket::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionWebsocket::ResolveVariablesToFixedValues() +{ + _message.ResolveVariables(); +} + static inline void populateAPISelection(QComboBox *list) { for (const auto &[_, name] : apiTypes) { diff --git a/plugins/base/macro-action-websocket.hpp b/plugins/base/macro-action-websocket.hpp index 9f4ff0a3f..92bdb66c1 100644 --- a/plugins/base/macro-action-websocket.hpp +++ b/plugins/base/macro-action-websocket.hpp @@ -19,10 +19,9 @@ class MacroActionWebsocket : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class API { SCENE_SWITCHER, diff --git a/plugins/base/macro-action-window.cpp b/plugins/base/macro-action-window.cpp index ebcc192b8..626e5aa82 100644 --- a/plugins/base/macro-action-window.cpp +++ b/plugins/base/macro-action-window.cpp @@ -136,6 +136,21 @@ std::string MacroActionWindow::GetShortDesc() const return _window; } +std::shared_ptr MacroActionWindow::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionWindow::Copy() const +{ + return std::make_shared(*this); +} + +void MacroActionWindow::ResolveVariablesToFixedValues() +{ + _window.ResolveVariables(); +} + static inline void populateActionSelection(QComboBox *list) { for (const auto &[_, name] : actionTypes) { diff --git a/plugins/base/macro-action-window.hpp b/plugins/base/macro-action-window.hpp index ee8633b7b..93185f1d5 100644 --- a/plugins/base/macro-action-window.hpp +++ b/plugins/base/macro-action-window.hpp @@ -14,10 +14,9 @@ class MacroActionWindow : public MacroAction { bool Load(obs_data_t *obj); std::string GetShortDesc() const; std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + void ResolveVariablesToFixedValues(); enum class Action { SET_FOCUS_WINDOW, diff --git a/plugins/base/macro-condition-obs-stats.hpp b/plugins/base/macro-condition-obs-stats.hpp index 7d317ff68..2c8c0b51c 100644 --- a/plugins/base/macro-condition-obs-stats.hpp +++ b/plugins/base/macro-condition-obs-stats.hpp @@ -2,6 +2,7 @@ #include "macro-condition-edit.hpp" #include "variable-spinbox.hpp" +#include #include #include #include diff --git a/plugins/base/utils/filter-selection.cpp b/plugins/base/utils/filter-selection.cpp index 568b19d0a..01e6e065a 100644 --- a/plugins/base/utils/filter-selection.cpp +++ b/plugins/base/utils/filter-selection.cpp @@ -114,6 +114,20 @@ FilterSelection::GetFilters(const SourceSelection &source) const return {}; } +void FilterSelection::ResolveVariables() +{ + if (_type != Type::VARIABLE) { + return; + } + _type = Type::SOURCE; + auto var = _variable.lock(); + if (!var) { + _filterName = ""; + return; + } + _filterName = var->Value(); +} + std::string FilterSelection::ToString(bool resolve) const { switch (_type) { diff --git a/plugins/base/utils/filter-selection.hpp b/plugins/base/utils/filter-selection.hpp index eae93420c..bd8091739 100644 --- a/plugins/base/utils/filter-selection.hpp +++ b/plugins/base/utils/filter-selection.hpp @@ -19,6 +19,7 @@ class FilterSelection { Type GetType() const { return _type; } std::vector GetFilters(const SourceSelection &source) const; + void ResolveVariables(); std::string ToString(bool resolve = false) const; private: diff --git a/plugins/base/utils/osc-helpers.cpp b/plugins/base/utils/osc-helpers.cpp index 266614c63..0bc493683 100644 --- a/plugins/base/utils/osc-helpers.cpp +++ b/plugins/base/utils/osc-helpers.cpp @@ -1,4 +1,5 @@ #include "osc-helpers.hpp" +#include "log-helper.hpp" #include "obs-module-helper.hpp" #include "ui-helpers.hpp" @@ -139,6 +140,11 @@ void OSCBlob::Load(obs_data_t *obj, const char *name) _stringRep.Load(obj, name); } +void OSCBlob::ResolveVariables() +{ + _stringRep.ResolveVariables(); +} + void OSCTrue::Save(obs_data_t *obj, const char *name) const { obs_data_set_bool(obj, name, true); @@ -200,6 +206,14 @@ std::optional> OSCMessage::GetBuffer() const return buffer; } +void OSCMessage::ResolveVariables() +{ + _address.ResolveVariables(); + for (auto &element : _elements) { + element.ResolveVariables(); + } +} + const char *OSCMessageElement::GetTypeTag() const { return GetTypeTag(*this); @@ -215,6 +229,21 @@ const char *OSCMessageElement::GetTypeTag(const OSCMessageElement &element) return _typeNames.at(element._value.index()).tag; } +void OSCMessageElement::ResolveVariables() +{ + std::visit( + [](auto &&arg) { + using T = std::decay_t; + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) { + arg.ResolveVariables(); + } + }, + _value); +} + const char *OSCMessageElement::GetTypeName(const OSCMessageElement &element) { return obs_module_text( diff --git a/plugins/base/utils/osc-helpers.hpp b/plugins/base/utils/osc-helpers.hpp index 31898b6a7..f2391196b 100644 --- a/plugins/base/utils/osc-helpers.hpp +++ b/plugins/base/utils/osc-helpers.hpp @@ -19,6 +19,7 @@ class OSCBlob { std::optional> GetBinary() const; void Save(obs_data_t *obj, const char *name) const; void Load(obs_data_t *obj, const char *name); + void ResolveVariables(); private: StringVariable _stringRep; @@ -69,6 +70,8 @@ class OSCMessageElement { static const char *GetTypeName(const OSCMessageElement &); static const char *GetTypeTag(const OSCMessageElement &); + void ResolveVariables(); + private: struct TypeInfo { const char *localizedName, *tag; @@ -91,6 +94,8 @@ class OSCMessage { std::string ToString() const; std::optional> GetBuffer() const; + void ResolveVariables(); + private: StringVariable _address = "/address"; std::vector _elements = { diff --git a/plugins/base/utils/process-config.cpp b/plugins/base/utils/process-config.cpp index 4ccce5fc3..8351a7195 100644 --- a/plugins/base/utils/process-config.cpp +++ b/plugins/base/utils/process-config.cpp @@ -53,6 +53,13 @@ bool ProcessConfig::StartProcessDetached() const QString::fromStdString(WorkingDir())); } +void ProcessConfig::ResolveVariables() +{ + _path.ResolveVariables(); + _workingDirectory.ResolveVariables(); + _args.ResolveVariables(); +} + std::variant ProcessConfig::StartProcessAndWait(int timeout) const { diff --git a/plugins/base/utils/process-config.hpp b/plugins/base/utils/process-config.hpp index f353459ec..e70856ccd 100644 --- a/plugins/base/utils/process-config.hpp +++ b/plugins/base/utils/process-config.hpp @@ -34,6 +34,8 @@ class ProcessConfig { StartProcessAndWait(int timeoutInMs) const; bool StartProcessDetached() const; + void ResolveVariables(); + private: StringVariable _path = obs_module_text("AdvSceneSwitcher.enterPath"); StringVariable _workingDirectory = ""; diff --git a/plugins/base/utils/scene-item-selection.cpp b/plugins/base/utils/scene-item-selection.cpp index 4dd9d0887..5826ee51c 100644 --- a/plugins/base/utils/scene-item-selection.cpp +++ b/plugins/base/utils/scene-item-selection.cpp @@ -304,6 +304,25 @@ void SceneItemSelection::SetSourceTypeSelection(const char *type) _sourceGroup = type; } +void SceneItemSelection::ResolveVariables() +{ + _index.ResolveVariables(); + _indexEnd.ResolveVariables(); + _pattern = std::string(_pattern); + + if (_type != Type::VARIABLE_NAME) { + return; + } + _type = Type::SOURCE_NAME; + + auto variable = _variable.lock(); + if (variable) { + _source = GetWeakSourceByName(variable->Value().c_str()); + } else { + _source = nullptr; + } +} + void SceneItemSelection::ReduceBadedOnIndexSelection( std::vector &items) const { diff --git a/plugins/base/utils/scene-item-selection.hpp b/plugins/base/utils/scene-item-selection.hpp index 9204bde53..d91832ef7 100644 --- a/plugins/base/utils/scene-item-selection.hpp +++ b/plugins/base/utils/scene-item-selection.hpp @@ -53,6 +53,8 @@ class SceneItemSelection { // scene item visibility action void SetSourceTypeSelection(const char *); + void ResolveVariables(); + private: std::vector GetSceneItemsByName(const SceneSelection &) const; diff --git a/plugins/base/utils/string-list.cpp b/plugins/base/utils/string-list.cpp index 6bdcbb975..fdc29ba03 100644 --- a/plugins/base/utils/string-list.cpp +++ b/plugins/base/utils/string-list.cpp @@ -39,6 +39,13 @@ bool StringList::Load(obs_data_t *obj, const char *name, return true; } +void StringList::ResolveVariables() +{ + for (auto &value : *this) { + value.ResolveVariables(); + } +} + StringListEdit::StringListEdit(QWidget *parent, const QString &addString, const QString &addStringDescription, int maxStringSize, bool allowEmtpy) diff --git a/plugins/base/utils/string-list.hpp b/plugins/base/utils/string-list.hpp index 97a41f74e..5d06c55c5 100644 --- a/plugins/base/utils/string-list.hpp +++ b/plugins/base/utils/string-list.hpp @@ -16,6 +16,7 @@ class StringList : public QList { const char *elementName = "string") const; bool Load(obs_data_t *obj, const char *name, const char *elementName = "string"); + void ResolveVariables(); friend class StringListEdit; }; diff --git a/plugins/midi/macro-action-midi.cpp b/plugins/midi/macro-action-midi.cpp index 3d1c49728..35701cbe3 100644 --- a/plugins/midi/macro-action-midi.cpp +++ b/plugins/midi/macro-action-midi.cpp @@ -23,7 +23,7 @@ bool MacroActionMidi::PerformAction() void MacroActionMidi::LogAction() const { - vblog(LOG_INFO, "send midi message \"%s\" to \"%s\"", + ablog(LOG_INFO, "send midi message \"%s\" to \"%s\"", _message.ToString().c_str(), _device.Name().c_str()); } @@ -48,6 +48,21 @@ std::string MacroActionMidi::GetShortDesc() const return _device.Name(); } +void MacroActionMidi::ResolveVariablesToFixedValues() +{ + _message.ResolveVariables(); +} + +std::shared_ptr MacroActionMidi::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionMidi::Copy() const +{ + return std::make_shared(*this); +} + MacroActionMidiEdit::MacroActionMidiEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), diff --git a/plugins/midi/macro-action-midi.hpp b/plugins/midi/macro-action-midi.hpp index c04fd97b4..dbee18105 100644 --- a/plugins/midi/macro-action-midi.hpp +++ b/plugins/midi/macro-action-midi.hpp @@ -15,11 +15,10 @@ class MacroActionMidi : public MacroAction { bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); std::string GetShortDesc() const; + void ResolveVariablesToFixedValues(); std::string GetId() const { return id; }; - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; MidiDevice _device; MidiMessage _message; diff --git a/plugins/midi/midi-helpers.cpp b/plugins/midi/midi-helpers.cpp index b484b3a0b..eee6820f4 100644 --- a/plugins/midi/midi-helpers.cpp +++ b/plugins/midi/midi-helpers.cpp @@ -91,6 +91,13 @@ std::string MidiMessage::ToString() const " Value: " + std::to_string(_value); } +void MidiMessage::ResolveVariables() +{ + _channel.ResolveVariables(); + _note.ResolveVariables(); + _value.ResolveVariables(); +} + std::string MidiMessage::ToString(const libremidi::message &msg) { return "Type: " + GetMidiType(msg) + diff --git a/plugins/midi/midi-helpers.hpp b/plugins/midi/midi-helpers.hpp index 5adc7b4b8..fbb4b2ada 100644 --- a/plugins/midi/midi-helpers.hpp +++ b/plugins/midi/midi-helpers.hpp @@ -38,6 +38,8 @@ class MidiMessage { int Note() const { return _note; } int Value() const { return _value; } + void ResolveVariables(); + private: // Values which don't appear for channel, note, and value will be used // to indicate whether this part of the message is optional and can be diff --git a/plugins/twitch/channel-selection.cpp b/plugins/twitch/channel-selection.cpp index 3430e0428..f8f2e4132 100644 --- a/plugins/twitch/channel-selection.cpp +++ b/plugins/twitch/channel-selection.cpp @@ -110,8 +110,9 @@ TwitchChannel::GetLiveInfo(const TwitchToken &token) return {}; } - httplib::Params params = { - {"first", "1"}, {"after", ""}, {"user_id", id}}; + httplib::Params params = {{"first", "1"}, + {"after", ""}, + {"user_id", id}}; auto result = SendGetRequest(token, "https://api.twitch.tv", "/helix/streams", params, true); if (result.status != 200) { @@ -151,8 +152,9 @@ std::optional TwitchChannel::GetInfo(const TwitchToken &token) return {}; } - httplib::Params params = { - {"first", "1"}, {"after", ""}, {"broadcaster_id", id}}; + httplib::Params params = {{"first", "1"}, + {"after", ""}, + {"broadcaster_id", id}}; auto result = SendGetRequest(token, "https://api.twitch.tv", "/helix/channels", params, true); if (result.status != 200) { @@ -183,6 +185,11 @@ std::optional TwitchChannel::GetInfo(const TwitchToken &token) return info; } +void TwitchChannel::ResolveVariables() +{ + _name.ResolveVariables(); +} + bool TwitchChannel::IsValid(const std::string &id) const { return id != "invalid" && !id.empty(); diff --git a/plugins/twitch/channel-selection.hpp b/plugins/twitch/channel-selection.hpp index 5c26121dd..175b751d0 100644 --- a/plugins/twitch/channel-selection.hpp +++ b/plugins/twitch/channel-selection.hpp @@ -48,11 +48,12 @@ struct ChannelInfo { struct TwitchChannel { void Load(obs_data_t *obj); void Save(obs_data_t *obj) const; - StringVariable GetName() const { return _name; }; + StringVariable GetName() const { return _name; } std::string GetUserID(const TwitchToken &token) const; bool IsValid(const std::string &id) const; std::optional GetLiveInfo(const TwitchToken &); std::optional GetInfo(const TwitchToken &); + void ResolveVariables(); private: StringVariable _name = ""; diff --git a/plugins/twitch/macro-action-twitch.cpp b/plugins/twitch/macro-action-twitch.cpp index 624518aea..12db0b6bd 100644 --- a/plugins/twitch/macro-action-twitch.cpp +++ b/plugins/twitch/macro-action-twitch.cpp @@ -13,6 +13,26 @@ bool MacroActionTwitch::_registered = MacroActionFactory::Register( {MacroActionTwitch::Create, MacroActionTwitchEdit::Create, "AdvSceneSwitcher.action.twitch"}); +void MacroActionTwitch::ResolveVariablesToFixedValues() +{ + _streamTitle.ResolveVariables(); + _markerDescription.ResolveVariables(); + _duration.ResolveVariables(); + _announcementMessage.ResolveVariables(); + _channel.ResolveVariables(); + _chatMessage.ResolveVariables(); +} + +std::shared_ptr MacroActionTwitch::Create(Macro *m) +{ + return std::make_shared(m); +} + +std::shared_ptr MacroActionTwitch::Copy() const +{ + return std::make_shared(*this); +} + std::string MacroActionTwitch::GetShortDesc() const { return GetWeakTwitchTokenName(_token); @@ -285,7 +305,7 @@ void MacroActionTwitch::LogAction() const { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, "performed action \"%s\" with token for \"%s\"", + ablog(LOG_INFO, "performed action \"%s\" with token for \"%s\"", it->second.c_str(), GetWeakTwitchTokenName(_token).c_str()); } else { diff --git a/plugins/twitch/macro-action-twitch.hpp b/plugins/twitch/macro-action-twitch.hpp index 25fa0708f..9771bf07a 100644 --- a/plugins/twitch/macro-action-twitch.hpp +++ b/plugins/twitch/macro-action-twitch.hpp @@ -15,10 +15,9 @@ namespace advss { class MacroActionTwitch : public MacroAction { public: MacroActionTwitch(Macro *m) : MacroAction(m) {} - static std::shared_ptr Create(Macro *m) - { - return std::make_shared(m); - } + static std::shared_ptr Create(Macro *m); + std::shared_ptr Copy() const; + std::string GetId() const { return id; }; std::string GetShortDesc() const; @@ -151,6 +150,7 @@ class MacroActionTwitch : public MacroAction { void LogAction() const; bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); + void ResolveVariablesToFixedValues(); void SetAction(Action); Action GetAction() const { return _action; } bool ActionIsSupportedByToken();