Compare commits

...

19 Commits

Author SHA1 Message Date
WarmUpTill
132d89b350 Fix virtual camera action selection causing a crash
The Create() and Copy() functions were not correctly implemented and
returned a nullptr
2024-03-06 12:53:43 +01:00
WarmUpTill
daf16357c9 Fix output volume check of audio condition not working
Only the percent based selection was not working properly since the
calculation was off by a factor of 100.
2024-03-03 20:54:15 +01:00
WarmUpTill
8080abc93c Fix crash when opening setting window 2024-03-03 20:54:15 +01:00
WarmUpTill
902715bd3e Save settings when switching to new macro
This should ensure that settings are saved more frequently and less data
is lost in case the plugin crashes with the settings dialog opened.
2024-03-03 20:54:15 +01:00
WarmUpTill
8271a6e8db CI: Don't attempt to rename files if not required 2024-03-02 16:38:24 +01:00
WarmUpTill
6c121a093b Add "Log" action
This action will allow you to write custom messages to the OBS log
2024-03-02 15:27:02 +01:00
WarmUpTill
ab0cce9eaa Add log level which prints performed actions 2024-03-02 15:27:02 +01:00
WarmUpTill
9acbead87b Update BUILDING.md 2024-03-02 15:27:02 +01:00
WarmUpTill
03e71e9183 Add support to resolve variables on action queue add 2024-03-02 15:27:02 +01:00
WarmUpTill
f8dadd38b4 Add ResolveVariables()
Settings will be set to fixed values based on the values of the
variables used.
2024-03-02 15:27:02 +01:00
WarmUpTill
2928775f5b Add option to resolve variables on queue add 2024-03-02 15:27:02 +01:00
WarmUpTill
673ac8078b Update lastVariableChange when using settings dialog to change value 2024-03-02 15:27:02 +01:00
WarmUpTill
234ae27205 Fix crash when running RunPostLoadSteps()
RunPostLoadSteps() could be called with "stale" post load steps as
RunPostLoadSteps() was never called when a copy of an action or
condition was created
2024-03-02 15:27:02 +01:00
WarmUpTill
a740a29798 Cleanup includes 2024-03-02 15:27:02 +01:00
WarmUpTill
341a58b8e4 Add window action
It allows to set the focus window and close windows.
Only supported on Windows for now.
2024-03-02 14:03:00 +01:00
Michael Kirsch
ba9a16e718 Force LF for formatter script for WSL 2024-02-29 20:31:50 +01:00
WarmUpTill
2b2bab8fbc Backup setting on exit to plugin config dir
Only one version of the settings file will be kept per scene collection
and plugin version combination
2024-02-28 12:53:02 +01:00
WarmUpTill
f50f31ec4c Allow stop of current macro when using run button 2024-02-26 20:56:26 +01:00
WarmUpTill
3a1c353ea3 Use git tag as version identifier in package scripts 2024-02-24 22:51:24 +01:00
160 changed files with 1799 additions and 420 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
/build-aux/*.zsh eol=lf
/build-aux/.functions/* eol=lf

View File

@@ -163,9 +163,13 @@ ${_usage_host:-}"
local product_name local product_name
local product_version local product_version
local git_tag="$(git describe --tags)"
read -r product_name product_version <<< \ read -r product_name product_version <<< \
"$(jq -r '. | {name, version} | join(" ")' ${buildspec_file})" "$(jq -r '. | {name, version} | join(" ")' ${buildspec_file})"
log_info "Using git tag as version identifier '${git_tag}'"
product_version="${git_tag}"
if [[ ${host_os} == macos ]] { if [[ ${host_os} == macos ]] {
autoload -Uz check_packages read_codesign read_codesign_installer read_codesign_pass autoload -Uz check_packages read_codesign read_codesign_installer read_codesign_pass
@@ -247,15 +251,21 @@ ${_usage_host:-}"
cmake --build build_${target##*-} --config ${config} -t package_source ${cmake_args} cmake --build build_${target##*-} --config ${config} -t package_source ${cmake_args}
popd popd
local output_name="${product_name}-${product_version}-${target##*-}-linux-gnu"
if (( package )) { if (( package )) {
log_group "Packaging ${product_name}..." log_group "Packaging ${product_name}..."
pushd ${project_root} pushd ${project_root}
cmake --build build_${target##*-} --config ${config} -t package ${cmake_args} cmake --build build_${target##*-} --config ${config} -t package ${cmake_args}
if [ ! -e ${project_root}/release/${output_name}.deb ]; then
mv ${project_root}/release/*.deb ${project_root}/release/${output_name}.deb
mv ${project_root}/release/*.ddeb ${project_root}/release/${output_name}.ddeb
fi
popd popd
} }
log_group "Archiving ${product_name}..." log_group "Archiving ${product_name}..."
local output_name="${product_name}-${product_version}-${target##*-}-linux-gnu"
local _tarflags='cJf' local _tarflags='cJf'
if (( _loglevel > 1 || ${+CI} )) _tarflags="v${_tarflags}" if (( _loglevel > 1 || ${+CI} )) _tarflags="v${_tarflags}"

View File

@@ -48,6 +48,10 @@ function Package {
$ProductName = $BuildSpec.name $ProductName = $BuildSpec.name
$ProductVersion = $BuildSpec.version $ProductVersion = $BuildSpec.version
$GitOutput = git describe --tags
Log-Information "Using git tag as version identifier '${GitOutput}'"
$ProductVersion = $GitOutput
$OutputName = "${ProductName}-${ProductVersion}-windows-${Target}" $OutputName = "${ProductName}-${ProductVersion}-windows-${Target}"
if ( ! $SkipDeps ) { if ( ! $SkipDeps ) {

0
.github/test vendored Normal file
View File

1
.gitignore vendored
View File

@@ -14,6 +14,7 @@
!/tests !/tests
!.clang-format !.clang-format
!.cmake-format.json !.cmake-format.json
!.gitattributes
!.gitignore !.gitignore
!BUILDING.md !BUILDING.md
!buildspec.json !buildspec.json

View File

@@ -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**) - 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**) - 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) ## 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/: Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
``` ```
cd 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: First you will need to clone the plugin sources by running the following command:
``` ```
git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git 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: For example, on Windows you might want to run this command:
``` ```
cd SceneSwitcher
cmake --preset windows-x64 cmake --preset windows-x64
``` ```
Next, you can build the plugin and install the files into a folder named release using the following commands: 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 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 | | Platform | Command |
| ----------- | ----------- | | ----------- | ----------- |
@@ -83,10 +85,10 @@ You can rely on the CI scripts to build the dependencies for you, although it is
# Contributing # 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`. 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 condition
Macro conditions should inherit from the `MacroCondition` class and must implement the following functions: Macro conditions should inherit from the `MacroCondition` class and must implement the following functions:
@@ -97,12 +99,12 @@ public:
MacroConditionExample(Macro *m) : MacroCondition(m) {} MacroConditionExample(Macro *m) : MacroCondition(m) {}
// This function should perform the condition check // This function should perform the condition check
bool CheckCondition(); 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 // For example called on OBS shutdown
bool Save(obs_data_t *obj); bool Save(obs_data_t *data);
// This function should load the condition data from "obj" // This function should load the condition data from "data"
// For example called on OBS startup // 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 // This function should return a unique id for this condition type
// The _id is defined below // The _id is defined below
std::string GetId() { return _id; }; std::string GetId() { return _id; };
@@ -120,7 +122,7 @@ private:
static const std::string _id; 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()`) It will be called whenever a new condition MacroConditionExample is created. (See `MacroConditionFactory::Register()`)
``` ```
class MacroConditionExampleEdit : public QWidget { class MacroConditionExampleEdit : public QWidget {
@@ -151,7 +153,7 @@ bool MacroConditionExample::_registered = MacroConditionFactory::Register(
MacroConditionExample::id, // Unique string identifying this condition type MacroConditionExample::id, // Unique string identifying this condition type
{ {
MacroConditionExample::Create, // Function called to create the object performing the condition 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) "AdvSceneSwitcher.condition.example", // User facing name of the condition type (will be translated)
true // Condition type supports duration modifiers (default true) true // Condition type supports duration modifiers (default true)
} }
@@ -167,16 +169,18 @@ The differences are highlighted in the comments below.
class MacroActionExample : public MacroAction { class MacroActionExample : public MacroAction {
public: public:
MacroActionExample(Macro *m) : MacroAction(m) {} MacroActionExample(Macro *m) : MacroAction(m) {}
static std::shared_ptr<MacroAction> Create(Macro *m);
// Used to create a copy of the action (used for action queues)
std::shared_ptr<MacroAction> Copy() const;
// This function should perform the action // This function should perform the action
// If false is returned the macro will aborted // If false is returned the macro will aborted
bool PerformAction(); bool PerformAction();
bool Save(obs_data_t *obj); bool Save(obs_data_t *data);
bool Load(obs_data_t *obj); bool Load(obs_data_t *data);
std::string GetId() { return _id; }; std::string GetId() { return _id; };
static std::shared_ptr<MacroAction> Create(Macro *m) // Optional:
{ // Might be called when action is inserted to action queue
return std::make_shared<MacroActionExample>(m); void ResolveVariablesToFixedValues();
}
private: private:
static bool _registered; static bool _registered;
@@ -207,11 +211,11 @@ MacroActionFactory::Register(
MacroActionExample::id, // Unique string identifying this action type MacroActionExample::id, // Unique string identifying this action type
{ {
MacroActionExample::Create, // Function called to create the object performing the action 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 "AdvSceneSwitcher.action.example" // User facing name of the action type
} }
); );
``` ```
## External dependencies ## 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. 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. For example, `plugins/video` will only be loaded if the `OpenCV` dependencies are met.

View File

@@ -147,6 +147,8 @@ target_sources(
${LIB_NAME} ${LIB_NAME}
PRIVATE lib/utils/action-queue.cpp PRIVATE lib/utils/action-queue.cpp
lib/utils/action-queue.hpp lib/utils/action-queue.hpp
lib/utils/backup.cpp
lib/utils/backup.hpp
lib/utils/curl-helper.cpp lib/utils/curl-helper.cpp
lib/utils/curl-helper.hpp lib/utils/curl-helper.hpp
lib/utils/duration-control.cpp lib/utils/duration-control.cpp

View File

@@ -75,7 +75,7 @@ AdvSceneSwitcher.macroTab.edit.action="Aktions-Typ:"
AdvSceneSwitcher.macroTab.add="Neues Makro hinzufügen" AdvSceneSwitcher.macroTab.add="Neues Makro hinzufügen"
AdvSceneSwitcher.macroTab.name="Name:" AdvSceneSwitcher.macroTab.name="Name:"
AdvSceneSwitcher.macroTab.run="Makro ausführen" AdvSceneSwitcher.macroTab.run="Makro ausführen"
AdvSceneSwitcher.macroTab.runFail="Ausführen von \"%1\" fehlgeschlagen!\nEntweder ist eine der Aktionen fehlgeschlagen oder das Makro wird bereits ausgeführt." AdvSceneSwitcher.macroTab.runFail="Ausführen von \"%1\" fehlgeschlagen!\nEntweder ist eine der Aktionen fehlgeschlagen oder das Makro wird bereits ausgeführt.\nSoll die aktuelle Ausführung gestoppt werden?"
AdvSceneSwitcher.macroTab.runInParallel="Parallel zu anderen Makros ausführen" AdvSceneSwitcher.macroTab.runInParallel="Parallel zu anderen Makros ausführen"
AdvSceneSwitcher.macroTab.onChange="Nur bei Änderung ausführen" AdvSceneSwitcher.macroTab.onChange="Nur bei Änderung ausführen"
AdvSceneSwitcher.macroTab.defaultname="Makro %1" AdvSceneSwitcher.macroTab.defaultname="Makro %1"

View File

@@ -26,6 +26,10 @@ AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Switch to an
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Switch to:" AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Switch to:"
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="After performing actions skip performing actions for" 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.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.verboseLogging="Enable verbose logging"
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size" AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size"
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Show system tray notifications" AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Show system tray notifications"
@@ -94,7 +98,7 @@ AdvSceneSwitcher.macroTab.name="Name:"
AdvSceneSwitcher.macroTab.run="Run macro" AdvSceneSwitcher.macroTab.run="Run macro"
AdvSceneSwitcher.macroTab.run.tooltip="Run all macro actions regardless of condition.\nIf else actions are available, hold Shift and click the button to execute them instead." AdvSceneSwitcher.macroTab.run.tooltip="Run all macro actions regardless of condition.\nIf else actions are available, hold Shift and click the button to execute them instead."
AdvSceneSwitcher.macroTab.runElse="Run macro (else)" AdvSceneSwitcher.macroTab.runElse="Run macro (else)"
AdvSceneSwitcher.macroTab.runFail="Running \"%1\" failed!\nEither one of the actions failed or the macro is running already." AdvSceneSwitcher.macroTab.runFail="Running \"%1\" failed!\nEither one of the actions failed or the macro is running already.\nDo you want to stop it?"
AdvSceneSwitcher.macroTab.runInParallel="Run macro in parallel to other macros" AdvSceneSwitcher.macroTab.runInParallel="Run macro in parallel to other macros"
AdvSceneSwitcher.macroTab.onChange="Perform actions only on condition change" AdvSceneSwitcher.macroTab.onChange="Perform actions only on condition change"
AdvSceneSwitcher.macroTab.defaultname="Macro %1" AdvSceneSwitcher.macroTab.defaultname="Macro %1"
@@ -962,6 +966,15 @@ AdvSceneSwitcher.action.queue.type.start="Start"
AdvSceneSwitcher.action.queue.type.stop="Stop" AdvSceneSwitcher.action.queue.type.stop="Stop"
AdvSceneSwitcher.action.queue.entry.add="{{actions}}actions of macro{{macros}}to queue{{queues}}" AdvSceneSwitcher.action.queue.entry.add="{{actions}}actions of macro{{macros}}to queue{{queues}}"
AdvSceneSwitcher.action.queue.entry.other="{{actions}}queue{{queues}}" AdvSceneSwitcher.action.queue.entry.other="{{actions}}queue{{queues}}"
AdvSceneSwitcher.action.window="Window"
AdvSceneSwitcher.action.window.type.setFocusWindow="Focus window"
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 ; Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Start the Advanced Scene Switcher" AdvSceneSwitcher.hotkey.startSwitcherHotkey="Start the Advanced Scene Switcher"
@@ -1034,6 +1047,7 @@ AdvSceneSwitcher.actionQueues.configure="Configure action queue settings"
AdvSceneSwitcher.actionQueues.invalid="Invalid action queue selection" AdvSceneSwitcher.actionQueues.invalid="Invalid action queue selection"
AdvSceneSwitcher.actionQueues.name="Name:" AdvSceneSwitcher.actionQueues.name="Name:"
AdvSceneSwitcher.actionQueues.runOnStartup="Run action queue when starting the plugin" 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.running="Queue is running"
AdvSceneSwitcher.actionQueues.stopped="Queue is stopped" AdvSceneSwitcher.actionQueues.stopped="Queue is stopped"
AdvSceneSwitcher.actionQueues.start="Start action queue" AdvSceneSwitcher.actionQueues.start="Start action queue"

View File

@@ -72,7 +72,6 @@ AdvSceneSwitcher.macroTab.edit.action="Tipo de acción:"
AdvSceneSwitcher.macroTab.add="Agregar nueva macro" AdvSceneSwitcher.macroTab.add="Agregar nueva macro"
AdvSceneSwitcher.macroTab.name="Nombre:" AdvSceneSwitcher.macroTab.name="Nombre:"
AdvSceneSwitcher.macroTab.run="Ejecutar macro" AdvSceneSwitcher.macroTab.run="Ejecutar macro"
AdvSceneSwitcher.macroTab.runFail="Error al ejecutar \"%1\" si se ha producido un error en una de las acciones o si la macro ya se está ejecutando."
AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros" AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros"
AdvSceneSwitcher.macroTab.onChange="Realizar acciones solo en el cambio de condición" AdvSceneSwitcher.macroTab.onChange="Realizar acciones solo en el cambio de condición"
AdvSceneSwitcher.macroTab.defaultname="Macro %1" AdvSceneSwitcher.macroTab.defaultname="Macro %1"

View File

@@ -78,7 +78,6 @@ AdvSceneSwitcher.macroTab.edit.action="Type d'action :"
AdvSceneSwitcher.macroTab.add="Ajouter une nouvelle macro" AdvSceneSwitcher.macroTab.add="Ajouter une nouvelle macro"
AdvSceneSwitcher.macroTab.name="Nom :" AdvSceneSwitcher.macroTab.name="Nom :"
AdvSceneSwitcher.macroTab.run="Exécuter la macro" AdvSceneSwitcher.macroTab.run="Exécuter la macro"
AdvSceneSwitcher.macroTab.runFail="Échec de l'exécution de \"%1\" !\nSoit l'une des actions a échoué, soit la macro est déjà en cours d'exécution."
AdvSceneSwitcher.macroTab.runInParallel="Exécuter la macro en parallèle avec d'autres macros" AdvSceneSwitcher.macroTab.runInParallel="Exécuter la macro en parallèle avec d'autres macros"
AdvSceneSwitcher.macroTab.onChange="Exécuter des actions uniquement en cas de changement de condition" AdvSceneSwitcher.macroTab.onChange="Exécuter des actions uniquement en cas de changement de condition"
AdvSceneSwitcher.macroTab.defaultname="Macro %1" AdvSceneSwitcher.macroTab.defaultname="Macro %1"

View File

@@ -72,7 +72,6 @@ AdvSceneSwitcher.macroTab.edit.action="Eylem türü:"
AdvSceneSwitcher.macroTab.add="Yeni Makro ekle" AdvSceneSwitcher.macroTab.add="Yeni Makro ekle"
AdvSceneSwitcher.macroTab.name="İsim:" AdvSceneSwitcher.macroTab.name="İsim:"
AdvSceneSwitcher.macroTab.run="Makro Çalıştırma" AdvSceneSwitcher.macroTab.run="Makro Çalıştırma"
AdvSceneSwitcher.macroTab.runFail="\"%1\" çalıştırılamadı!\n Eylemlerden biri başarısız oldu veya makro zaten çalışıyor."
AdvSceneSwitcher.macroTab.runInParallel="Makroyu diğer makrolara paralel olarak çalıştırın" AdvSceneSwitcher.macroTab.runInParallel="Makroyu diğer makrolara paralel olarak çalıştırın"
AdvSceneSwitcher.macroTab.onChange="Eylemleri yalnızca koşul değişikliğinde gerçekleştirin" AdvSceneSwitcher.macroTab.onChange="Eylemleri yalnızca koşul değişikliğinde gerçekleştirin"
AdvSceneSwitcher.macroTab.defaultname="Makro %1" AdvSceneSwitcher.macroTab.defaultname="Makro %1"

View File

@@ -77,7 +77,6 @@ AdvSceneSwitcher.macroTab.edit.action="动作类型:"
AdvSceneSwitcher.macroTab.add="添加新宏" AdvSceneSwitcher.macroTab.add="添加新宏"
AdvSceneSwitcher.macroTab.name="名称:" AdvSceneSwitcher.macroTab.name="名称:"
AdvSceneSwitcher.macroTab.run="运行宏" AdvSceneSwitcher.macroTab.run="运行宏"
AdvSceneSwitcher.macroTab.runFail="运行 \"%1\" 失败!\n其中一个操作失败或者宏已在运行."
AdvSceneSwitcher.macroTab.runInParallel="与其他宏同时运行宏" AdvSceneSwitcher.macroTab.runInParallel="与其他宏同时运行宏"
AdvSceneSwitcher.macroTab.onChange="仅在条件更改时执行操作" AdvSceneSwitcher.macroTab.onChange="仅在条件更改时执行操作"
AdvSceneSwitcher.macroTab.defaultname="宏 %1" AdvSceneSwitcher.macroTab.defaultname="宏 %1"

View File

@@ -163,12 +163,31 @@
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_52"> <layout class="QHBoxLayout" name="horizontalLayout_52">
<item> <item>
<widget class="QCheckBox" name="verboseLogging"> <widget class="QLabel" name="label_21">
<property name="text"> <property name="text">
<string>AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging</string> <string>AdvSceneSwitcher.generalTab.generalBehavior.logLevel</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QComboBox" name="logLevel">
<item>
<property name="text">
<string>AdvSceneSwitcher.generalTab.generalBehavior.logLevel.default</string>
</property>
</item>
<item>
<property name="text">
<string>AdvSceneSwitcher.generalTab.generalBehavior.logLevel.printActions</string>
</property>
</item>
<item>
<property name="text">
<string>AdvSceneSwitcher.generalTab.generalBehavior.logLevel.verbose</string>
</property>
</item>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_49"> <spacer name="horizontalSpacer_49">
<property name="orientation"> <property name="orientation">
@@ -5078,7 +5097,7 @@
<tabstop>checkInterval</tabstop> <tabstop>checkInterval</tabstop>
<tabstop>startupBehavior</tabstop> <tabstop>startupBehavior</tabstop>
<tabstop>autoStartEvent</tabstop> <tabstop>autoStartEvent</tabstop>
<tabstop>verboseLogging</tabstop> <tabstop>logLevel</tabstop>
<tabstop>saveWindowGeo</tabstop> <tabstop>saveWindowGeo</tabstop>
<tabstop>showTrayNotifications</tabstop> <tabstop>showTrayNotifications</tabstop>
<tabstop>uiHintsDisable</tabstop> <tabstop>uiHintsDisable</tabstop>

View File

@@ -1,4 +1,5 @@
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "backup.hpp"
#include "curl-helper.hpp" #include "curl-helper.hpp"
#include "log-helper.hpp" #include "log-helper.hpp"
#include "macro-helpers.hpp" #include "macro-helpers.hpp"
@@ -17,7 +18,6 @@
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
#include <QAction> #include <QAction>
#include <QDirIterator> #include <QDirIterator>
#include <QFileDialog>
#include <QMainWindow> #include <QMainWindow>
#include <QTextStream> #include <QTextStream>
#include <regex> #include <regex>
@@ -143,7 +143,6 @@ bool AdvSceneSwitcher::eventFilter(QObject *obj, QEvent *event)
/****************************************************************************** /******************************************************************************
* Saving and loading * Saving and loading
******************************************************************************/ ******************************************************************************/
static void AskForBackup(const QString &json);
static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
{ {
@@ -192,34 +191,6 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
} }
} }
static void AskForBackup(const QString &json)
{
const bool backupWasConfirmed = DisplayMessage(
obs_module_text("AdvSceneSwitcher.askBackup"), true, false);
if (!backupWasConfirmed) {
return;
}
QString path = QFileDialog::getSaveFileName(
nullptr,
obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle"),
GetDefaultSettingsSaveLocation(),
obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"));
if (path.isEmpty()) {
return;
}
QFile file(path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
auto out = QTextStream(&file);
out << json;
}
/****************************************************************************** /******************************************************************************
* Main switcher thread * Main switcher thread
******************************************************************************/ ******************************************************************************/
@@ -635,6 +606,8 @@ static void handleShutdown()
// TODO: Look for a way to possibly resolve this // TODO: Look for a way to possibly resolve this
obs_frontend_save(); obs_frontend_save();
} }
BackupSettingsOfCurrentVersion();
} }
static void handleSceneCollectionChanging() static void handleSceneCollectionChanging()

View File

@@ -55,6 +55,7 @@ public slots:
void NoMatchDelayDurationChanged(const Duration &); void NoMatchDelayDurationChanged(const Duration &);
void CooldownDurationChanged(const Duration &); void CooldownDurationChanged(const Duration &);
void on_startupBehavior_currentIndexChanged(int index); void on_startupBehavior_currentIndexChanged(int index);
void on_logLevel_currentIndexChanged(int index);
void on_autoStartEvent_currentIndexChanged(int index); void on_autoStartEvent_currentIndexChanged(int index);
void on_noMatchSwitchScene_currentTextChanged(const QString &text); void on_noMatchSwitchScene_currentTextChanged(const QString &text);
void on_checkInterval_valueChanged(int value); void on_checkInterval_valueChanged(int value);
@@ -62,7 +63,6 @@ public slots:
void on_tabWidget_currentChanged(int index); void on_tabWidget_currentChanged(int index);
void on_exportSettings_clicked(); void on_exportSettings_clicked();
void on_importSettings_clicked(); void on_importSettings_clicked();
void on_verboseLogging_stateChanged(int state);
void on_saveWindowGeo_stateChanged(int state); void on_saveWindowGeo_stateChanged(int state);
void on_showTrayNotifications_stateChanged(int state); void on_showTrayNotifications_stateChanged(int state);
void on_uiHintsDisable_stateChanged(int state); void on_uiHintsDisable_stateChanged(int state);

View File

@@ -112,6 +112,14 @@ void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
static_cast<SwitcherData::StartupBehavior>(index); static_cast<SwitcherData::StartupBehavior>(index);
} }
void AdvSceneSwitcher::on_logLevel_currentIndexChanged(int value)
{
if (loading) {
return;
}
switcher->logLevel = static_cast<SwitcherData::LogLevel>(value);
}
void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index) void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index)
{ {
if (loading) { if (loading) {
@@ -157,15 +165,6 @@ void AdvSceneSwitcher::closeEvent(QCloseEvent *)
obs_frontend_save(); obs_frontend_save();
} }
void AdvSceneSwitcher::on_verboseLogging_stateChanged(int state)
{
if (loading) {
return;
}
switcher->verbose = state;
}
void AdvSceneSwitcher::on_saveWindowGeo_stateChanged(int state) void AdvSceneSwitcher::on_saveWindowGeo_stateChanged(int state)
{ {
if (loading) { if (loading) {
@@ -598,7 +597,7 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
obs_data_set_int(obj, "autoStartEvent", obs_data_set_int(obj, "autoStartEvent",
static_cast<int>(autoStartEvent)); static_cast<int>(autoStartEvent));
obs_data_set_bool(obj, "verbose", verbose); obs_data_set_int(obj, "logLevel", static_cast<int>(logLevel));
obs_data_set_bool(obj, "showSystemTrayNotifications", obs_data_set_bool(obj, "showSystemTrayNotifications",
showSystemTrayNotifications); showSystemTrayNotifications);
obs_data_set_bool(obj, "disableHints", disableHints); obs_data_set_bool(obj, "disableHints", disableHints);
@@ -649,7 +648,7 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
autoStartEvent = autoStartEvent =
static_cast<AutoStart>(obs_data_get_int(obj, "autoStartEvent")); static_cast<AutoStart>(obs_data_get_int(obj, "autoStartEvent"));
verbose = obs_data_get_bool(obj, "verbose"); logLevel = static_cast<LogLevel>(obs_data_get_int(obj, "logLevel"));
showSystemTrayNotifications = showSystemTrayNotifications =
obs_data_get_bool(obj, "showSystemTrayNotifications"); obs_data_get_bool(obj, "showSystemTrayNotifications");
disableHints = obs_data_get_bool(obj, "disableHints"); disableHints = obs_data_get_bool(obj, "disableHints");
@@ -940,7 +939,8 @@ void AdvSceneSwitcher::SetupGeneralTab()
SIGNAL(DurationChanged(const Duration &)), this, SIGNAL(DurationChanged(const Duration &)), this,
SLOT(CooldownDurationChanged(const Duration &))); SLOT(CooldownDurationChanged(const Duration &)));
ui->verboseLogging->setChecked(switcher->verbose); ui->logLevel->setCurrentIndex(static_cast<int>(switcher->logLevel));
ui->saveWindowGeo->setChecked(switcher->saveWindowGeo); ui->saveWindowGeo->setChecked(switcher->saveWindowGeo);
ui->showTrayNotifications->setChecked( ui->showTrayNotifications->setChecked(
switcher->showSystemTrayNotifications); switcher->showSystemTrayNotifications);

View File

@@ -104,7 +104,7 @@ void SwitcherData::checkAudioSwitchFallback(OBSWeakSource &scene,
scene = audioFallback.getScene(); scene = audioFallback.getScene();
transition = audioFallback.transition; transition = audioFallback.transition;
if (verbose) { if (VerboseLoggingEnabled()) {
audioFallback.logMatch(); audioFallback.logMatch();
} }
} }
@@ -165,7 +165,7 @@ bool SwitcherData::checkAudioSwitch(OBSWeakSource &scene,
transition = s.transition; transition = s.transition;
match = true; match = true;
if (verbose) { if (VerboseLoggingEnabled()) {
s.logMatch(); s.logMatch();
} }

View File

@@ -119,7 +119,7 @@ bool SwitcherData::checkExeSwitch(OBSWeakSource &scene,
scene = s.getScene(); scene = s.getScene();
transition = s.transition; transition = s.transition;
if (verbose) { if (VerboseLoggingEnabled()) {
s.logMatch(); s.logMatch();
} }
break; break;

View File

@@ -274,7 +274,7 @@ bool SwitcherData::checkFileContent(OBSWeakSource &scene,
transition = s.transition; transition = s.transition;
match = true; match = true;
if (verbose) { if (VerboseLoggingEnabled()) {
s.logMatch(); s.logMatch();
} }
break; break;

View File

@@ -53,7 +53,7 @@ bool SwitcherData::checkIdleSwitch(OBSWeakSource &scene,
match = true; match = true;
idleData.alreadySwitched = true; idleData.alreadySwitched = true;
if (verbose) { if (VerboseLoggingEnabled()) {
idleData.logMatch(); idleData.logMatch();
} }
} else { } else {

View File

@@ -193,7 +193,7 @@ bool SwitcherData::checkMediaSwitch(OBSWeakSource &scene,
scene = mediaSwitch.getScene(); scene = mediaSwitch.getScene();
transition = mediaSwitch.transition; transition = mediaSwitch.transition;
if (verbose) { if (VerboseLoggingEnabled()) {
mediaSwitch.logMatch(); mediaSwitch.logMatch();
} }
} }

View File

@@ -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()); 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"; std::string ret = "message ok";
auto transition = GetWeakTransitionByName(transitionName.c_str()); auto transition = GetWeakTransitionByName(transitionName.c_str());
if (switcher->verbose && !transition) { if (VerboseLoggingEnabled() && !transition) {
ret += " - ignoring invalid transition: '" + transitionName + ret += " - ignoring invalid transition: '" + transitionName +
"'"; "'";
} }
@@ -481,7 +481,7 @@ void WSClient::onMessage(connection_hdl hdl, client::message_ptr message)
errorCodeMessage.c_str()); errorCodeMessage.c_str());
} }
if (switcher->verbose) { if (VerboseLoggingEnabled()) {
blog(LOG_INFO, "client sent message:\n%s", response.c_str()); blog(LOG_INFO, "client sent message:\n%s", response.c_str());
} }
} }

View File

@@ -76,7 +76,7 @@ bool SwitcherData::checkRandom(OBSWeakSource &scene, OBSWeakSource &transition,
lastRandomScene = r.scene; lastRandomScene = r.scene;
lastRandomSceneGroup = r.group; lastRandomSceneGroup = r.group;
if (verbose) { if (VerboseLoggingEnabled()) {
r.logMatch(); r.logMatch();
} }
break; break;

View File

@@ -183,7 +183,7 @@ bool SwitcherData::checkScreenRegionSwitch(OBSWeakSource &scene,
transition = s.transition; transition = s.transition;
minRegionSize = regionSize; minRegionSize = regionSize;
if (verbose) { if (VerboseLoggingEnabled()) {
s.logMatch(); s.logMatch();
} }
break; break;

View File

@@ -225,13 +225,13 @@ bool SwitcherData::checkSceneSequence(OBSWeakSource &scene,
scene = s.getScene(); scene = s.getScene();
transition = s.transition; transition = s.transition;
setPrevSceneAfterLinger = s.usePreviousScene; setPrevSceneAfterLinger = s.usePreviousScene;
if (verbose) { if (VerboseLoggingEnabled()) {
s.logMatch(); s.logMatch();
} }
} }
s.advanceActiveSequence(); s.advanceActiveSequence();
if (verbose) { if (VerboseLoggingEnabled()) {
s.logAdvanceSequence(); s.logAdvanceSequence();
} }

View File

@@ -142,7 +142,7 @@ bool SwitcherData::checkTimeSwitch(OBSWeakSource &scene,
transition = s.transition; transition = s.transition;
match = true; match = true;
if (verbose) { if (VerboseLoggingEnabled()) {
s.logMatch(); s.logMatch();
} }
break; break;

View File

@@ -168,7 +168,7 @@ void SwitcherData::checkDefaultSceneTransitions()
for (auto &t : defaultSceneTransitions) { for (auto &t : defaultSceneTransitions) {
if (t.checkMatch(currentScene)) { if (t.checkMatch(currentScene)) {
if (verbose) { if (VerboseLoggingEnabled()) {
t.logMatch(); t.logMatch();
} }
t.setTransition(); t.setTransition();
@@ -427,7 +427,8 @@ DefTransitionSwitchWidget::DefTransitionSwitchWidget(QWidget *parent,
{ {
QHBoxLayout *mainLayout = new QHBoxLayout; QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = { std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{scenes}}", scenes}, {"{{transitions}}", transitions}}; {"{{scenes}}", scenes},
{"{{transitions}}", transitions}};
PlaceWidgets( PlaceWidgets(
obs_module_text( obs_module_text(
"AdvSceneSwitcher.transitionTab.defaultTransitionEntry"), "AdvSceneSwitcher.transitionTab.defaultTransitionEntry"),

View File

@@ -148,7 +148,7 @@ bool SwitcherData::checkVideoSwitch(OBSWeakSource &scene,
match = true; match = true;
scene = s.getScene(); scene = s.getScene();
transition = s.transition; transition = s.transition;
if (verbose) { if (VerboseLoggingEnabled()) {
s.logMatch(); s.logMatch();
} }
} }

View File

@@ -249,7 +249,7 @@ bool SwitcherData::checkWindowTitleSwitch(OBSWeakSource &scene,
} }
if (match) { if (match) {
if (verbose) { if (VerboseLoggingEnabled()) {
s.logMatch(); s.logMatch();
} }
break; break;

View File

@@ -3,6 +3,7 @@
#include "macro-helpers.hpp" #include "macro-helpers.hpp"
#include "macro-properties.hpp" #include "macro-properties.hpp"
#include "macro.hpp" #include "macro.hpp"
#include "plugin-state-helpers.hpp"
#include "section.hpp" #include "section.hpp"
#include "switch-button.hpp" #include "switch-button.hpp"
@@ -88,6 +89,7 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
*_entryData = MacroActionFactory::Create(id, macro); *_entryData = MacroActionFactory::Create(id, macro);
(*_entryData)->SetIndex(idx); (*_entryData)->SetIndex(idx);
(*_entryData)->PostLoad(); (*_entryData)->PostLoad();
RunPostLoadSteps();
} }
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData); auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)), QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
@@ -185,9 +187,10 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
auto data = obs_data_create(); auto data = obs_data_create();
macro->Actions().at(idx - 1)->Save(data); macro->Actions().at(idx - 1)->Save(data);
macro->Actions().at(idx)->Load(data); macro->Actions().at(idx)->Load(data);
macro->Actions().at(idx)->PostLoad();
obs_data_release(data); obs_data_release(data);
} }
macro->Actions().at(idx)->PostLoad();
RunPostLoadSteps();
macro->UpdateActionIndices(); macro->UpdateActionIndices();
ui->actionsList->Insert( ui->actionsList->Insert(
idx, idx,
@@ -475,6 +478,7 @@ void AdvSceneSwitcher::AddMacroElseAction(int idx)
macro->ElseActions().at(idx)->Load(data); macro->ElseActions().at(idx)->Load(data);
} }
macro->ElseActions().at(idx)->PostLoad(); macro->ElseActions().at(idx)->PostLoad();
RunPostLoadSteps();
macro->UpdateElseActionIndices(); macro->UpdateElseActionIndices();
ui->elseActionsList->Insert( ui->elseActionsList->Insert(
idx, new MacroActionEdit( idx, new MacroActionEdit(

View File

@@ -88,32 +88,32 @@ void MacroActionMacro::LogAction() const
} }
switch (_action) { switch (_action) {
case Action::PAUSE: case Action::PAUSE:
vblog(LOG_INFO, "paused \"%s\"", macro->Name().c_str()); ablog(LOG_INFO, "paused \"%s\"", macro->Name().c_str());
break; break;
case Action::UNPAUSE: case Action::UNPAUSE:
vblog(LOG_INFO, "unpaused \"%s\"", macro->Name().c_str()); ablog(LOG_INFO, "unpaused \"%s\"", macro->Name().c_str());
break; break;
case Action::RESET_COUNTER: case Action::RESET_COUNTER:
vblog(LOG_INFO, "reset counter for \"%s\"", ablog(LOG_INFO, "reset counter for \"%s\"",
macro->Name().c_str()); macro->Name().c_str());
break; break;
case Action::RUN: case Action::RUN:
vblog(LOG_INFO, "run nested macro \"%s\"", ablog(LOG_INFO, "run nested macro \"%s\"",
macro->Name().c_str()); macro->Name().c_str());
break; break;
case Action::STOP: case Action::STOP:
vblog(LOG_INFO, "stopped macro \"%s\"", macro->Name().c_str()); ablog(LOG_INFO, "stopped macro \"%s\"", macro->Name().c_str());
break; break;
case Action::DISABLE_ACTION: 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()); _actionIndex.GetValue(), macro->Name().c_str());
break; break;
case Action::ENABLE_ACTION: 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()); _actionIndex.GetValue(), macro->Name().c_str());
break; break;
case Action::TOGGLE_ACTION: 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()); _actionIndex.GetValue(), macro->Name().c_str());
break; break;
default: default:
@@ -145,6 +145,21 @@ std::string MacroActionMacro::GetShortDesc() const
return _macro.Name(); return _macro.Name();
} }
std::shared_ptr<MacroAction> MacroActionMacro::Create(Macro *m)
{
return std::make_shared<MacroActionMacro>(m);
}
std::shared_ptr<MacroAction> MacroActionMacro::Copy() const
{
return std::make_shared<MacroActionMacro>(*this);
}
void MacroActionMacro::ResolveVariablesToFixedValues()
{
_actionIndex.ResolveVariables();
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (auto entry : actionTypes) {

View File

@@ -16,10 +16,9 @@ public:
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc() const; std::string GetShortDesc() const;
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionMacro>(m); void ResolveVariablesToFixedValues();
}
enum class Action { enum class Action {
PAUSE, PAUSE,

View File

@@ -69,20 +69,20 @@ void MacroActionQueue::LogAction() const
} }
switch (_action) { switch (_action) {
case Action::ADD_TO_QUEUE: 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(), GetMacroName(macro.get()).c_str(),
GetActionQueueName(_queue).c_str()); GetActionQueueName(_queue).c_str());
break; break;
case Action::START_QUEUE: case Action::START_QUEUE:
vblog(LOG_INFO, "start queue \"%s\"", ablog(LOG_INFO, "start queue \"%s\"",
GetActionQueueName(_queue).c_str()); GetActionQueueName(_queue).c_str());
break; break;
case Action::STOP_QUEUE: case Action::STOP_QUEUE:
vblog(LOG_INFO, "stop queue \"%s\"", ablog(LOG_INFO, "stop queue \"%s\"",
GetActionQueueName(_queue).c_str()); GetActionQueueName(_queue).c_str());
break; break;
case Action::CLEAR_QUEUE: case Action::CLEAR_QUEUE:
vblog(LOG_INFO, "cleared queue \"%s\"", ablog(LOG_INFO, "cleared queue \"%s\"",
GetActionQueueName(_queue).c_str()); GetActionQueueName(_queue).c_str());
break; break;
default: default:
@@ -114,6 +114,16 @@ std::string MacroActionQueue::GetShortDesc() const
return GetActionQueueName(_queue); return GetActionQueueName(_queue);
} }
std::shared_ptr<MacroAction> MacroActionQueue::Create(Macro *m)
{
return std::make_shared<MacroActionQueue>(m);
}
std::shared_ptr<MacroAction> MacroActionQueue::Copy() const
{
return std::make_shared<MacroActionQueue>(*this);
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (const auto &[_, name] : actionTypes) { for (const auto &[_, name] : actionTypes) {

View File

@@ -16,10 +16,8 @@ public:
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc() const; std::string GetShortDesc() const;
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionQueue>(m);
}
enum class Action { enum class Action {
ADD_TO_QUEUE, ADD_TO_QUEUE,

View File

@@ -198,7 +198,8 @@ void MacroActionVariable::SetToSceneItemName(Variable *var)
struct AskForInputParams { struct AskForInputParams {
AskForInputParams(const QString &prompt_, const QString &placeholder_) AskForInputParams(const QString &prompt_, const QString &placeholder_)
: prompt(prompt_), placeholder(placeholder_){}; : prompt(prompt_),
placeholder(placeholder_){};
QString prompt; QString prompt;
QString placeholder; QString placeholder;
std::optional<std::string> result; std::optional<std::string> result;
@@ -422,6 +423,16 @@ std::string MacroActionVariable::GetShortDesc() const
return GetWeakVariableName(_variable); return GetWeakVariableName(_variable);
} }
std::shared_ptr<MacroAction> MacroActionVariable::Create(Macro *m)
{
return std::make_shared<MacroActionVariable>(m);
}
std::shared_ptr<MacroAction> MacroActionVariable::Copy() const
{
return std::make_shared<MacroActionVariable>(*this);
}
void MacroActionVariable::SetSegmentIndexValue(int value) void MacroActionVariable::SetSegmentIndexValue(int value)
{ {
DecrementCurrentSegmentVariableRef(); DecrementCurrentSegmentVariableRef();
@@ -485,6 +496,19 @@ int MacroActionVariable::GetSegmentIndexValue() const
return -1; 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() void MacroActionVariable::DecrementCurrentSegmentVariableRef()
{ {
auto segment = _macroSegment.lock(); auto segment = _macroSegment.lock();

View File

@@ -20,12 +20,11 @@ public:
bool PostLoad() override; bool PostLoad() override;
std::string GetShortDesc() const; std::string GetShortDesc() const;
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionVariable>(m);
}
void SetSegmentIndexValue(int); void SetSegmentIndexValue(int);
int GetSegmentIndexValue() const; int GetSegmentIndexValue() const;
void ResolveVariablesToFixedValues();
enum class Type { enum class Type {
SET_FIXED_VALUE, SET_FIXED_VALUE,

View File

@@ -25,7 +25,7 @@ bool MacroAction::Load(obs_data_t *obj)
void MacroAction::LogAction() const 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) void MacroAction::SetEnabled(bool value)
@@ -38,6 +38,8 @@ bool MacroAction::Enabled() const
return _enabled; return _enabled;
} }
void MacroAction::ResolveVariablesToFixedValues() {}
std::string_view MacroAction::GetDefaultID() std::string_view MacroAction::GetDefaultID()
{ {
return "scene_switch"; return "scene_switch";

View File

@@ -8,10 +8,17 @@ class EXPORT MacroAction : public MacroSegment {
public: public:
MacroAction(Macro *m, bool supportsVariableValue = false); MacroAction(Macro *m, bool supportsVariableValue = false);
virtual ~MacroAction() = default; virtual ~MacroAction() = default;
virtual std::shared_ptr<MacroAction> Copy() const = 0;
virtual bool PerformAction() = 0; virtual bool PerformAction() = 0;
virtual void LogAction() const;
virtual bool Save(obs_data_t *obj) const = 0; virtual bool Save(obs_data_t *obj) const = 0;
virtual bool Load(obs_data_t *obj) = 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); void SetEnabled(bool);
bool Enabled() const; bool Enabled() const;

View File

@@ -3,6 +3,7 @@
#include "macro-properties.hpp" #include "macro-properties.hpp"
#include "macro.hpp" #include "macro.hpp"
#include "path-helpers.hpp" #include "path-helpers.hpp"
#include "plugin-state-helpers.hpp"
#include "section.hpp" #include "section.hpp"
#include "ui-helpers.hpp" #include "ui-helpers.hpp"
#include "utility.hpp" #include "utility.hpp"
@@ -254,6 +255,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
(*_entryData)->SetIndex(idx); (*_entryData)->SetIndex(idx);
(*_entryData)->SetLogicType(logic); (*_entryData)->SetLogicType(logic);
(*_entryData)->PostLoad(); (*_entryData)->PostLoad();
RunPostLoadSteps();
} }
auto widget = auto widget =
MacroConditionFactory::CreateWidget(id, this, *_entryData); MacroConditionFactory::CreateWidget(id, this, *_entryData);
@@ -325,6 +327,7 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
obs_data_release(data); obs_data_release(data);
} }
macro->Conditions().at(idx)->PostLoad(); macro->Conditions().at(idx)->PostLoad();
RunPostLoadSteps();
(*cond)->SetLogicType(logic); (*cond)->SetLogicType(logic);
macro->UpdateConditionIndices(); macro->UpdateConditionIndices();
ui->conditionsList->Insert( ui->conditionsList->Insert(

View File

@@ -96,11 +96,15 @@ void MacroRunButton::Pressed()
bool ret = _elseStateActive ? macro->PerformActions(false, true, true) bool ret = _elseStateActive ? macro->PerformActions(false, true, true)
: macro->PerformActions(true, true, true); : macro->PerformActions(true, true, true);
if (ret) {
return;
}
if (!ret) { QString err = obs_module_text("AdvSceneSwitcher.macroTab.runFail");
QString err = const bool abortMacro = DisplayMessage(
obs_module_text("AdvSceneSwitcher.macroTab.runFail"); err.arg(QString::fromStdString(macro->Name())), true);
DisplayMessage(err.arg(QString::fromStdString(macro->Name()))); if (abortMacro) {
macro->Stop();
} }
} }

View File

@@ -4,7 +4,6 @@
#include "section.hpp" #include "section.hpp"
#include "ui-helpers.hpp" #include "ui-helpers.hpp"
#include <obs.hpp>
#include <QApplication> #include <QApplication>
#include <QEvent> #include <QEvent>
#include <QLabel> #include <QLabel>

View File

@@ -11,7 +11,7 @@
#include <QFrame> #include <QFrame>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QTimer> #include <QTimer>
#include <obs.hpp> #include <obs-data.h>
class QLabel; class QLabel;
@@ -116,8 +116,8 @@ private:
void ShowDropLine(DropLineState); void ShowDropLine(DropLineState);
// The reason for using two separate frame widget each with their own // The reason for using two separate frame widgets, each with their own
// stylesheet and changing their visibility vs. using a single frame // stylesheet, and changing their visibility vs. using a single frame
// and changing the stylesheet at runtime is that the operation of // and changing the stylesheet at runtime is that the operation of
// adjusting the stylesheet is very expensive and can take multiple // adjusting the stylesheet is very expensive and can take multiple
// hundred milliseconds per widget. // hundred milliseconds per widget.

View File

@@ -13,6 +13,7 @@
#include "utility.hpp" #include "utility.hpp"
#include "version.h" #include "version.h"
#include <obs-frontend-api.h>
#include <QColor> #include <QColor>
#include <QGraphicsOpacityEffect> #include <QGraphicsOpacityEffect>
#include <QMenu> #include <QMenu>
@@ -729,6 +730,7 @@ void AdvSceneSwitcher::MacroSelectionChanged()
return; return;
} }
SetEditMacro(*macro); SetEditMacro(*macro);
obs_frontend_save();
} }
void AdvSceneSwitcher::HighlightOnChange() void AdvSceneSwitcher::HighlightOnChange()

View File

@@ -13,7 +13,7 @@
#include <memory> #include <memory>
#include <map> #include <map>
#include <thread> #include <thread>
#include <obs-data.h> #include <obs.hpp>
#include <obs-module-helper.hpp> #include <obs-module-helper.hpp>
namespace advss { namespace advss {

View File

@@ -141,7 +141,9 @@ public:
bool showSystemTrayNotifications = false; bool showSystemTrayNotifications = false;
bool transitionOverrideOverride = false; bool transitionOverrideOverride = false;
bool adjustActiveTransitionType = true; bool adjustActiveTransitionType = true;
bool verbose = false;
enum class LogLevel { DEFAULT, PRINT_ACTION, VERBOSE };
LogLevel logLevel = LogLevel::DEFAULT;
/* --- End of General tab section --- */ /* --- End of General tab section --- */

View File

@@ -33,6 +33,7 @@ void ActionQueue::Save(obs_data_t *obj) const
{ {
obs_data_set_string(obj, "name", _name.c_str()); obs_data_set_string(obj, "name", _name.c_str());
obs_data_set_bool(obj, "runOnStartup", _runOnStartup); obs_data_set_bool(obj, "runOnStartup", _runOnStartup);
obs_data_set_bool(obj, "resolveVariablesOnAdd", _resolveVariablesOnAdd);
} }
void ActionQueue::Load(obs_data_t *obj) void ActionQueue::Load(obs_data_t *obj)
@@ -40,6 +41,8 @@ void ActionQueue::Load(obs_data_t *obj)
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
_name = obs_data_get_string(obj, "name"); _name = obs_data_get_string(obj, "name");
_runOnStartup = obs_data_get_bool(obj, "runOnStartup"); _runOnStartup = obs_data_get_bool(obj, "runOnStartup");
_resolveVariablesOnAdd =
obs_data_get_bool(obj, "resolveVariablesOnAdd");
if (_runOnStartup) { if (_runOnStartup) {
Start(); Start();
@@ -80,10 +83,21 @@ void ActionQueue::Clear()
_actions.clear(); _actions.clear();
} }
void ActionQueue::Add(const std::shared_ptr<MacroAction> &actions) void ActionQueue::Add(const std::shared_ptr<MacroAction> &action)
{ {
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> 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(); _cv.notify_all();
} }
@@ -120,8 +134,11 @@ void ActionQueue::RunActions()
continue; continue;
} }
vblog(LOG_INFO, "Performing action '%s' in queue '%s'", if (ActionLoggingEnabled()) {
action->GetId().c_str(), _name.c_str()); blog(LOG_INFO, "Performing action '%s' in queue '%s'",
action->GetId().c_str(), _name.c_str());
action->LogAction();
}
action->PerformAction(); action->PerformAction();
} }
} }
@@ -139,6 +156,7 @@ ActionQueueSettingsDialog::ActionQueueSettingsDialog(QWidget *parent,
_clear(new QPushButton( _clear(new QPushButton(
obs_module_text("AdvSceneSwitcher.actionQueues.clear"))), obs_module_text("AdvSceneSwitcher.actionQueues.clear"))),
_runOnStartup(new QCheckBox()), _runOnStartup(new QCheckBox()),
_resolveVariablesOnAdd(new QCheckBox()),
_queue(settings) _queue(settings)
{ {
QWidget::connect(_startStopToggle, SIGNAL(clicked()), this, QWidget::connect(_startStopToggle, SIGNAL(clicked()), this,
@@ -146,6 +164,7 @@ ActionQueueSettingsDialog::ActionQueueSettingsDialog(QWidget *parent,
QWidget::connect(_clear, SIGNAL(clicked()), this, SLOT(ClearClicked())); QWidget::connect(_clear, SIGNAL(clicked()), this, SLOT(ClearClicked()));
_runOnStartup->setChecked(settings._runOnStartup); _runOnStartup->setChecked(settings._runOnStartup);
_resolveVariablesOnAdd->setChecked(settings._resolveVariablesOnAdd);
UpdateLabels(); UpdateLabels();
auto layout = new QGridLayout(); auto layout = new QGridLayout();
@@ -167,6 +186,14 @@ ActionQueueSettingsDialog::ActionQueueSettingsDialog(QWidget *parent,
_runOnStartup->setToolTip( _runOnStartup->setToolTip(
obs_module_text("AdvSceneSwitcher.actionQueues.runOnStartup")); obs_module_text("AdvSceneSwitcher.actionQueues.runOnStartup"));
++row; ++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(_queueRunStatus, row, 0);
layout->addWidget(_startStopToggle, row, 1); layout->addWidget(_startStopToggle, row, 1);
++row; ++row;
@@ -194,6 +221,8 @@ bool ActionQueueSettingsDialog::AskForSettings(QWidget *parent,
settings._name = dialog._name->text().toStdString(); settings._name = dialog._name->text().toStdString();
settings._runOnStartup = dialog._runOnStartup->isChecked(); settings._runOnStartup = dialog._runOnStartup->isChecked();
settings._resolveVariablesOnAdd =
dialog._resolveVariablesOnAdd->isChecked();
return true; return true;
} }

View File

@@ -38,6 +38,7 @@ private:
void RunActions(); void RunActions();
bool _runOnStartup = true; bool _runOnStartup = true;
bool _resolveVariablesOnAdd = true;
std::atomic_bool _stop = {false}; std::atomic_bool _stop = {false};
std::mutex _mutex; std::mutex _mutex;
std::condition_variable _cv; std::condition_variable _cv;
@@ -66,6 +67,7 @@ private:
QLabel *_queueSize; QLabel *_queueSize;
QPushButton *_clear; QPushButton *_clear;
QCheckBox *_runOnStartup; QCheckBox *_runOnStartup;
QCheckBox *_resolveVariablesOnAdd;
ActionQueue &_queue; ActionQueue &_queue;
}; };

86
lib/utils/backup.cpp Normal file
View File

@@ -0,0 +1,86 @@
#include "backup.hpp"
#include "log-helper.hpp"
#include "obs-module-helper.hpp"
#include "path-helpers.hpp"
#include "plugin-state-helpers.hpp"
#include "ui-helpers.hpp"
#include "version.h"
#include <obs-frontend-api.h>
#include <obs-module.h>
#include <QFileDialog>
#include <QTextStream>
#include <util/config-file.h>
namespace advss {
void AskForBackup(const QString &json)
{
const bool backupWasConfirmed = DisplayMessage(
obs_module_text("AdvSceneSwitcher.askBackup"), true, false);
if (!backupWasConfirmed) {
return;
}
QString path = QFileDialog::getSaveFileName(
nullptr,
obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle"),
GetDefaultSettingsSaveLocation(),
obs_module_text(
"AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType"));
if (path.isEmpty()) {
return;
}
QFile file(path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
auto out = QTextStream(&file);
out << json;
}
void BackupSettingsOfCurrentVersion()
{
auto sceneCollectionName = obs_frontend_get_current_scene_collection();
const std::string fileName =
std::string("settings-backup-") +
(sceneCollectionName ? sceneCollectionName : "-") + "-" +
g_GIT_TAG + ".json";
bfree(sceneCollectionName);
auto settingsFile = obs_module_config_path(fileName.c_str());
if (!settingsFile) {
return;
}
QString dirPath = QFileInfo(settingsFile).absolutePath();
QDir dir(dirPath);
if (!dir.exists()) {
if (!dir.mkpath(dirPath)) {
blog(LOG_WARNING,
"failed to create directory to save automated backup");
bfree(settingsFile);
return;
}
}
QFile file(settingsFile);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
bfree(settingsFile);
return;
}
OBSDataAutoRelease data = obs_data_create();
SavePluginSettings(data);
auto settings = obs_data_get_json(data);
QString settingsString = QString(settings ? settings : "");
auto out = QTextStream(&file);
out << settingsString;
bfree(settingsFile);
}
} // namespace advss

9
lib/utils/backup.hpp Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include <QString>
namespace advss {
void AskForBackup(const QString &json);
void BackupSettingsOfCurrentVersion();
} // namespace advss

View File

@@ -1,9 +1,9 @@
#include "curl-helper.hpp" #include "curl-helper.hpp"
#include "log-helper.hpp"
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <curl/curl.h> #include <curl/curl.h>
#include <obs.hpp>
namespace advss { namespace advss {

View File

@@ -165,4 +165,9 @@ void Duration::SetUnit(Unit u)
_value = _value * (prevMultiplier / newMultiplier); _value = _value * (prevMultiplier / newMultiplier);
} }
void Duration::ResolveVariables()
{
_value.ResolveVariables();
}
} // namespace advss } // namespace advss

View File

@@ -34,8 +34,10 @@ public:
// Only use this function if you intend to convert old settings formats // Only use this function if you intend to convert old settings formats
EXPORT void SetUnit(Unit u); EXPORT void SetUnit(Unit u);
EXPORT void ResolveVariables();
private: private:
NumberVariable<double> _value = 0.; DoubleVariable _value = 0.;
Unit _unit = Unit::SECONDS; Unit _unit = Unit::SECONDS;
std::chrono::high_resolution_clock::time_point _startTime; std::chrono::high_resolution_clock::time_point _startTime;

View File

@@ -5,7 +5,16 @@ namespace advss {
bool VerboseLoggingEnabled() 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 } // namespace advss

View File

@@ -3,14 +3,26 @@
namespace advss { namespace advss {
// Print log with "[adv-ss] " prefix
#define blog(level, msg, ...) blog(level, "[adv-ss] " msg, ##__VA_ARGS__) #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, ...) \ #define vblog(level, msg, ...) \
do { \ do { \
if (VerboseLoggingEnabled()) { \ if (VerboseLoggingEnabled()) { \
blog(level, msg, ##__VA_ARGS__); \ blog(level, msg, ##__VA_ARGS__); \
} \ } \
} while (0) } 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(); EXPORT bool VerboseLoggingEnabled();
// Returns true if log level is set to "action" or "verbose"
EXPORT bool ActionLoggingEnabled();
} // namespace advss } // namespace advss

View File

@@ -3,6 +3,11 @@
namespace advss { namespace advss {
void SavePluginSettings(obs_data_t *obj)
{
GetSwitcher()->SaveSettings(obj);
}
void LoadPluginSettings(obs_data_t *obj) void LoadPluginSettings(obs_data_t *obj)
{ {
GetSwitcher()->LoadSettings(obj); GetSwitcher()->LoadSettings(obj);

View File

@@ -5,6 +5,7 @@
namespace advss { namespace advss {
void SavePluginSettings(obs_data_t *);
EXPORT void LoadPluginSettings(obs_data_t *); EXPORT void LoadPluginSettings(obs_data_t *);
EXPORT void AddSaveStep(std::function<void(obs_data_t *)>); EXPORT void AddSaveStep(std::function<void(obs_data_t *)>);

View File

@@ -181,6 +181,12 @@ std::string SceneSelection::ToString(bool resolve) const
return ""; return "";
} }
void SceneSelection::ResolveVariables()
{
_scene = GetScene();
_type = Type::SCENE;
}
SceneSelection SceneSelectionWidget::CurrentSelection() SceneSelection SceneSelectionWidget::CurrentSelection()
{ {
SceneSelection s; SceneSelection s;

View File

@@ -26,6 +26,7 @@ public:
EXPORT Type GetType() const { return _type; } EXPORT Type GetType() const { return _type; }
EXPORT OBSWeakSource GetScene(bool advance = true) const; EXPORT OBSWeakSource GetScene(bool advance = true) const;
EXPORT std::string ToString(bool resolve = false) const; EXPORT std::string ToString(bool resolve = false) const;
EXPORT void ResolveVariables();
private: private:
OBSWeakSource _scene; OBSWeakSource _scene;

View File

@@ -2,7 +2,6 @@
#include "export-symbol-helper.hpp" #include "export-symbol-helper.hpp"
#include <deque> #include <deque>
#include <obs.hpp>
#include <QComboBox> #include <QComboBox>
#include <QStringList> #include <QStringList>
#include <string> #include <string>

View File

@@ -88,6 +88,11 @@ void SourceSelection::SetSource(OBSWeakSource source)
_source = source; _source = source;
} }
void SourceSelection::ResolveVariables()
{
SetSource(GetSource());
}
std::string SourceSelection::ToString(bool resolve) const std::string SourceSelection::ToString(bool resolve) const
{ {
switch (_type) { switch (_type) {

View File

@@ -19,6 +19,7 @@ public:
EXPORT Type GetType() const { return _type; } EXPORT Type GetType() const { return _type; }
EXPORT OBSWeakSource GetSource() const; EXPORT OBSWeakSource GetSource() const;
EXPORT void SetSource(OBSWeakSource); EXPORT void SetSource(OBSWeakSource);
EXPORT void ResolveVariables();
EXPORT std::string ToString(bool resolve = false) const; EXPORT std::string ToString(bool resolve = false) const;
EXPORT bool operator==(const SourceSelection &) const; EXPORT bool operator==(const SourceSelection &) const;

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "filter-combo-box.hpp" #include "filter-combo-box.hpp"
#include <obs.hpp> #include <obs-data.h>
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <QEnterEvent> #include <QEnterEvent>

View File

@@ -3,7 +3,6 @@
#include "obs-module-helper.hpp" #include "obs-module-helper.hpp"
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
#include <obs.hpp>
#include <QGraphicsColorizeEffect> #include <QGraphicsColorizeEffect>
#include <QMainWindow> #include <QMainWindow>
#include <QPropertyAnimation> #include <QPropertyAnimation>

View File

@@ -1,8 +1,6 @@
#pragma once #pragma once
#include "variable.hpp" #include "variable.hpp"
#include <obs.hpp>
namespace advss { namespace advss {
template<typename T> class NumberVariable { template<typename T> class NumberVariable {
@@ -24,6 +22,7 @@ public:
Type GetType() const { return _type; } Type GetType() const { return _type; }
bool IsFixedType() const { return _type == Type::FIXED_VALUE; } bool IsFixedType() const { return _type == Type::FIXED_VALUE; }
std::weak_ptr<Variable> GetVariable() const { return _variable; } std::weak_ptr<Variable> GetVariable() const { return _variable; }
void ResolveVariables();
private: private:
Type _type = Type::FIXED_VALUE; Type _type = Type::FIXED_VALUE;

View File

@@ -93,3 +93,9 @@ template<typename T> NumberVariable<T>::operator T() const
{ {
return GetValue(); return GetValue();
} }
template<typename T> void NumberVariable<T>::ResolveVariables()
{
_value = GetValue();
_type = Type::FIXED_VALUE;
}

View File

@@ -50,6 +50,12 @@ void StringVariable::Save(obs_data_t *obj, const char *name) const
obs_data_set_string(obj, name, _value.c_str()); obs_data_set_string(obj, name, _value.c_str());
} }
void StringVariable::ResolveVariables()
{
Resolve();
_value = _resolvedValue;
}
const char *StringVariable::c_str() const char *StringVariable::c_str()
{ {
Resolve(); Resolve();

View File

@@ -2,7 +2,7 @@
#include "variable.hpp" #include "variable.hpp"
#include <string> #include <string>
#include <obs.hpp> #include <obs-data.h>
namespace advss { namespace advss {
@@ -27,6 +27,8 @@ public:
EXPORT void Load(obs_data_t *obj, const char *name); EXPORT void Load(obs_data_t *obj, const char *name);
EXPORT void Save(obs_data_t *obj, const char *name) const; EXPORT void Save(obs_data_t *obj, const char *name) const;
EXPORT void ResolveVariables();
private: private:
void Resolve() const; void Resolve() const;

View File

@@ -102,7 +102,6 @@ static void removeVariableRow(QTableWidget *table, const QString &name)
static void updateVaribleStatus(QTableWidget *table) static void updateVaribleStatus(QTableWidget *table)
{ {
auto lock = LockContext();
for (int row = 0; row < table->rowCount(); row++) { for (int row = 0; row < table->rowCount(); row++) {
auto item = table->item(row, 0); auto item = table->item(row, 0);
if (!item) { if (!item) {

View File

@@ -267,6 +267,7 @@ bool VariableSettingsDialog::AskForSettings(QWidget *parent, Variable &settings)
dialog._defaultValue->toPlainText().toStdString(); dialog._defaultValue->toPlainText().toStdString();
settings._saveAction = settings._saveAction =
static_cast<Variable::SaveAction>(dialog._save->currentIndex()); static_cast<Variable::SaveAction>(dialog._save->currentIndex());
lastVariableChange = std::chrono::high_resolution_clock::now();
return true; return true;
} }
@@ -274,7 +275,6 @@ static bool AskForSettingsWrapper(QWidget *parent, Item &settings)
{ {
Variable &VariableSettings = dynamic_cast<Variable &>(settings); Variable &VariableSettings = dynamic_cast<Variable &>(settings);
if (VariableSettingsDialog::AskForSettings(parent, VariableSettings)) { if (VariableSettingsDialog::AskForSettings(parent, VariableSettings)) {
lastVariableChange = std::chrono::high_resolution_clock::now();
return true; return true;
} }
return false; return false;

View File

@@ -17,6 +17,8 @@ target_sources(
macro-action-hotkey.hpp macro-action-hotkey.hpp
macro-action-http.cpp macro-action-http.cpp
macro-action-http.hpp macro-action-http.hpp
macro-action-log.cpp
macro-action-log.hpp
macro-action-media.cpp macro-action-media.cpp
macro-action-media.hpp macro-action-media.hpp
macro-action-osc.cpp macro-action-osc.cpp
@@ -69,6 +71,8 @@ target_sources(
macro-action-wait.hpp macro-action-wait.hpp
macro-action-websocket.cpp macro-action-websocket.cpp
macro-action-websocket.hpp macro-action-websocket.hpp
macro-action-window.cpp
macro-action-window.hpp
macro-condition-audio.cpp macro-condition-audio.cpp
macro-condition-audio.hpp macro-condition-audio.hpp
macro-condition-cursor.cpp macro-condition-cursor.cpp

View File

@@ -244,7 +244,7 @@ void MacroActionAudio::LogAction() const
auto it = actionTypes.find(_action); auto it = actionTypes.find(_action);
if (it != actionTypes.end()) { if (it != actionTypes.end()) {
auto &[_, action] = *it; auto &[_, action] = *it;
vblog(LOG_INFO, ablog(LOG_INFO,
"performed action \"%s\" for source \"%s\" with volume %f with fade %d %f", "performed action \"%s\" for source \"%s\" with volume %f with fade %d %f",
action.c_str(), _audioSource.ToString(true).c_str(), action.c_str(), _audioSource.ToString(true).c_str(),
GetVolume(), _fade, _duration.Seconds()); GetVolume(), _fade, _duration.Seconds());
@@ -328,6 +328,27 @@ std::string MacroActionAudio::GetShortDesc() const
return _audioSource.ToString(); return _audioSource.ToString();
} }
std::shared_ptr<MacroAction> MacroActionAudio::Create(Macro *m)
{
return std::make_shared<MacroActionAudio>(m);
}
std::shared_ptr<MacroAction> MacroActionAudio::Copy() const
{
return std::make_shared<MacroActionAudio>(*this);
}
void MacroActionAudio::ResolveVariablesToFixedValues()
{
_audioSource.ResolveVariables();
_syncOffset.ResolveVariables();
_balance.ResolveVariables();
_volume.ResolveVariables();
_volumeDB.ResolveVariables();
_duration.ResolveVariables();
_rate.ResolveVariables();
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (const auto &[action, name] : actionTypes) { for (const auto &[action, name] : actionTypes) {

View File

@@ -20,10 +20,9 @@ public:
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc() const; std::string GetShortDesc() const;
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionAudio>(m); void ResolveVariablesToFixedValues();
}
SourceSelection _audioSource; SourceSelection _audioSource;
@@ -44,15 +43,15 @@ public:
Action _action = Action::MUTE; Action _action = Action::MUTE;
FadeType _fadeType = FadeType::DURATION; FadeType _fadeType = FadeType::DURATION;
NumberVariable<int> _syncOffset = 0; IntVariable _syncOffset = 0;
obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE; obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE;
NumberVariable<double> _balance = 0.5; DoubleVariable _balance = 0.5;
bool _useDb = false; bool _useDb = false;
NumberVariable<int> _volume = 0; IntVariable _volume = 0;
NumberVariable<double> _volumeDB = 0.0; DoubleVariable _volumeDB = 0.0;
bool _fade = false; bool _fade = false;
Duration _duration; Duration _duration;
NumberVariable<double> _rate = 100.; DoubleVariable _rate = 100.;
bool _wait = false; bool _wait = false;
bool _abortActiveFade = false; bool _abortActiveFade = false;

View File

@@ -1,6 +1,7 @@
#include "macro-action-clipboard.hpp" #include "macro-action-clipboard.hpp"
#include "curl-helper.hpp" #include "curl-helper.hpp"
#include <obs.hpp>
#include <QApplication> #include <QApplication>
#include <QClipboard> #include <QClipboard>
#include <QImage> #include <QImage>
@@ -92,6 +93,16 @@ static void copyImageFromUrl(void *param)
setMimeTypeParams(params, clipboard); setMimeTypeParams(params, clipboard);
} }
std::shared_ptr<MacroAction> MacroActionClipboard::Create(Macro *m)
{
return std::make_shared<MacroActionClipboard>(m);
}
std::shared_ptr<MacroAction> MacroActionClipboard::Copy() const
{
return std::make_shared<MacroActionClipboard>(*this);
}
bool MacroActionClipboard::PerformAction() bool MacroActionClipboard::PerformAction()
{ {
switch (_action) { switch (_action) {
@@ -158,6 +169,12 @@ bool MacroActionClipboard::Load(obs_data_t *obj)
return true; return true;
} }
void MacroActionClipboard::ResolveVariablesToFixedValues()
{
_text.ResolveVariables();
_url.ResolveVariables();
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (const auto &[action, name] : actionTypes) { for (const auto &[action, name] : actionTypes) {

View File

@@ -22,16 +22,16 @@ struct ClipboardImageQueueParams : ClipboardQueueParams {
class MacroActionClipboard : public MacroAction { class MacroActionClipboard : public MacroAction {
public: public:
MacroActionClipboard(Macro *m) : MacroAction(m) {} MacroActionClipboard(Macro *m) : MacroAction(m) {}
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionClipboard>(m);
}
std::string GetId() const { return id; }; std::string GetId() const { return id; };
bool PerformAction(); bool PerformAction();
bool Save(obs_data_t *obj) const; bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
void ResolveVariablesToFixedValues();
enum class Action { enum class Action {
COPY_TEXT, COPY_TEXT,
COPY_IMAGE, COPY_IMAGE,

View File

@@ -14,9 +14,11 @@ bool MacroActionFile::_registered = MacroActionFactory::Register(
{MacroActionFile::Create, MacroActionFileEdit::Create, {MacroActionFile::Create, MacroActionFileEdit::Create,
"AdvSceneSwitcher.action.file"}); "AdvSceneSwitcher.action.file"});
const static std::map<FileAction, std::string> actionTypes = { static const std::map<MacroActionFile::Action, std::string> actionTypes = {
{FileAction::WRITE, "AdvSceneSwitcher.action.file.type.write"}, {MacroActionFile::Action::WRITE,
{FileAction::APPEND, "AdvSceneSwitcher.action.file.type.append"}, "AdvSceneSwitcher.action.file.type.write"},
{MacroActionFile::Action::APPEND,
"AdvSceneSwitcher.action.file.type.append"},
}; };
bool MacroActionFile::PerformAction() bool MacroActionFile::PerformAction()
@@ -25,10 +27,10 @@ bool MacroActionFile::PerformAction()
QFile file(path); QFile file(path);
bool open = false; bool open = false;
switch (_action) { switch (_action) {
case FileAction::WRITE: case Action::WRITE:
open = file.open(QIODevice::WriteOnly); open = file.open(QIODevice::WriteOnly);
break; break;
case FileAction::APPEND: case Action::APPEND:
open = file.open(QIODevice::WriteOnly | QIODevice::Append); open = file.open(QIODevice::WriteOnly | QIODevice::Append);
break; break;
default: default:
@@ -45,7 +47,7 @@ void MacroActionFile::LogAction() const
{ {
auto it = actionTypes.find(_action); auto it = actionTypes.find(_action);
if (it != actionTypes.end()) { 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()); it->second.c_str(), _file.c_str());
} else { } else {
blog(LOG_WARNING, "ignored unknown file action %d", blog(LOG_WARNING, "ignored unknown file action %d",
@@ -67,7 +69,7 @@ bool MacroActionFile::Load(obs_data_t *obj)
MacroAction::Load(obj); MacroAction::Load(obj);
_file.Load(obj, "file"); _file.Load(obj, "file");
_text.Load(obj, "text"); _text.Load(obj, "text");
_action = static_cast<FileAction>(obs_data_get_int(obj, "action")); _action = static_cast<Action>(obs_data_get_int(obj, "action"));
return true; return true;
} }
@@ -76,21 +78,36 @@ std::string MacroActionFile::GetShortDesc() const
return _file.UnresolvedValue(); return _file.UnresolvedValue();
} }
std::shared_ptr<MacroAction> MacroActionFile::Create(Macro *m)
{
return std::make_shared<MacroActionFile>(m);
}
std::shared_ptr<MacroAction> MacroActionFile::Copy() const
{
return std::make_shared<MacroActionFile>(*this);
}
void MacroActionFile::ResolveVariablesToFixedValues()
{
_file.ResolveVariables();
_text.ResolveVariables();
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (const auto &[_, name] : actionTypes) {
list->addItem(obs_module_text(entry.second.c_str())); list->addItem(obs_module_text(name.c_str()));
} }
} }
MacroActionFileEdit::MacroActionFileEdit( MacroActionFileEdit::MacroActionFileEdit(
QWidget *parent, std::shared_ptr<MacroActionFile> entryData) QWidget *parent, std::shared_ptr<MacroActionFile> 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); populateActionSelection(_actions);
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
@@ -166,7 +183,7 @@ void MacroActionFileEdit::ActionChanged(int value)
} }
auto lock = LockContext(); auto lock = LockContext();
_entryData->_action = static_cast<FileAction>(value); _entryData->_action = static_cast<MacroActionFile::Action>(value);
} }
} // namespace advss } // namespace advss

View File

@@ -7,11 +7,6 @@
namespace advss { namespace advss {
enum class FileAction {
WRITE,
APPEND,
};
class MacroActionFile : public MacroAction { class MacroActionFile : public MacroAction {
public: public:
MacroActionFile(Macro *m) : MacroAction(m) {} MacroActionFile(Macro *m) : MacroAction(m) {}
@@ -21,14 +16,18 @@ public:
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc() const; std::string GetShortDesc() const;
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionFile>(m); void ResolveVariablesToFixedValues();
}
StringVariable _file = obs_module_text("AdvSceneSwitcher.enterPath"); StringVariable _file = obs_module_text("AdvSceneSwitcher.enterPath");
StringVariable _text = obs_module_text("AdvSceneSwitcher.enterText"); StringVariable _text = obs_module_text("AdvSceneSwitcher.enterText");
FileAction _action = FileAction::WRITE;
enum class Action {
WRITE,
APPEND,
};
Action _action = Action::WRITE;
private: private:
static bool _registered; static bool _registered;
@@ -58,13 +57,12 @@ private slots:
signals: signals:
void HeaderInfoChanged(const QString &); void HeaderInfoChanged(const QString &);
protected: private:
FileSelection *_filePath; FileSelection *_filePath;
VariableTextEdit *_text; VariableTextEdit *_text;
QComboBox *_actions; QComboBox *_actions;
std::shared_ptr<MacroActionFile> _entryData;
private: std::shared_ptr<MacroActionFile> _entryData;
bool _loading = true; bool _loading = true;
}; };

View File

@@ -94,7 +94,7 @@ void MacroActionFilter::LogAction() const
{ {
auto it = actionTypes.find(_action); auto it = actionTypes.find(_action);
if (it != actionTypes.end()) { if (it != actionTypes.end()) {
vblog(LOG_INFO, ablog(LOG_INFO,
"performed action \"%s\" for filter \"%s\" on source \"%s\"", "performed action \"%s\" for filter \"%s\" on source \"%s\"",
it->second.c_str(), _filter.ToString().c_str(), it->second.c_str(), _filter.ToString().c_str(),
_source.ToString(true).c_str()); _source.ToString(true).c_str());
@@ -158,6 +158,24 @@ std::string MacroActionFilter::GetShortDesc() const
return ""; return "";
} }
std::shared_ptr<MacroAction> MacroActionFilter::Create(Macro *m)
{
return std::make_shared<MacroActionFilter>(m);
}
std::shared_ptr<MacroAction> MacroActionFilter::Copy() const
{
return std::make_shared<MacroActionFilter>(*this);
}
void MacroActionFilter::ResolveVariablesToFixedValues()
{
_source.ResolveVariables();
_filter.ResolveVariables();
_settingsString.ResolveVariables();
_manualSettingValue.ResolveVariables();
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (auto entry : actionTypes) {

View File

@@ -20,10 +20,9 @@ public:
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc() const; std::string GetShortDesc() const;
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionFilter>(m); void ResolveVariablesToFixedValues();
}
enum class Action { enum class Action {
ENABLE, ENABLE,

View File

@@ -371,7 +371,7 @@ bool MacroActionHotkey::PerformAction()
void MacroActionHotkey::LogAction() const void MacroActionHotkey::LogAction() const
{ {
vblog(LOG_INFO, "sent hotkey type %d", static_cast<int>(_action)); ablog(LOG_INFO, "sent hotkey type %d", static_cast<int>(_action));
} }
bool MacroActionHotkey::Save(obs_data_t *obj) const bool MacroActionHotkey::Save(obs_data_t *obj) const
@@ -425,6 +425,16 @@ bool MacroActionHotkey::Load(obs_data_t *obj)
return true; return true;
} }
std::shared_ptr<MacroAction> MacroActionHotkey::Create(Macro *m)
{
return std::make_shared<MacroActionHotkey>(m);
}
std::shared_ptr<MacroAction> MacroActionHotkey::Copy() const
{
return std::make_shared<MacroActionHotkey>(*this);
}
static inline void populateKeySelection(QComboBox *list) static inline void populateKeySelection(QComboBox *list)
{ {
list->addItems({"No key", list->addItems({"No key",

View File

@@ -18,10 +18,8 @@ public:
bool Save(obs_data_t *obj) const; bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionHotkey>(m);
}
enum class Action { enum class Action {
OBS_HOTKEY, OBS_HOTKEY,

View File

@@ -95,7 +95,7 @@ void MacroActionHttp::LogAction() const
{ {
auto it = methods.find(_method); auto it = methods.find(_method);
if (it != methods.end()) { if (it != methods.end()) {
vblog(LOG_INFO, ablog(LOG_INFO,
"sent http request \"%s\" to \"%s\" with data \"%s\"", "sent http request \"%s\" to \"%s\" with data \"%s\"",
it->second.c_str(), _url.c_str(), _data.c_str()); it->second.c_str(), _url.c_str(), _data.c_str());
} else { } else {
@@ -133,6 +133,24 @@ std::string MacroActionHttp::GetShortDesc() const
return _url.UnresolvedValue(); return _url.UnresolvedValue();
} }
std::shared_ptr<MacroAction> MacroActionHttp::Create(Macro *m)
{
return std::make_shared<MacroActionHttp>(m);
}
std::shared_ptr<MacroAction> MacroActionHttp::Copy() const
{
return std::make_shared<MacroActionHttp>(*this);
}
void MacroActionHttp::ResolveVariablesToFixedValues()
{
_url.ResolveVariables();
_data.ResolveVariables();
_headers.ResolveVariables();
_timeout.ResolveVariables();
}
static inline void populateMethodSelection(QComboBox *list) static inline void populateMethodSelection(QComboBox *list)
{ {
for (auto entry : methods) { for (auto entry : methods) {

View File

@@ -20,10 +20,9 @@ public:
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc() const; std::string GetShortDesc() const;
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionHttp>(m); void ResolveVariablesToFixedValues();
}
enum class Method { enum class Method {
GET = 0, GET = 0,

View File

@@ -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<MacroAction> MacroActionLog::Create(Macro *m)
{
return std::make_shared<MacroActionLog>(m);
}
std::shared_ptr<MacroAction> MacroActionLog::Copy() const
{
return std::make_shared<MacroActionLog>(*this);
}
void MacroActionLog::ResolveVariablesToFixedValues()
{
_logMessage.ResolveVariables();
}
MacroActionLogEdit::MacroActionLogEdit(
QWidget *parent, std::shared_ptr<MacroActionLog> 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

View File

@@ -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<MacroAction> Create(Macro *m);
std::shared_ptr<MacroAction> 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<MacroActionLog> entryData = nullptr);
void UpdateEntryData();
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroAction> action)
{
return new MacroActionLogEdit(
parent,
std::dynamic_pointer_cast<MacroActionLog>(action));
}
private slots:
void LogMessageChanged();
private:
VariableTextEdit *_logMessage;
std::shared_ptr<MacroActionLog> _entryData;
bool _loading = true;
};
} // namespace advss

View File

@@ -38,6 +38,16 @@ static const std::map<MacroActionMedia::SelectionType, std::string>
"AdvSceneSwitcher.action.media.selectionType.sceneItem"}, "AdvSceneSwitcher.action.media.selectionType.sceneItem"},
}; };
std::shared_ptr<MacroAction> MacroActionMedia::Create(Macro *m)
{
return std::make_shared<MacroActionMedia>(m);
}
std::shared_ptr<MacroAction> MacroActionMedia::Copy() const
{
return std::make_shared<MacroActionMedia>(*this);
}
std::string MacroActionMedia::GetShortDesc() const std::string MacroActionMedia::GetShortDesc() const
{ {
if (_selection == SelectionType::SOURCE) { if (_selection == SelectionType::SOURCE) {
@@ -112,7 +122,7 @@ void MacroActionMedia::LogAction() const
{ {
auto it = actionTypes.find(_action); auto it = actionTypes.find(_action);
if (it != actionTypes.end()) { 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(), it->second.c_str(),
_selection == SelectionType::SOURCE _selection == SelectionType::SOURCE
? _mediaSource.ToString(true).c_str() ? _mediaSource.ToString(true).c_str()
@@ -150,6 +160,15 @@ bool MacroActionMedia::Load(obs_data_t *obj)
return true; return true;
} }
void MacroActionMedia::ResolveVariablesToFixedValues()
{
_seekDuration.ResolveVariables();
_seekPercentage.ResolveVariables();
_mediaSource.ResolveVariables();
_sceneItem.ResolveVariables();
_scene.ResolveVariables();
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (const auto &[_, name] : actionTypes) { for (const auto &[_, name] : actionTypes) {

View File

@@ -11,10 +11,8 @@ namespace advss {
class MacroActionMedia : public MacroAction { class MacroActionMedia : public MacroAction {
public: public:
MacroActionMedia(Macro *m) : MacroAction(m) {} MacroActionMedia(Macro *m) : MacroAction(m) {}
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionMedia>(m);
}
std::string GetId() const { return id; }; std::string GetId() const { return id; };
std::string GetShortDesc() const; std::string GetShortDesc() const;
@@ -22,6 +20,7 @@ public:
void LogAction() const; void LogAction() const;
bool Save(obs_data_t *obj) const; bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
void ResolveVariablesToFixedValues();
enum class Action { enum class Action {
PLAY, PLAY,

View File

@@ -1,5 +1,6 @@
#include "macro-action-osc.hpp" #include "macro-action-osc.hpp"
#include <obs.hpp>
#include <QGroupBox> #include <QGroupBox>
#include <system_error> #include <system_error>
@@ -146,7 +147,7 @@ bool MacroActionOSC::PerformAction()
void MacroActionOSC::LogAction() const 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(), _message.ToString().c_str(),
_protocol == Protocol::UDP ? "UDP" : "TCP", _ip.c_str(), _protocol == Protocol::UDP ? "UDP" : "TCP", _ip.c_str(),
_port.GetValue()); _port.GetValue());
@@ -172,6 +173,21 @@ bool MacroActionOSC::Load(obs_data_t *obj)
return true; return true;
} }
std::shared_ptr<MacroAction> MacroActionOSC::Create(Macro *m)
{
return std::make_shared<MacroActionOSC>(m);
}
std::shared_ptr<MacroAction> 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) void MacroActionOSC::SetProtocol(Protocol p)
{ {
_protocol = p; _protocol = p;
@@ -190,6 +206,13 @@ void MacroActionOSC::SetPortNr(IntVariable port)
_reconnect = true; _reconnect = true;
} }
void MacroActionOSC::ResolveVariablesToFixedValues()
{
_ip.ResolveVariables();
_port.ResolveVariables();
_message.ResolveVariables();
}
static void populateProtocolSelection(QComboBox *list) static void populateProtocolSelection(QComboBox *list)
{ {
list->addItem("TCP"); list->addItem("TCP");

View File

@@ -15,10 +15,8 @@ public:
bool Save(obs_data_t *obj) const; bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionOSC>(m);
}
enum class Protocol { enum class Protocol {
TCP, TCP,
@@ -31,6 +29,7 @@ public:
StringVariable GetIP() const { return _ip; } StringVariable GetIP() const { return _ip; }
void SetPortNr(IntVariable); void SetPortNr(IntVariable);
IntVariable GetPortNr() { return _port; } IntVariable GetPortNr() { return _port; }
void ResolveVariablesToFixedValues();
OSCMessage _message; OSCMessage _message;

View File

@@ -174,14 +174,14 @@ void MacroActionPluginState::LogAction() const
blog(LOG_INFO, "stop() called by macro"); blog(LOG_INFO, "stop() called by macro");
break; break;
case PluginStateAction::NO_MATCH_BEHAVIOUR: case PluginStateAction::NO_MATCH_BEHAVIOUR:
vblog(LOG_INFO, "setting no match to %d", _value); ablog(LOG_INFO, "setting no match to %d", _value);
break; break;
case PluginStateAction::IMPORT_SETTINGS: case PluginStateAction::IMPORT_SETTINGS:
vblog(LOG_INFO, "importing settings from %s", ablog(LOG_INFO, "importing settings from %s",
_settingsPath.c_str()); _settingsPath.c_str());
break; break;
case PluginStateAction::TERMINATE: case PluginStateAction::TERMINATE:
vblog(LOG_INFO, "sending terminate signal to OBS in 10s"); ablog(LOG_INFO, "sending terminate signal to OBS in 10s");
break; break;
default: default:
blog(LOG_WARNING, "ignored unknown pluginState action %d", blog(LOG_WARNING, "ignored unknown pluginState action %d",
@@ -212,10 +212,25 @@ bool MacroActionPluginState::Load(obs_data_t *obj)
return true; return true;
} }
std::shared_ptr<MacroAction> MacroActionPluginState::Create(Macro *m)
{
return std::make_shared<MacroActionPluginState>(m);
}
std::shared_ptr<MacroAction> MacroActionPluginState::Copy() const
{
return std::make_shared<MacroActionPluginState>(*this);
}
void MacroActionPluginState::ResolveVariablesToFixedValues()
{
_settingsPath = std::string(_settingsPath);
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (const auto &[_, name] : actionTypes) {
list->addItem(obs_module_text(entry.second.c_str())); list->addItem(obs_module_text(name.c_str()));
} }
} }
@@ -223,8 +238,8 @@ static inline void populateValueSelection(QComboBox *list,
PluginStateAction action) PluginStateAction action)
{ {
if (action == PluginStateAction::NO_MATCH_BEHAVIOUR) { if (action == PluginStateAction::NO_MATCH_BEHAVIOUR) {
for (auto entry : noMatchValues) { for (const auto &[_, name] : noMatchValues) {
list->addItem(obs_module_text(entry.second.c_str())); list->addItem(obs_module_text(name.c_str()));
} }
} }
} }

View File

@@ -2,6 +2,7 @@
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "file-selection.hpp" #include "file-selection.hpp"
#include <obs.hpp>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QLabel> #include <QLabel>
@@ -22,10 +23,9 @@ public:
bool Save(obs_data_t *obj) const; bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionPluginState>(m); void ResolveVariablesToFixedValues();
}
PluginStateAction _action = PluginStateAction::STOP; PluginStateAction _action = PluginStateAction::STOP;
int _value = 0; int _value = 0;

View File

@@ -21,7 +21,7 @@ bool MacroActionProfile::PerformAction()
void MacroActionProfile::LogAction() const 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 bool MacroActionProfile::Save(obs_data_t *obj) const
@@ -43,6 +43,16 @@ std::string MacroActionProfile::GetShortDesc() const
return _profile; return _profile;
} }
std::shared_ptr<MacroAction> MacroActionProfile::Create(Macro *m)
{
return std::make_shared<MacroActionProfile>(m);
}
std::shared_ptr<MacroAction> MacroActionProfile::Copy() const
{
return std::make_shared<MacroActionProfile>(*this);
}
MacroActionProfileEdit::MacroActionProfileEdit( MacroActionProfileEdit::MacroActionProfileEdit(
QWidget *parent, std::shared_ptr<MacroActionProfile> entryData) QWidget *parent, std::shared_ptr<MacroActionProfile> entryData)
: QWidget(parent) : QWidget(parent)

View File

@@ -14,10 +14,8 @@ public:
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc() const; std::string GetShortDesc() const;
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionProfile>(m);
}
std::string _profile; std::string _profile;

View File

@@ -75,7 +75,7 @@ void MacroActionProjector::LogAction() const
{ {
auto it = selectionTypes.find(_type); auto it = selectionTypes.find(_type);
if (it != selectionTypes.end()) { if (it != selectionTypes.end()) {
vblog(LOG_INFO, ablog(LOG_INFO,
"performed projector action \"%s\" with" "performed projector action \"%s\" with"
"source \"%s\"," "source \"%s\","
"scene \"%s\"," "scene \"%s\","
@@ -119,6 +119,22 @@ bool MacroActionProjector::Load(obs_data_t *obj)
return true; return true;
} }
std::shared_ptr<MacroAction> MacroActionProjector::Create(Macro *m)
{
return std::make_shared<MacroActionProjector>(m);
}
std::shared_ptr<MacroAction> MacroActionProjector::Copy() const
{
return std::make_shared<MacroActionProjector>(*this);
}
void MacroActionProjector::ResolveVariablesToFixedValues()
{
_source.ResolveVariables();
_scene.ResolveVariables();
}
void MacroActionProjector::SetMonitor(int idx) void MacroActionProjector::SetMonitor(int idx)
{ {
_monitor = idx; _monitor = idx;

View File

@@ -13,10 +13,9 @@ public:
bool Save(obs_data_t *obj) const; bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionProjector>(m); void ResolveVariablesToFixedValues();
}
void SetMonitor(int); void SetMonitor(int);
int GetMonitor() const; int GetMonitor() const;

View File

@@ -64,7 +64,7 @@ bool MacroActionRandom::PerformAction()
void MacroActionRandom::LogAction() const void MacroActionRandom::LogAction() const
{ {
vblog(LOG_INFO, "running random macro"); ablog(LOG_INFO, "running random macro");
} }
bool MacroActionRandom::Save(obs_data_t *obj) const bool MacroActionRandom::Save(obs_data_t *obj) const
@@ -83,6 +83,16 @@ bool MacroActionRandom::Load(obs_data_t *obj)
return true; return true;
} }
std::shared_ptr<MacroAction> MacroActionRandom::Create(Macro *m)
{
return std::make_shared<MacroActionRandom>(m);
}
std::shared_ptr<MacroAction> MacroActionRandom::Copy() const
{
return std::make_shared<MacroActionRandom>(*this);
}
MacroActionRandomEdit::MacroActionRandomEdit( MacroActionRandomEdit::MacroActionRandomEdit(
QWidget *parent, std::shared_ptr<MacroActionRandom> entryData) QWidget *parent, std::shared_ptr<MacroActionRandom> entryData)
: QWidget(parent), : QWidget(parent),

View File

@@ -16,10 +16,8 @@ public:
bool Save(obs_data_t *obj) const; bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionRandom>(m);
}
bool _allowRepeat = false; bool _allowRepeat = false;

View File

@@ -97,7 +97,7 @@ void MacroActionRecord::LogAction() const
{ {
auto it = actionTypes.find(_action); auto it = actionTypes.find(_action);
if (it != actionTypes.end()) { 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 { } else {
blog(LOG_WARNING, "ignored unknown recording action %d", blog(LOG_WARNING, "ignored unknown recording action %d",
static_cast<int>(_action)); static_cast<int>(_action));
@@ -122,10 +122,26 @@ bool MacroActionRecord::Load(obs_data_t *obj)
return true; return true;
} }
std::shared_ptr<MacroAction> MacroActionRecord::Create(Macro *m)
{
return std::make_shared<MacroActionRecord>(m);
}
std::shared_ptr<MacroAction> MacroActionRecord::Copy() const
{
return std::make_shared<MacroActionRecord>(*this);
}
void MacroActionRecord::ResolveVariablesToFixedValues()
{
_folder.ResolveVariables();
_fileFormat.ResolveVariables();
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (const auto &[_, name] : actionTypes) {
list->addItem(obs_module_text(entry.second.c_str())); list->addItem(obs_module_text(name.c_str()));
} }
} }

View File

@@ -17,10 +17,9 @@ public:
bool Save(obs_data_t *obj) const; bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m) static std::shared_ptr<MacroAction> Create(Macro *m);
{ std::shared_ptr<MacroAction> Copy() const;
return std::make_shared<MacroActionRecord>(m); void ResolveVariablesToFixedValues();
}
enum class Action { enum class Action {
STOP, STOP,

View File

@@ -47,7 +47,7 @@ void MacroActionReplayBuffer::LogAction() const
{ {
auto it = actionTypes.find(_action); auto it = actionTypes.find(_action);
if (it != actionTypes.end()) { 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 { } else {
blog(LOG_WARNING, "ignored unknown replay buffer action %d", blog(LOG_WARNING, "ignored unknown replay buffer action %d",
static_cast<int>(_action)); static_cast<int>(_action));
@@ -69,10 +69,20 @@ bool MacroActionReplayBuffer::Load(obs_data_t *obj)
return true; return true;
} }
std::shared_ptr<MacroAction> MacroActionReplayBuffer::Create(Macro *m)
{
return std::make_shared<MacroActionReplayBuffer>(m);
}
std::shared_ptr<MacroAction> MacroActionReplayBuffer::Copy() const
{
return std::make_shared<MacroActionReplayBuffer>(*this);
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (const auto &[_, name] : actionTypes) {
list->addItem(obs_module_text(entry.second.c_str())); list->addItem(obs_module_text(name.c_str()));
} }
} }

Some files were not shown because too many files have changed in this diff Show More