mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 12:45:28 -05:00
Compare commits
84 Commits
virtual-de
...
1.15.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2af0735a2f | ||
|
|
556943c293 | ||
|
|
e3004184c4 | ||
|
|
7b2c2e91db | ||
|
|
06ea7bf1d9 | ||
|
|
1474509cb9 | ||
|
|
87aa8d3b40 | ||
|
|
d3e8b76fa6 | ||
|
|
99c9b1a4a2 | ||
|
|
8c0aad4c96 | ||
|
|
c964ed04d3 | ||
|
|
810235e0b7 | ||
|
|
e2b3563810 | ||
|
|
76c5ec480b | ||
|
|
84e4b740a8 | ||
|
|
95409dfa26 | ||
|
|
058af0d3bb | ||
|
|
fd789b476b | ||
|
|
3fc82df278 | ||
|
|
d541356fd3 | ||
|
|
5c2adacca1 | ||
|
|
7200668158 | ||
|
|
7cf7fd6112 | ||
|
|
41821cbeb2 | ||
|
|
9537579235 | ||
|
|
40a701a934 | ||
|
|
6c8556c66c | ||
|
|
a467dffd05 | ||
|
|
497dbd89d4 | ||
|
|
0fdbce25a1 | ||
|
|
7e3e621ae5 | ||
|
|
9dfbd266fc | ||
|
|
8d02f63c36 | ||
|
|
f31c54fd72 | ||
|
|
7719087065 | ||
|
|
0b175a41d1 | ||
|
|
0824abc4f5 | ||
|
|
efef29603b | ||
|
|
034a1b0c93 | ||
|
|
86fefe1e9e | ||
|
|
0bc15b4c2d | ||
|
|
7cfa956b80 | ||
|
|
9670a01e1a | ||
|
|
371f6daf5a | ||
|
|
1c141abd06 | ||
|
|
13788c2dfa | ||
|
|
daf36365a8 | ||
|
|
cea4df90b1 | ||
|
|
80b824e0a7 | ||
|
|
0bfdc3890b | ||
|
|
cc067de021 | ||
|
|
57c0734ba6 | ||
|
|
913682e128 | ||
|
|
92711c5798 | ||
|
|
80334088d0 | ||
|
|
bdd9d12257 | ||
|
|
decee4647b | ||
|
|
4991e74a72 | ||
|
|
baa158bb33 | ||
|
|
0975ffabfa | ||
|
|
beec7d5939 | ||
|
|
1bf2a154e2 | ||
|
|
aa691cf51c | ||
|
|
8fc12bee99 | ||
|
|
5e8a0f92ee | ||
|
|
86029e8e0e | ||
|
|
a86d6f1f76 | ||
|
|
8ef798c70c | ||
|
|
efc8726054 | ||
|
|
7b72abb100 | ||
|
|
311ee5d0a0 | ||
|
|
5e4258968a | ||
|
|
ae4e861f7f | ||
|
|
d692444687 | ||
|
|
6976c98fd8 | ||
|
|
75f8d0cb07 | ||
|
|
a7e03245bd | ||
|
|
056e7ef737 | ||
|
|
675c23d7cc | ||
|
|
c4b66ef7f6 | ||
|
|
5cae1bca41 | ||
|
|
407d338b8b | ||
|
|
edd9f18de0 | ||
|
|
c9769a799d |
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@@ -160,6 +160,7 @@ jobs:
|
||||
libxcb-xinerama0-dev \
|
||||
libxcomposite-dev \
|
||||
libxinerama-dev \
|
||||
libxtst-dev \
|
||||
libmbedtls-dev \
|
||||
pkg-config \
|
||||
python3-dev \
|
||||
|
||||
131
BUILDING.md
Normal file
131
BUILDING.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# Compiling the plugin
|
||||
|
||||
You have the option to ...
|
||||
- either add the plugin to the OBS source tree directly and build the plugin while building OBS itself. (**in tree**)
|
||||
- or you can move the sources of this plugin outside of the OBS source tree and build it separately from OBS. (**out of tree**)
|
||||
|
||||
As both methods require you to have a working [OBS Studio development environment](https://obsproject.com/wiki/install-instructions), [Qt](https://download.qt.io/official_releases/qt/5.15/5.15.2/) 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.
|
||||
|
||||
Note that your Qt install must include the QtConcurrent module.
|
||||
|
||||
## Compiling in tree (recommended)
|
||||
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
|
||||
```
|
||||
cd obs-studio/UI/frontend-plugins/
|
||||
git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git
|
||||
```
|
||||
|
||||
Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt file and add an entry for the scene switcher:
|
||||
add_subdirectory(SceneSwitcher)
|
||||
|
||||
## Compiling out of tree
|
||||
### Prerequisites
|
||||
You'll need [Qt](https://download.qt.io/official_releases/qt/5.15/5.15.2/), [CMake](https://cmake.org/download/) and a working [OBS Studio development environment](https://obsproject.com/wiki/install-instructions) installed on your computer.
|
||||
Once you've set this up, do the following:
|
||||
```
|
||||
git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git
|
||||
cd SceneSwitcher
|
||||
mkdir build && cd build
|
||||
```
|
||||
|
||||
### Windows
|
||||
In cmake-gui, you'll have to set these CMake variables :
|
||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||
|
||||
- **LIBOBS_LIB** (filepath) : location of the obs.lib file
|
||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||
code of OBS Studio, located at [source_directory]/libobs/.
|
||||
|
||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the obs-frontend-api.lib file
|
||||
(usually in the same place as LIBOBS_LIB)
|
||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
||||
subfolder in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
||||
|
||||
- **CURL_LIB** (filepath) : location of the libcurl.lib file
|
||||
(part of the dependencies2019/win64/bin folder used to build OBS)
|
||||
- **CURL_INCLUDE_DIR** (path) : location of the curl
|
||||
subfolder in OBS dependencies folder: ".../dependencies2019/win64/include/"
|
||||
|
||||
|
||||
Assuming that you set up Qt via QT installer:
|
||||
- **Qt5Core_DIR** (path) : C:/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5Core
|
||||
- **Qt5Gui_DIR** (path): C:/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5Gui
|
||||
- **Qt5Widgets_DIR** (path) : C:/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5Widgets
|
||||
|
||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||
|
||||
### Linux
|
||||
Most versions of Linux you can use cmake-gui or the command line.
|
||||
|
||||
**For the command line:**
|
||||
```
|
||||
# [...] are placeholders
|
||||
cmake -DBUILD_OUT_OF_TREE=1 \
|
||||
-DLIBOBS_INCLUDE_DIR=[...]/obs-studio/libobs/ \
|
||||
-DLIBOBS_LIB=[...]/libobs.so \
|
||||
-DLIBOBS_FRONTEND_INCLUDE_DIR=[...]/obs-studio/UI/obs-frontend-api/ \
|
||||
-DLIBOBS_FRONTEND_API_LIB=[...]/libobs-frontend-api.so \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
|
||||
For cmake-gui you'll have to set the following variables:
|
||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||
code of OBS Studio, located at [source_directory]/libobs/.
|
||||
- **LIBOBS_LIB** (filepath) : location of the libobs.so file (usually CMake finds
|
||||
this, but if not it'll usually be in /usr/lib/libobs.so)
|
||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.so
|
||||
file (usually in the same place as LIBOBS_LIB)
|
||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
||||
subfolder in the source code of OBS Studio, located at
|
||||
[source_directory]/UI/obs-frontend-api.
|
||||
|
||||
Assuming that you installed Qt via your system package manager, it should be
|
||||
found automatically. If not, then usually you'll find it in something like:
|
||||
- **Qt5Core_DIR** (path) : /usr/lib64/cmake/Qt5Core
|
||||
- **Qt5Gui_DIR** (path): /usr/lib64/cmake/Qt5Gui
|
||||
- **Qt5Widgets_DIR** (path) : /usr/lib64/cmake/Qt5Widgets
|
||||
|
||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||
|
||||
Then open a terminal in the build folder and type:
|
||||
```
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
NOTE: The Linux version of this plugin is dependent on libXScrnSaver, libcurl and libXtst.
|
||||
|
||||
### OS X
|
||||
In cmake-gui, you'll have to set these CMake variables :
|
||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||
code of OBS Studio, located at [source_directory]/libobs/.
|
||||
- **LIBOBS_LIB** (filepath) : location of the libobs.0.dylib file (usually
|
||||
in /Applications/OBS.app/Contents/Resources/bin/libobs.0.dylib)
|
||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.0.dylib
|
||||
file (usually in usually in /Applications/OBS.app/Contents/Resources/bin/libobs-frontend-api.0.dylib)
|
||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api subfolder
|
||||
in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
||||
|
||||
Assuming that you installed Qt via the regular Qt App way:
|
||||
- **Qt5Core_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Core
|
||||
- **Qt5Widgets_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Widgets
|
||||
- **Qt5MacExtras_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5MacExtras
|
||||
|
||||
|
||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||
|
||||
Open xcode (or a terminal, depending on the build type you chose), build and copy
|
||||
the advanced-scene-switcher.so file to 'Library/Application Support/obs-studio/plugins/advanced-scene-switcher/bin/'
|
||||
And the 'data' folder to 'Library/Application Support/obs-studio/plugins/advanced-scene-switcher/'.
|
||||
|
||||
Note that you might have to adjust the library search paths using the install_name_tool if you want the plugin to run on machines other than your build machine:
|
||||
```
|
||||
install_name_tool -change @rpath/libobs-frontend-api.dylib @executable_path/../Frameworks/libobs-frontend-api.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change /usr/local/opt/qt5/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change /usr/local/opt/qt5/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change /usr/local/opt/qt5/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
```
|
||||
571
CMakeLists.txt
571
CMakeLists.txt
@@ -1,294 +1,347 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(advanced-scene-switcher)
|
||||
add_definitions(-DASIO_STANDALONE)
|
||||
|
||||
# generate version info
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
||||
endif()
|
||||
|
||||
# Compiler settings
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC
|
||||
OR CMAKE_COMPILER_IS_GNUCXX
|
||||
OR CMAKE_COMPILER_IS_CLANG)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"-Wall -Wextra -Wvla -Wno-unused-function -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS} -fno-strict-aliasing"
|
||||
)
|
||||
set(CMAKE_C_FLAGS
|
||||
"-Wall -Wextra -Wvla -Wno-unused-function -Werror-implicit-function-declaration -Wno-missing-braces -Wno-missing-field-initializers ${CMAKE_C_FLAGS} -std=gnu99 -fno-strict-aliasing"
|
||||
)
|
||||
|
||||
option(USE_LIBC++ "Use libc++ instead of libstdc++" ${APPLE})
|
||||
if(USE_LIBC++)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
elseif(MSVC)
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
|
||||
# Disable pointless constant condition warnings
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} /wd4127 /wd4201 /wd4456 /wd4457 /wd4458 /wd4459 /wd4595"
|
||||
)
|
||||
add_definitions(-DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS
|
||||
-D_CRT_NONSTDC_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
# Generate version info
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
|
||||
if(WIN32)
|
||||
get_filename_component(ISS_PLUGIN_FILES_DIR "${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
|
||||
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}" ISS_MSVC_REDIST_HELPER_DIR)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
|
||||
get_filename_component(ISS_PLUGIN_FILES_DIR
|
||||
"${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
|
||||
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR
|
||||
"${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}"
|
||||
ISS_MSVC_REDIST_HELPER_DIR)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
|
||||
endif()
|
||||
|
||||
# Windows installer
|
||||
if(WIN32)
|
||||
get_filename_component(ISS_PLUGIN_FILES_DIR "${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
|
||||
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}" ISS_MSVC_REDIST_HELPER_DIR)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
|
||||
get_filename_component(ISS_PLUGIN_FILES_DIR
|
||||
"${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
|
||||
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR
|
||||
"${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}"
|
||||
ISS_MSVC_REDIST_HELPER_DIR)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
|
||||
endif()
|
||||
|
||||
# Out of tree specific settings
|
||||
if(BUILD_OUT_OF_TREE)
|
||||
set(CMAKE_PREFIX_PATH "${QTDIR}")
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/external")
|
||||
set(CMAKE_PREFIX_PATH "${QTDIR}")
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/external")
|
||||
include(external/FindLibObs.cmake)
|
||||
find_package(LibObs REQUIRED)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_path(LIBOBS_FRONTEND_INCLUDE_DIR HINTS ${LIBOBS_INCLUDE_DIRS})
|
||||
find_file(
|
||||
LIBOBS_FRONTEND_API_LIB
|
||||
NAMES libobs-frontend-api.*
|
||||
HINTS ${LIBOBS_LIB})
|
||||
|
||||
include(external/FindLibObs.cmake)
|
||||
find_package(LibObs REQUIRED)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Libcurl REQUIRED)
|
||||
find_path(LIBOBS_FRONTEND_INCLUDE_DIR HINTS ${LIBOBS_INCLUDE_DIRS})
|
||||
find_file(LIBOBS_FRONTEND_API_LIB NAMES libobs-frontend-api.* HINTS ${LIBOBS_LIB} )
|
||||
include_directories("${LIBOBS_INCLUDE_DIRS}" "${LIBOBS_FRONTEND_INCLUDE_DIR}"
|
||||
${Qt5Core_INCLUDES} ${Qt5Widgets_INCLUDES})
|
||||
endif()
|
||||
|
||||
# Platform specific settings
|
||||
if(APPLE)
|
||||
find_library(COCOA Cocoa)
|
||||
if(BUILD_OUT_OF_TREE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif()
|
||||
include_directories(${COCOA})
|
||||
find_library(COCOA Cocoa)
|
||||
if(BUILD_OUT_OF_TREE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif()
|
||||
include_directories(${COCOA})
|
||||
endif()
|
||||
|
||||
find_package(Libcurl REQUIRED)
|
||||
include_directories("${LIBCURL_INCLUDE_DIRS}")
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(X11 REQUIRED)
|
||||
link_libraries(${X11_LIBRARIES})
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
find_package(X11 REQUIRED COMPONENTS Xtst Xss)
|
||||
link_libraries(${X11_LIBRARIES})
|
||||
include_directories("${X11_INCLUDE_DIR}" "${X11_Xtst_INCLUDE_PATH}"
|
||||
"${X11_Xss_INCLUDE_PATH}")
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp"
|
||||
)
|
||||
|
||||
set(advanced-scene-switcher_HEADERS
|
||||
${advanced-scene-switcher_HEADERS}
|
||||
src/headers/advanced-scene-switcher.hpp
|
||||
src/headers/switcher-data-structs.hpp
|
||||
src/headers/scene-group.hpp
|
||||
src/headers/scene-trigger.hpp
|
||||
src/headers/switch-audio.hpp
|
||||
src/headers/switch-executable.hpp
|
||||
src/headers/switch-file.hpp
|
||||
src/headers/switch-idle.hpp
|
||||
src/headers/switch-media.hpp
|
||||
src/headers/switch-network.hpp
|
||||
src/headers/switch-pause.hpp
|
||||
src/headers/switch-random.hpp
|
||||
src/headers/switch-screen-region.hpp
|
||||
src/headers/switch-time.hpp
|
||||
src/headers/switch-transitions.hpp
|
||||
src/headers/switch-window.hpp
|
||||
src/headers/switch-sequence.hpp
|
||||
src/headers/switch-video.hpp
|
||||
src/headers/switch-generic.hpp
|
||||
src/headers/macro-action-edit.hpp
|
||||
src/headers/macro-action-audio.hpp
|
||||
src/headers/macro-action-filter.hpp
|
||||
src/headers/macro-action-macro.hpp
|
||||
src/headers/macro-action-media.hpp
|
||||
src/headers/macro-action-plugin-state.hpp
|
||||
src/headers/macro-action-recording.hpp
|
||||
src/headers/macro-action-replay-buffer.hpp
|
||||
src/headers/macro-action-run.hpp
|
||||
src/headers/macro-action-scene-switch.hpp
|
||||
src/headers/macro-action-scene-visibility.hpp
|
||||
src/headers/macro-action-source.hpp
|
||||
src/headers/macro-action-streaming.hpp
|
||||
src/headers/macro-action-wait.hpp
|
||||
src/headers/macro-condition-edit.hpp
|
||||
src/headers/macro-condition-audio.hpp
|
||||
src/headers/macro-condition-counter.hpp
|
||||
src/headers/macro-condition-file.hpp
|
||||
src/headers/macro-condition-idle.hpp
|
||||
src/headers/macro-condition-interval.hpp
|
||||
src/headers/macro-condition-media.hpp
|
||||
src/headers/macro-condition-plugin-state.hpp
|
||||
src/headers/macro-condition-process.hpp
|
||||
src/headers/macro-condition-recording.hpp
|
||||
src/headers/macro-condition-region.hpp
|
||||
src/headers/macro-condition-scene.hpp
|
||||
src/headers/macro-condition-source.hpp
|
||||
src/headers/macro-condition-streaming.hpp
|
||||
src/headers/macro-condition-video.hpp
|
||||
src/headers/macro-condition-virt-desktop.hpp
|
||||
src/headers/macro-condition-window.hpp
|
||||
src/headers/macro.hpp
|
||||
src/headers/macro-selection.hpp
|
||||
src/headers/curl-helper.hpp
|
||||
src/headers/screenshot-helper.hpp
|
||||
src/headers/name-dialog.hpp
|
||||
src/headers/duration-control.hpp
|
||||
src/headers/section.hpp
|
||||
src/headers/platform-funcs.hpp
|
||||
src/headers/utility.hpp
|
||||
src/headers/volume-control.hpp
|
||||
src/headers/version.h
|
||||
)
|
||||
|
||||
set(advanced-scene-switcher_SOURCES
|
||||
${advanced-scene-switcher_SOURCES}
|
||||
src/advanced-scene-switcher.cpp
|
||||
src/advanced-scene-switcher-module.c
|
||||
src/switcher-data-structs.cpp
|
||||
src/scene-group.cpp
|
||||
src/scene-trigger.cpp
|
||||
src/switch-transitions.cpp
|
||||
src/switch-screen-region.cpp
|
||||
src/switch-priority.cpp
|
||||
src/switch-executable.cpp
|
||||
src/switch-idle.cpp
|
||||
src/switch-sequence.cpp
|
||||
src/switch-file.cpp
|
||||
src/switch-window.cpp
|
||||
src/switch-media.cpp
|
||||
src/switch-network.cpp
|
||||
src/hotkey.cpp
|
||||
src/general.cpp
|
||||
src/switch-pause.cpp
|
||||
src/switch-random.cpp
|
||||
src/switch-time.cpp
|
||||
src/switch-audio.cpp
|
||||
src/switch-video.cpp
|
||||
src/switch-generic.cpp
|
||||
src/macro-action-edit.cpp
|
||||
src/macro-action-audio.cpp
|
||||
src/macro-action-filter.cpp
|
||||
src/macro-action-macro.cpp
|
||||
src/macro-action-media.cpp
|
||||
src/macro-action-plugin-state.cpp
|
||||
src/macro-action-recording.cpp
|
||||
src/macro-action-replay-buffer.cpp
|
||||
src/macro-action-run.cpp
|
||||
src/macro-action-scene-switch.cpp
|
||||
src/macro-action-scene-visibility.cpp
|
||||
src/macro-action-source.cpp
|
||||
src/macro-action-streaming.cpp
|
||||
src/macro-action-wait.cpp
|
||||
src/macro-condition-edit.cpp
|
||||
src/macro-condition-audio.cpp
|
||||
src/macro-condition-counter.cpp
|
||||
src/macro-condition-file.cpp
|
||||
src/macro-condition-idle.cpp
|
||||
src/macro-condition-interval.cpp
|
||||
src/macro-condition-media.cpp
|
||||
src/macro-condition-plugin-state.cpp
|
||||
src/macro-condition-process.cpp
|
||||
src/macro-condition-recording.cpp
|
||||
src/macro-condition-region.cpp
|
||||
src/macro-condition-scene.cpp
|
||||
src/macro-condition-source.cpp
|
||||
src/macro-condition-streaming.cpp
|
||||
src/macro-condition-video.cpp
|
||||
src/macro-condition-virt-desktop.cpp
|
||||
src/macro-condition-window.cpp
|
||||
src/macro.cpp
|
||||
src/macro-selection.cpp
|
||||
src/macro-tab.cpp
|
||||
src/curl-helper.cpp
|
||||
src/screenshot-helper.cpp
|
||||
src/name-dialog.cpp
|
||||
src/duration-control.cpp
|
||||
src/section.cpp
|
||||
src/utility.cpp
|
||||
src/volume-control.cpp
|
||||
src/version.cpp
|
||||
)
|
||||
|
||||
set(advanced-scene-switcher_UI
|
||||
${advanced-scene-switcher_UI}
|
||||
forms/advanced-scene-switcher.ui
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/win/advanced-scene-switcher-win.cpp)
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/win/advanced-scene-switcher-win.cpp)
|
||||
elseif(APPLE)
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/osx/advanced-scene-switcher-osx.mm)
|
||||
set_source_files_properties(advanced-scene-switcher-osx.mm
|
||||
PROPERTIES COMPILE_FLAGS "-fobjc-arc")
|
||||
set(advanced-scene-switcher_PLATFORM_LIBS
|
||||
${COCOA})
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/osx/advanced-scene-switcher-osx.mm)
|
||||
set_source_files_properties(advanced-scene-switcher-osx.mm
|
||||
PROPERTIES COMPILE_FLAGS "-fobjc-arc")
|
||||
set(advanced-scene-switcher_PLATFORM_LIBS ${COCOA})
|
||||
else()
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/linux/advanced-scene-switcher-nix.cpp)
|
||||
set(advanced-scene-switcher_PLATFORM_LIBS
|
||||
Xss)
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/linux/advanced-scene-switcher-nix.cpp)
|
||||
set(advanced-scene-switcher_PLATFORM_LIBS Xss)
|
||||
endif()
|
||||
|
||||
qt5_wrap_ui(advanced-scene-switcher_UI_HEADERS
|
||||
${advanced-scene-switcher_UI}
|
||||
${advanced-scene-switcher_PLATFORM_UI})
|
||||
# asio and websocketpp
|
||||
add_definitions(-DASIO_STANDALONE)
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp")
|
||||
if(WIN32)
|
||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||
endif()
|
||||
|
||||
add_library(advanced-scene-switcher MODULE
|
||||
${advanced-scene-switcher_HEADERS}
|
||||
${advanced-scene-switcher_SOURCES}
|
||||
${advanced-scene-switcher_UI_HEADERS}
|
||||
${advanced-scene-switcher_PLATFORM_SOURCES}
|
||||
${advanced-scene-switcher_PLATFORM_HEADERS}
|
||||
)
|
||||
# Setup QT tools
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/forms")
|
||||
set(advanced-scene-switcher_UI ${advanced-scene-switcher_UI}
|
||||
forms/advanced-scene-switcher.ui)
|
||||
qt5_wrap_ui(advanced-scene-switcher_UI_HEADERS ${advanced-scene-switcher_UI}
|
||||
${advanced-scene-switcher_PLATFORM_UI})
|
||||
|
||||
# The plugin sources
|
||||
set(advanced-scene-switcher_HEADERS
|
||||
${advanced-scene-switcher_HEADERS}
|
||||
src/headers/advanced-scene-switcher.hpp
|
||||
src/headers/switcher-data-structs.hpp
|
||||
src/headers/scene-group.hpp
|
||||
src/headers/scene-trigger.hpp
|
||||
src/headers/switch-audio.hpp
|
||||
src/headers/switch-executable.hpp
|
||||
src/headers/switch-file.hpp
|
||||
src/headers/switch-idle.hpp
|
||||
src/headers/switch-media.hpp
|
||||
src/headers/switch-network.hpp
|
||||
src/headers/switch-pause.hpp
|
||||
src/headers/switch-random.hpp
|
||||
src/headers/switch-screen-region.hpp
|
||||
src/headers/switch-time.hpp
|
||||
src/headers/switch-transitions.hpp
|
||||
src/headers/switch-window.hpp
|
||||
src/headers/switch-sequence.hpp
|
||||
src/headers/switch-video.hpp
|
||||
src/headers/switch-generic.hpp
|
||||
src/headers/macro-action-edit.hpp
|
||||
src/headers/macro-action-audio.hpp
|
||||
src/headers/macro-action-file.hpp
|
||||
src/headers/macro-action-filter.hpp
|
||||
src/headers/macro-action-hotkey.hpp
|
||||
src/headers/macro-action-macro.hpp
|
||||
src/headers/macro-action-media.hpp
|
||||
src/headers/macro-action-plugin-state.hpp
|
||||
src/headers/macro-action-recording.hpp
|
||||
src/headers/macro-action-replay-buffer.hpp
|
||||
src/headers/macro-action-run.hpp
|
||||
src/headers/macro-action-scene-order.hpp
|
||||
src/headers/macro-action-scene-switch.hpp
|
||||
src/headers/macro-action-scene-transform.hpp
|
||||
src/headers/macro-action-scene-visibility.hpp
|
||||
src/headers/macro-action-source.hpp
|
||||
src/headers/macro-action-streaming.hpp
|
||||
src/headers/macro-action-virtual-cam.hpp
|
||||
src/headers/macro-action-wait.hpp
|
||||
src/headers/macro-condition-edit.hpp
|
||||
src/headers/macro-condition-audio.hpp
|
||||
src/headers/macro-condition-cursor.hpp
|
||||
src/headers/macro-condition-date.hpp
|
||||
src/headers/macro-condition-file.hpp
|
||||
src/headers/macro-condition-filter.hpp
|
||||
src/headers/macro-condition-hotkey.hpp
|
||||
src/headers/macro-condition-idle.hpp
|
||||
src/headers/macro-condition-macro.hpp
|
||||
src/headers/macro-condition-media.hpp
|
||||
src/headers/macro-condition-plugin-state.hpp
|
||||
src/headers/macro-condition-process.hpp
|
||||
src/headers/macro-condition-recording.hpp
|
||||
src/headers/macro-condition-replay-buffer.hpp
|
||||
src/headers/macro-condition-scene-order.hpp
|
||||
src/headers/macro-condition-scene.hpp
|
||||
src/headers/macro-condition-source.hpp
|
||||
src/headers/macro-condition-streaming.hpp
|
||||
src/headers/macro-condition-timer.hpp
|
||||
src/headers/macro-condition-video.hpp
|
||||
src/headers/macro-condition-virtual-cam.hpp
|
||||
src/headers/macro-condition-window.hpp
|
||||
src/headers/macro.hpp
|
||||
src/headers/macro-controls.hpp
|
||||
src/headers/macro-segment.hpp
|
||||
src/headers/macro-selection.hpp
|
||||
src/headers/curl-helper.hpp
|
||||
src/headers/hotkey.hpp
|
||||
src/headers/scene-selection.hpp
|
||||
src/headers/screenshot-helper.hpp
|
||||
src/headers/name-dialog.hpp
|
||||
src/headers/duration-control.hpp
|
||||
src/headers/section.hpp
|
||||
src/headers/platform-funcs.hpp
|
||||
src/headers/utility.hpp
|
||||
src/headers/volume-control.hpp
|
||||
src/headers/version.h)
|
||||
|
||||
set(advanced-scene-switcher_SOURCES
|
||||
${advanced-scene-switcher_SOURCES}
|
||||
src/advanced-scene-switcher.cpp
|
||||
src/advanced-scene-switcher-module.c
|
||||
src/switcher-data-structs.cpp
|
||||
src/scene-group.cpp
|
||||
src/scene-trigger.cpp
|
||||
src/switch-transitions.cpp
|
||||
src/switch-screen-region.cpp
|
||||
src/switch-priority.cpp
|
||||
src/switch-executable.cpp
|
||||
src/switch-idle.cpp
|
||||
src/switch-sequence.cpp
|
||||
src/switch-file.cpp
|
||||
src/switch-window.cpp
|
||||
src/switch-media.cpp
|
||||
src/switch-network.cpp
|
||||
src/hotkey.cpp
|
||||
src/general.cpp
|
||||
src/switch-pause.cpp
|
||||
src/switch-random.cpp
|
||||
src/switch-time.cpp
|
||||
src/switch-audio.cpp
|
||||
src/switch-video.cpp
|
||||
src/switch-generic.cpp
|
||||
src/macro-action-edit.cpp
|
||||
src/macro-action-audio.cpp
|
||||
src/macro-action-file.cpp
|
||||
src/macro-action-filter.cpp
|
||||
src/macro-action-hotkey.cpp
|
||||
src/macro-action-macro.cpp
|
||||
src/macro-action-media.cpp
|
||||
src/macro-action-plugin-state.cpp
|
||||
src/macro-action-recording.cpp
|
||||
src/macro-action-replay-buffer.cpp
|
||||
src/macro-action-run.cpp
|
||||
src/macro-action-scene-order.cpp
|
||||
src/macro-action-scene-switch.cpp
|
||||
src/macro-action-scene-transform.cpp
|
||||
src/macro-action-scene-visibility.cpp
|
||||
src/macro-action-source.cpp
|
||||
src/macro-action-streaming.cpp
|
||||
src/macro-action-virtual-cam.cpp
|
||||
src/macro-action-wait.cpp
|
||||
src/macro-condition-edit.cpp
|
||||
src/macro-condition-audio.cpp
|
||||
src/macro-condition-cursor.cpp
|
||||
src/macro-condition-date.cpp
|
||||
src/macro-condition-file.cpp
|
||||
src/macro-condition-filter.cpp
|
||||
src/macro-condition-hotkey.cpp
|
||||
src/macro-condition-idle.cpp
|
||||
src/macro-condition-macro.cpp
|
||||
src/macro-condition-media.cpp
|
||||
src/macro-condition-plugin-state.cpp
|
||||
src/macro-condition-process.cpp
|
||||
src/macro-condition-recording.cpp
|
||||
src/macro-condition-replay-buffer.cpp
|
||||
src/macro-condition-scene-order.cpp
|
||||
src/macro-condition-scene.cpp
|
||||
src/macro-condition-source.cpp
|
||||
src/macro-condition-streaming.cpp
|
||||
src/macro-condition-timer.cpp
|
||||
src/macro-condition-video.cpp
|
||||
src/macro-condition-virtual-cam.cpp
|
||||
src/macro-condition-window.cpp
|
||||
src/macro.cpp
|
||||
src/macro-controls.cpp
|
||||
src/macro-segment.cpp
|
||||
src/macro-selection.cpp
|
||||
src/macro-tab.cpp
|
||||
src/curl-helper.cpp
|
||||
src/scene-selection.cpp
|
||||
src/screenshot-helper.cpp
|
||||
src/name-dialog.cpp
|
||||
src/duration-control.cpp
|
||||
src/section.cpp
|
||||
src/utility.cpp
|
||||
src/volume-control.cpp
|
||||
src/version.cpp)
|
||||
|
||||
add_library(
|
||||
advanced-scene-switcher MODULE
|
||||
${advanced-scene-switcher_HEADERS}
|
||||
${advanced-scene-switcher_SOURCES}
|
||||
${advanced-scene-switcher_UI_HEADERS}
|
||||
${advanced-scene-switcher_PLATFORM_SOURCES}
|
||||
${advanced-scene-switcher_PLATFORM_HEADERS})
|
||||
|
||||
# Out of tree build
|
||||
if(BUILD_OUT_OF_TREE)
|
||||
include_directories(
|
||||
"${LIBOBS_INCLUDE_DIRS}"
|
||||
"${LIBOBS_FRONTEND_INCLUDE_DIR}"
|
||||
${Qt5Core_INCLUDES}
|
||||
${Qt5Widgets_INCLUDES}
|
||||
${LIBCURL_INCLUDE_DIRS})
|
||||
target_link_libraries(
|
||||
advanced-scene-switcher ${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
${LIBOBS_LIB} ${LIBOBS_FRONTEND_API_LIB} Qt5::Core Qt5::Widgets)
|
||||
|
||||
target_link_libraries(advanced-scene-switcher
|
||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
${LIBOBS_LIB}
|
||||
${LIBOBS_FRONTEND_API_LIB}
|
||||
Qt5::Core
|
||||
Qt5::Widgets)
|
||||
# Additional commands to install the module in the correct place. Find all the
|
||||
# translation files so we can copy them to the correct place later on.
|
||||
file(GLOB ASS_TRANSLATION_FILES "data/locale/*.ini")
|
||||
|
||||
# Additional commands to install the module in the correct place.
|
||||
# Find all the translation files so we can copy them to the correct
|
||||
# place later on.
|
||||
file(GLOB ASS_TRANSLATION_FILES
|
||||
"data/locale/*.ini"
|
||||
)
|
||||
# OSX
|
||||
if(APPLE)
|
||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||
endif()
|
||||
|
||||
# Windows
|
||||
if(WIN32)
|
||||
string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
message("${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
||||
find_package(w32-pthreads REQUIRED)
|
||||
|
||||
target_link_libraries(advanced-scene-switcher
|
||||
w32-pthreads)
|
||||
endif()
|
||||
|
||||
# OSX
|
||||
if(APPLE)
|
||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||
endif()
|
||||
|
||||
# Linux
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(CMAKE_C_FLAGS "-Wall -Wextra -Wvla -Wno-unused-function -Werror-implicit-function-declaration -Wno-missing-braces -Wno-missing-field-initializers ${CMAKE_C_FLAGS} -std=c99 -fno-strict-aliasing")
|
||||
|
||||
if(ARCH EQUAL 64)
|
||||
set(ARCH_NAME "x86_64")
|
||||
else()
|
||||
set(ARCH_NAME "i686")
|
||||
endif()
|
||||
|
||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||
|
||||
install(TARGETS advanced-scene-switcher
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/obs-plugins)
|
||||
install(FILES ${ASS_TRANSLATION_FILES}
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/obs/obs-plugins/advanced-scene-switcher/locale")
|
||||
endif()
|
||||
# Linux
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(ARCH EQUAL 64)
|
||||
set(ARCH_NAME "x86_64")
|
||||
else()
|
||||
set(ARCH_NAME "i686")
|
||||
endif()
|
||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||
install(TARGETS advanced-scene-switcher
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/obs-plugins)
|
||||
install(
|
||||
FILES ${ASS_TRANSLATION_FILES}
|
||||
DESTINATION
|
||||
"${CMAKE_INSTALL_PREFIX}/share/obs/obs-plugins/advanced-scene-switcher/locale"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(advanced-scene-switcher
|
||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
obs-frontend-api
|
||||
Qt5::Widgets
|
||||
libobs)
|
||||
|
||||
install_obs_plugin_with_data(advanced-scene-switcher data)
|
||||
# In tree build
|
||||
target_link_libraries(
|
||||
advanced-scene-switcher ${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
obs-frontend-api Qt5::Widgets libobs)
|
||||
install_obs_plugin_with_data(advanced-scene-switcher data)
|
||||
endif()
|
||||
|
||||
126
README.md
126
README.md
@@ -1,119 +1,27 @@
|
||||
# SceneSwitcher
|
||||
An automated scene switcher for OBS Studio
|
||||
|
||||
More information can be found on https://obsproject.com/forum/resources/automatic-scene-switching.395/ and see https://github.com/WarmUpTill/SceneSwitcher/blob/master/CI/release/README.txt for installing releases.
|
||||
More information can be found on https://obsproject.com/forum/resources/automatic-scene-switching.395/.
|
||||
|
||||
## Compiling in tree (recommended)
|
||||
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
|
||||
## Downloads
|
||||
|
||||
Binaries for Windows, MacOS, and Linux are available in the [Releases](https://github.com/WarmUpTill/SceneSwitcher/releases) section.
|
||||
|
||||
## Installing the plugin
|
||||
|
||||
For the Windows and MacOS platforms, it is recommended to run the provided installers.
|
||||
|
||||
For Linux the Snap package manager offers an OBS Studio installation which is bundled with the plugin:
|
||||
```
|
||||
cd obs-studio/UI/frontend-plugins/
|
||||
git clone https://github.com/WarmUpTill/SceneSwitcher.git
|
||||
sudo snap install obs-studi
|
||||
```
|
||||
|
||||
Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt file and add an entry for the scene switcher:
|
||||
add_subdirectory(SceneSwitcher)
|
||||
If that is not an option you will have to ...
|
||||
1. Copy the library to the plugins folder of you obs installation.
|
||||
2. Copy the contents of the data directory to its respective folders of your obs installation.
|
||||
|
||||
## Compiling out of tree
|
||||
### Prerequisites
|
||||
You'll need CMake and a working development environment for OBS Studio installed
|
||||
on your computer. Once you've done that, do the following:
|
||||
```
|
||||
git clone https://github.com/WarmUpTill/SceneSwitcher.git
|
||||
cd SceneSwitcher
|
||||
mkdir build && cd build
|
||||
```
|
||||
Unfortunately the exact location of these folders may vary from system to system.
|
||||
|
||||
### Windows
|
||||
In cmake-gui, you'll have to set these CMake variables :
|
||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||
code of OBS Studio, located at [source_directory]/libobs/.
|
||||
- **LIBOBS_LIB** (filepath) : location of the obs.dll file (usually set to
|
||||
C:\Program Files\obs-studio\bin\64bit\obs.dll)
|
||||
## Compiling the plugin
|
||||
|
||||
Assuming that you installed Qt via the regular Qt App way:
|
||||
- **Qt5Core_DIR** (path) : C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Core
|
||||
- **Qt5Gui_DIR** (path): C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Gui
|
||||
- **Qt5Widgets_DIR** (path) : C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Widgets
|
||||
|
||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.dll
|
||||
file, usually C:/Program Files/obs-studio/bin/64bit/obs-frontend-api.dll
|
||||
(usually in the same place as LIBOBS_LIB)
|
||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
||||
subfolder in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
||||
|
||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||
|
||||
### Linux
|
||||
Most versions of Linux you can use cmake-gui or the command line.
|
||||
|
||||
**For the command line:**
|
||||
```
|
||||
cmake -DBUILD_OUT_OF_TREE=1 -DLIBOBS_INCLUDE_DIR="<path to the libobs/ sub-folder in obs-studio's source code>" \
|
||||
-DLIBOBS_FRONTEND_INCLUDE_DIR="<path to the UI/obs-frontend-api/ sub-folder in obs-studio's source code>" \
|
||||
-DLIBOBS_LIB="<path to the libobs.so file>" \
|
||||
-DLIBOBS_FRONTEND_API_LIB="<path to the libobs-frontend-api.so file (usually in the same place as LIBOBS_LIB)>" \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
|
||||
For cmake-gui you'll have to set the following variables:
|
||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||
code of OBS Studio, located at [source_directory]/libobs/.
|
||||
- **LIBOBS_LIB** (filepath) : location of the libobs.so file (usually CMake finds
|
||||
this, but if not it'll usually be in /usr/lib/libobs.so)
|
||||
|
||||
Assuming that you installed Qt via your system package manager, it should be
|
||||
found automatically. If not, then usually you'll find it in something like:
|
||||
- **Qt5Core_DIR** (path) : /usr/lib64/cmake/Qt5Core
|
||||
- **Qt5Gui_DIR** (path): /usr/lib64/cmake/Qt5Gui
|
||||
- **Qt5Widgets_DIR** (path) : /usr/lib64/cmake/Qt5Widgets
|
||||
|
||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.so
|
||||
file (usually in the same place as LIBOBS_LIB)
|
||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
||||
subfolder in the source code of OBS Studio, located at
|
||||
[source_directory]/UI/obs-frontend-api.
|
||||
|
||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||
|
||||
Then open a terminal in the build folder and type:
|
||||
```
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
NOTE: The Linux version of this plugin is dependent on libXScrnSaver.
|
||||
|
||||
### OS X
|
||||
In cmake-gui, you'll have to set these CMake variables :
|
||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||
code of OBS Studio, located at [source_directory]/libobs/.
|
||||
- **LIBOBS_LIB** (filepath) : location of the libobs.0.dylib file (usually
|
||||
in /Applications/OBS.app/Contents/Resources/bin/libobs.0.dylib)
|
||||
|
||||
Assuming that you installed Qt via the regular Qt App way:
|
||||
- **Qt5Core_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Core
|
||||
- **Qt5Widgets_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Widgets
|
||||
- **Qt5MacExtras_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5MacExtras
|
||||
|
||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.0.dylib
|
||||
file (usually in usually in /Applications/OBS.app/Contents/Resources/bin/libobs-frontend-api.0.dylib)
|
||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api subfolder
|
||||
in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
||||
|
||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||
|
||||
Open xcode (or a terminal, depending on the build type you chose), build and copy
|
||||
the advanced-scene-switcher.so file to /Applications/OBS.app/Contents/PlugIns
|
||||
|
||||
Note that you might have to adjust the library search paths using the install_name_tool if you want the plugin to run on machines other than your build machine:
|
||||
```
|
||||
install_name_tool -change @rpath/libobs-frontend-api.dylib @executable_path/../Frameworks/libobs-frontend-api.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change /usr/local/opt/qt5/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change /usr/local/opt/qt5/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change /usr/local/opt/qt5/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
```
|
||||
See the [build instructions](BUILDING.md).
|
||||
|
||||
@@ -284,6 +284,8 @@ AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="Audio Quelle stu
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="Audio Quelle aktiv schalten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="Szenenwechsler starten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="Szenenwechsler stoppen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="Virtuelle Kamera starten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Virtuelle Kamera stoppen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.entry="Wenn {{scenes}} {{triggers}} {{actions}} {{audioSources}} nach {{duration}} "
|
||||
AdvSceneSwitcher.sceneTriggerTab.help="Dieser Tab ermöglicht es automatisiert Handlungen, wie etwa das Stoppen von einer Aufnahme oder des Streamens, bei einem Szenenwechsel auszuführen."
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@ AdvSceneSwitcher.macroTab.name="Name:"
|
||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||
AdvSceneSwitcher.macroTab.exists="Macro name exists already"
|
||||
AdvSceneSwitcher.macroTab.copy="Create copy"
|
||||
AdvSceneSwitcher.macroTab.expandAll="Expand all"
|
||||
AdvSceneSwitcher.macroTab.collapseAll="Collapse all"
|
||||
|
||||
; Macro Logic
|
||||
AdvSceneSwitcher.logic.none="Ignore entry"
|
||||
@@ -83,15 +85,20 @@ AdvSceneSwitcher.condition.audio="Audio"
|
||||
AdvSceneSwitcher.condition.audio.state.below="Below"
|
||||
AdvSceneSwitcher.condition.audio.state.above="Above"
|
||||
AdvSceneSwitcher.condition.audio.entry="Volume of {{audioSources}} is {{condition}} {{volume}}"
|
||||
AdvSceneSwitcher.condition.region="Screen region"
|
||||
AdvSceneSwitcher.condition.region.entry="Cursor is in {{minX}} {{minY}} x {{maxX}} {{maxY}}"
|
||||
AdvSceneSwitcher.condition.cursor="Cursor"
|
||||
AdvSceneSwitcher.condition.cursor.type.region="is in region"
|
||||
AdvSceneSwitcher.condition.cursor.type.moving="is moving"
|
||||
AdvSceneSwitcher.condition.cursor.showFrame="Show frame"
|
||||
AdvSceneSwitcher.condition.cursor.hideFrame="Hide frame"
|
||||
AdvSceneSwitcher.condition.cursor.entry.line1="Cursor is {{conditions}} {{minX}} {{minY}} {{maxX}} {{maxY}} - {{toggleFrameButton}}"
|
||||
AdvSceneSwitcher.condition.cursor.entry.line2="Cursor is currently at {{xPos}} x {{yPos}}"
|
||||
AdvSceneSwitcher.condition.scene="Scene"
|
||||
AdvSceneSwitcher.condition.scene.type.current="Current"
|
||||
AdvSceneSwitcher.condition.scene.type.previous="Previous"
|
||||
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} scene is {{scenes}}"
|
||||
AdvSceneSwitcher.condition.window="Window"
|
||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} exist and ..."
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused"
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused {{windowFocusChanged}} foreground window changed"
|
||||
AdvSceneSwitcher.condition.file="File"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="Content of {{fileType}} {{filePath}} {{browseButton}} matches:"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
@@ -124,19 +131,22 @@ AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for {{duratio
|
||||
AdvSceneSwitcher.condition.pluginState="Plugin state"
|
||||
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene change was triggered in this interval"
|
||||
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
|
||||
AdvSceneSwitcher.condition.virtDesktop="Virtual desktop"
|
||||
AdvSceneSwitcher.condition.virtDesktop.notAvailable="Not availbale"
|
||||
AdvSceneSwitcher.condition.virtDesktop.entry.line1="Active virtual desktop is {{virtDesktops}}"
|
||||
AdvSceneSwitcher.condition.virtDesktop.entry.line2="Current: {{currentDesktop}}"
|
||||
AdvSceneSwitcher.condition.interval="Interval"
|
||||
AdvSceneSwitcher.condition.interval.entry="{{duration}} have passed"
|
||||
AdvSceneSwitcher.condition.counter="Count"
|
||||
AdvSceneSwitcher.condition.counter.type.below="Less than"
|
||||
AdvSceneSwitcher.condition.counter.type.above="More than"
|
||||
AdvSceneSwitcher.condition.counter.type.equal="Exactly"
|
||||
AdvSceneSwitcher.condition.counter.reset="Reset"
|
||||
AdvSceneSwitcher.condition.counter.entry.line1="{{macros}} was executed {{conditions}} {{count}} times"
|
||||
AdvSceneSwitcher.condition.counter.entry.line2="Current count: {{currentCount}} {{resetCount}}"
|
||||
AdvSceneSwitcher.condition.timer="Timer"
|
||||
AdvSceneSwitcher.condition.timer.entry.line1="{{duration}} have passed"
|
||||
AdvSceneSwitcher.condition.timer.entry.line2="Time remaining: {{remaining}} seconds"
|
||||
AdvSceneSwitcher.condition.timer.entry.line3="{{reset}} {{autoReset}} Automatically reset timer after duration was reached"
|
||||
AdvSceneSwitcher.condition.timer.reset="Reset"
|
||||
AdvSceneSwitcher.condition.macro="Macro"
|
||||
AdvSceneSwitcher.condition.macro.type.count="Count"
|
||||
AdvSceneSwitcher.condition.macro.type.state="State"
|
||||
AdvSceneSwitcher.condition.macro.type.selection="Condition type: {{types}}"
|
||||
AdvSceneSwitcher.condition.macro.count.type.below="Less than"
|
||||
AdvSceneSwitcher.condition.macro.count.type.above="More than"
|
||||
AdvSceneSwitcher.condition.macro.count.type.equal="Exactly"
|
||||
AdvSceneSwitcher.condition.macro.count.reset="Reset"
|
||||
AdvSceneSwitcher.condition.macro.state.entry="Conditions of {{macros}} are true"
|
||||
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} was executed {{conditions}} {{count}} times"
|
||||
AdvSceneSwitcher.condition.macro.count.entry.line2="Current count: {{currentCount}} {{resetCount}}"
|
||||
AdvSceneSwitcher.condition.source="Source"
|
||||
AdvSceneSwitcher.condition.source.type.active="Is active"
|
||||
AdvSceneSwitcher.condition.source.type.showing="Is showing"
|
||||
@@ -146,6 +156,41 @@ AdvSceneSwitcher.condition.source.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
|
||||
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.source.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.virtualCamera="Virtual camera"
|
||||
AdvSceneSwitcher.condition.virtualCamera.state.start="Virtual camera started"
|
||||
AdvSceneSwitcher.condition.virtualCamera.state.stop="Virtual camera stopped"
|
||||
AdvSceneSwitcher.condition.virtualCamera.entry="{{states}}"
|
||||
AdvSceneSwitcher.condition.filter="Filter"
|
||||
AdvSceneSwitcher.condition.filter.type.active="Is enabled"
|
||||
AdvSceneSwitcher.condition.filter.type.showing="Is disabled"
|
||||
AdvSceneSwitcher.condition.filter.type.settings="Settings match"
|
||||
AdvSceneSwitcher.condition.filter.regex="Use regular expressions"
|
||||
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.condition.filter.entry.line1="On {{sources}} {{filters}} {{conditions}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.sceneOrder="Scene item order"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.above="Is above"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.below="Is below"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.position="Is at position"
|
||||
AdvSceneSwitcher.condition.sceneOrder.positionInfo="The position value starts at the bottom with 0 and increases by one for each scene item including the ones in scene groups"
|
||||
AdvSceneSwitcher.condition.sceneOrder.entry="On {{scenes}} {{sources}} {{conditions}} {{sources2}} {{position}}"
|
||||
AdvSceneSwitcher.condition.hotkey="Hotkey"
|
||||
AdvSceneSwitcher.condition.hotkey.name="Macro trigger hotkey"
|
||||
AdvSceneSwitcher.condition.hotkey.tip="Note: You can configure the keybindings for this hotkey in the OBS settings window"
|
||||
AdvSceneSwitcher.condition.hotkey.entry="Name: {{name}}"
|
||||
AdvSceneSwitcher.condition.replay="Replay buffer"
|
||||
AdvSceneSwitcher.condition.replay.state.stopped="Replay buffer stopped"
|
||||
AdvSceneSwitcher.condition.replay.state.started="Replay buffer started"
|
||||
AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved"
|
||||
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||
AdvSceneSwitcher.condition.date="Date"
|
||||
AdvSceneSwitcher.condition.date.state.at="At"
|
||||
AdvSceneSwitcher.condition.date.state.after="After"
|
||||
AdvSceneSwitcher.condition.date.state.before="Before"
|
||||
AdvSceneSwitcher.condition.date.state.between="Between"
|
||||
AdvSceneSwitcher.condition.date.entry.line1="{{condition}} {{dateTime}} {{dateTime2}} {{ignoreDate}} Ignore date component {{ignoreTime}} Ignore time component"
|
||||
AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Reschedule {{duration}} later when matching"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Switch scene"
|
||||
@@ -178,6 +223,9 @@ AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Start streaming"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="Run"
|
||||
AdvSceneSwitcher.action.run.arguments="Arguments:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Add argument"
|
||||
AdvSceneSwitcher.action.run.addArgumentDescription="Add new argument:"
|
||||
AdvSceneSwitcher.action.run.entry="Run {{filePath}} {{browseButton}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
||||
@@ -186,7 +234,9 @@ AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sourc
|
||||
AdvSceneSwitcher.action.filter="Filter"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Enable"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Disable"
|
||||
AdvSceneSwitcher.action.filter.type.settings="Set settings"
|
||||
AdvSceneSwitcher.action.filter.entry="On {{sources}} {{actions}} {{filters}}"
|
||||
AdvSceneSwitcher.action.filter.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.action.source="Source"
|
||||
AdvSceneSwitcher.action.source.type.enable="Enable"
|
||||
AdvSceneSwitcher.action.source.type.disable="Disable"
|
||||
@@ -209,7 +259,37 @@ AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Plugin state"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
|
||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
|
||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}} {{values}} {{scenes}}"
|
||||
AdvSceneSwitcher.action.virtualCamera="Virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Stop virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.type.start="Start virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.hotkey="Hotkey"
|
||||
AdvSceneSwitcher.action.hotkey.leftShift="Left Shift"
|
||||
AdvSceneSwitcher.action.hotkey.rightShift="Right Shift"
|
||||
AdvSceneSwitcher.action.hotkey.leftCtrl="Left Ctrl"
|
||||
AdvSceneSwitcher.action.hotkey.rightCtrl="Right Ctrl"
|
||||
AdvSceneSwitcher.action.hotkey.leftAlt="Left Alt"
|
||||
AdvSceneSwitcher.action.hotkey.rightAlt="Right Alt"
|
||||
AdvSceneSwitcher.action.hotkey.leftMeta="Left Meta"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Right Meta"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate key presses - functionality disabled!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}}"
|
||||
AdvSceneSwitcher.action.sceneOrder="Scene item order"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Move up"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Move to top"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Move to bottom"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Move to position"
|
||||
AdvSceneSwitcher.action.sceneOrder.entry="On {{scenes}} {{actions}} {{sources}} {{position}}"
|
||||
AdvSceneSwitcher.action.sceneTransform="Scene item transform"
|
||||
AdvSceneSwitcher.action.sceneTransform.getTransform="Get transform"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="On {{scenes}} transform {{sources}}"
|
||||
AdvSceneSwitcher.action.file="File"
|
||||
AdvSceneSwitcher.action.file.type.write="Write"
|
||||
AdvSceneSwitcher.action.file.type.append="Append"
|
||||
AdvSceneSwitcher.action.file.entry="{{actions}} to {{filePath}} {{browseButton}}:"
|
||||
|
||||
; Transition Tab
|
||||
AdvSceneSwitcher.transitionTab.title="Transition"
|
||||
@@ -381,6 +461,7 @@ AdvSceneSwitcher.videoTab.help="<html><head/><body><p>This tab will allow you to
|
||||
|
||||
; Network Tab
|
||||
AdvSceneSwitcher.networkTab.title="Network"
|
||||
AdvSceneSwitcher.networkTab.description="This tab will allow you to remotely control the active scene of another OBS instance.\nPlease note that the scene names have to match exactly on all OBS instances."
|
||||
AdvSceneSwitcher.networkTab.warning="Running the server outside of a local network will allow third parties to read the active scene."
|
||||
AdvSceneSwitcher.networkTab.DisabledWarning="This functionality unfortunately had to be disabled on macOS due to library incompatibilities when running the obs-websocket plugin in parallel."
|
||||
AdvSceneSwitcher.networkTab.server="Start server (Sends scene switch messages to all connected clients)"
|
||||
@@ -443,6 +524,8 @@ AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="mute source"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="unmute source"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="start the scene switcher"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="stop the scene switcher"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="start virtual camera"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="stop virtual camera"
|
||||
AdvSceneSwitcher.sceneTriggerTab.entry="When {{scenes}} {{triggers}} {{actions}} {{audioSources}} after {{duration}}"
|
||||
AdvSceneSwitcher.sceneTriggerTab.help="This tab allows you to trigger actions on scene changes, like stopping recording or streaming."
|
||||
|
||||
@@ -460,6 +543,8 @@ AdvSceneSwitcher.browse="Browse"
|
||||
|
||||
AdvSceneSwitcher.selectScene="--select scene--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||
AdvSceneSwitcher.selectAnyScene="Any Scene"
|
||||
AdvSceneSwitcher.currentTransition="Current Transition"
|
||||
AdvSceneSwitcher.selectTransition="--select transition--"
|
||||
AdvSceneSwitcher.selectWindow="--select window--"
|
||||
|
||||
@@ -81,8 +81,7 @@ AdvSceneSwitcher.condition.audio="Аудио"
|
||||
AdvSceneSwitcher.ondition.audio.state.below="Ниже"
|
||||
AdvSceneSwitcher.ondition.audio.state.above="Выше"
|
||||
AdvSceneSwitcher.condition.audio.entry="Громкость {{audioSources}} равна {{condition}} {{volume}} в течении {{duration}} секунд"
|
||||
AdvSceneSwitcher.condition.region="Область экрана"
|
||||
AdvSceneSwitcher.condition.region.entry="Курсор находится в {{minX}} {{minY}} x {{maxX}} {{maxY}}"
|
||||
AdvSceneSwitcher.condition.cursor="Область экрана"
|
||||
AdvSceneSwitcher.condition.scene="Сцена"
|
||||
AdvSceneSwitcher.condition.scene.type.current="Текущий"
|
||||
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
|
||||
|
||||
@@ -693,13 +693,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_65">
|
||||
<property name="orientation">
|
||||
@@ -3723,6 +3716,13 @@
|
||||
<string>AdvSceneSwitcher.networkTab.title</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_30">
|
||||
<item>
|
||||
<widget class="QLabel" name="networkTabDescription">
|
||||
<property name="text">
|
||||
<string>AdvSceneSwitcher.networkTab.description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="networkTabWarningLabel">
|
||||
<property name="text">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <QMainWindow>
|
||||
#include <QAction>
|
||||
#include <QFileDialog>
|
||||
#include <regex>
|
||||
|
||||
#include <obs-module.h>
|
||||
#include <obs-frontend-api.h>
|
||||
@@ -199,6 +200,7 @@ void SwitcherData::Thread()
|
||||
if (checkPause()) {
|
||||
continue;
|
||||
}
|
||||
setPreconditions();
|
||||
match = checkForMatch(scene, transition, linger,
|
||||
setPrevSceneAfterLinger, macroMatch);
|
||||
if (stop) {
|
||||
@@ -252,6 +254,37 @@ void SwitcherData::Thread()
|
||||
blog(LOG_INFO, "stopped");
|
||||
}
|
||||
|
||||
void SwitcherData::setPreconditions()
|
||||
{
|
||||
// Window title
|
||||
lastTitle = currentTitle;
|
||||
std::string title;
|
||||
GetCurrentWindowTitle(title);
|
||||
for (auto &window : ignoreWindowsSwitches) {
|
||||
bool equals = (title == window);
|
||||
bool matches = false;
|
||||
if (!equals) {
|
||||
try {
|
||||
std::regex expr(window);
|
||||
matches = std::regex_match(title, expr);
|
||||
|
||||
} catch (const std::regex_error &) {
|
||||
}
|
||||
}
|
||||
if (equals || matches) {
|
||||
title = lastTitle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentTitle = title;
|
||||
|
||||
// Cursor
|
||||
std::pair<int, int> cursorPos = getCursorPos();
|
||||
cursorPosChanged = cursorPos.first != switcher->lastCursorPos.first ||
|
||||
cursorPos.second != switcher->lastCursorPos.second;
|
||||
lastCursorPos = getCursorPos();
|
||||
}
|
||||
|
||||
bool SwitcherData::checkForMatch(OBSWeakSource &scene,
|
||||
OBSWeakSource &transition, int &linger,
|
||||
bool &setPrevSceneAfterLinger,
|
||||
@@ -327,7 +360,8 @@ void switchScene(const sceneSwitchInfo &sceneSwitch)
|
||||
}
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene);
|
||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||
obs_source_t *currentSource =
|
||||
obs_weak_source_get_source(switcher->currentScene);
|
||||
|
||||
if (source && source != currentSource) {
|
||||
transitionData currentTransitionData;
|
||||
@@ -390,8 +424,9 @@ void SwitcherData::Stop()
|
||||
{
|
||||
if (th && th->isRunning()) {
|
||||
stop = true;
|
||||
transitionCv.notify_one();
|
||||
cv.notify_one();
|
||||
abortMacroWait = true;
|
||||
macroWaitCv.notify_one();
|
||||
th->wait();
|
||||
delete th;
|
||||
th = nullptr;
|
||||
@@ -433,6 +468,8 @@ extern "C" void FreeSceneSwitcher()
|
||||
loaded_curl_lib = nullptr;
|
||||
}
|
||||
|
||||
PlatformCleanup();
|
||||
|
||||
delete switcher;
|
||||
switcher = nullptr;
|
||||
}
|
||||
@@ -444,15 +481,21 @@ void handleSceneChange()
|
||||
switcher->cv.notify_one();
|
||||
}
|
||||
|
||||
// Set previous scene
|
||||
// Set current and previous scene
|
||||
obs_source_t *source = obs_frontend_get_current_scene();
|
||||
obs_weak_source_t *ws = obs_source_get_weak_source(source);
|
||||
|
||||
if (ws && ws != switcher->currentScene) {
|
||||
switcher->previousScene = switcher->currentScene;
|
||||
switcher->currentScene = ws;
|
||||
vblog(LOG_INFO, "current scene: %s",
|
||||
GetWeakSourceName(switcher->currentScene).c_str());
|
||||
vblog(LOG_INFO, "previous scene: %s",
|
||||
GetWeakSourceName(switcher->previousScene).c_str());
|
||||
}
|
||||
|
||||
obs_source_release(source);
|
||||
obs_weak_source_release(ws);
|
||||
if (source && switcher->previousSceneHelper != ws) {
|
||||
switcher->previousScene = switcher->previousSceneHelper;
|
||||
switcher->previousSceneHelper = ws;
|
||||
}
|
||||
|
||||
switcher->checkTriggers();
|
||||
switcher->checkDefaultSceneTransitions();
|
||||
@@ -497,6 +540,11 @@ void handlePeviewSceneChange()
|
||||
}
|
||||
}
|
||||
|
||||
void setReplayBufferSaved()
|
||||
{
|
||||
switcher->replayBufferSaved = true;
|
||||
}
|
||||
|
||||
// Note to future self:
|
||||
// be careful using switcher->m here as there is potential for deadlocks when using
|
||||
// frontend functions such as obs_frontend_set_current_scene()
|
||||
@@ -528,6 +576,9 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
||||
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
|
||||
resetLiveTime();
|
||||
break;
|
||||
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
|
||||
setReplayBufferSaved();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -546,6 +597,8 @@ extern "C" void InitSceneSwitcher()
|
||||
switcher->curl = f_curl_init();
|
||||
}
|
||||
|
||||
PlatformInit();
|
||||
|
||||
auto cb = []() {
|
||||
QMainWindow *window =
|
||||
(QMainWindow *)obs_frontend_get_main_window();
|
||||
|
||||
@@ -33,6 +33,17 @@ bool resolveCurl()
|
||||
|
||||
bool loadCurl()
|
||||
{
|
||||
loaded_curl_lib = new QLibrary(curl_library_name, nullptr);
|
||||
if (resolveCurl()) {
|
||||
blog(LOG_INFO, "[adv-ss] found curl library");
|
||||
return true;
|
||||
} else {
|
||||
delete loaded_curl_lib;
|
||||
loaded_curl_lib = nullptr;
|
||||
blog(LOG_WARNING,
|
||||
"[adv-ss] couldn't find the curl library in PATH");
|
||||
}
|
||||
|
||||
QStringList locations;
|
||||
locations << QDir::currentPath();
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
|
||||
@@ -32,6 +32,20 @@ bool Duration::DurationReached()
|
||||
return runTime.count() >= seconds * 1000;
|
||||
}
|
||||
|
||||
double Duration::TimeRemaining()
|
||||
{
|
||||
if (_startTime.time_since_epoch().count() == 0) {
|
||||
return seconds;
|
||||
}
|
||||
auto runTime = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::high_resolution_clock::now() - _startTime);
|
||||
|
||||
if (runTime.count() >= seconds * 1000) {
|
||||
return 0;
|
||||
}
|
||||
return (seconds * 1000 - runTime.count()) / 1000.;
|
||||
}
|
||||
|
||||
void Duration::Reset()
|
||||
{
|
||||
_startTime = {};
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
}
|
||||
|
||||
class QCloseEvent;
|
||||
class MacroActionEdit;
|
||||
class MacroConditionEdit;
|
||||
|
||||
/*******************************************************************************
|
||||
* Advanced Scene Switcher window
|
||||
@@ -47,6 +49,10 @@ public:
|
||||
bool addNewMacro(std::string &name);
|
||||
Macro *getSelectedMacro();
|
||||
void SetEditMacro(Macro &m);
|
||||
void ConnectControlSignals(MacroActionEdit *);
|
||||
void ConnectControlSignals(MacroConditionEdit *);
|
||||
void SwapActions(Macro *m, int pos1, int pos2);
|
||||
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||
|
||||
void loadUI();
|
||||
void setupGeneralTab();
|
||||
@@ -109,8 +115,22 @@ public slots:
|
||||
void on_conditionRemove_clicked();
|
||||
void on_actionAdd_clicked();
|
||||
void on_actionRemove_clicked();
|
||||
void showMacroContextMenu(const QPoint &);
|
||||
void copyMacro();
|
||||
void ShowMacroContextMenu(const QPoint &);
|
||||
void ShowMacroActionsContextMenu(const QPoint &);
|
||||
void ShowMacroConditionsContextMenu(const QPoint &);
|
||||
void CopyMacro();
|
||||
void ExpandAllActions();
|
||||
void ExpandAllConditions();
|
||||
void CollapseAllActions();
|
||||
void CollapseAllConditions();
|
||||
void AddMacroAction(int idx);
|
||||
void RemoveMacroAction(int idx);
|
||||
void MoveMacroActionUp(int idx);
|
||||
void MoveMacroActionDown(int idx);
|
||||
void AddMacroCondition(int idx);
|
||||
void RemoveMacroCondition(int idx);
|
||||
void MoveMacroConditionUp(int idx);
|
||||
void MoveMacroConditionDown(int idx);
|
||||
|
||||
void on_screenRegionSwitches_currentRowChanged(int idx);
|
||||
void on_showFrame_clicked();
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#if defined(WIN32)
|
||||
constexpr auto curl_library_name = "libcurl.dll";
|
||||
#elif __APPLE__
|
||||
#define curl_library_name "libcurl.4.dylib"
|
||||
constexpr auto curl_library_name = "libcurl.4.dylib";
|
||||
#else
|
||||
#define curl_library_name "libcurl.so.4"
|
||||
constexpr auto curl_library_name = "libcurl.so.4";
|
||||
#endif
|
||||
|
||||
typedef CURL *(*initFunction)(void);
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
const char *unitName = "displayUnit");
|
||||
|
||||
bool DurationReached();
|
||||
double TimeRemaining();
|
||||
void Reset();
|
||||
std::string ToString();
|
||||
|
||||
|
||||
125
src/headers/hotkey.hpp
Normal file
125
src/headers/hotkey.hpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#pragma once
|
||||
|
||||
extern bool canSimulateKeyPresses;
|
||||
|
||||
enum class HotkeyType {
|
||||
Key_NoKey = 0,
|
||||
|
||||
Key_A,
|
||||
Key_B,
|
||||
Key_C,
|
||||
Key_D,
|
||||
Key_E,
|
||||
Key_F,
|
||||
Key_G,
|
||||
Key_H,
|
||||
Key_I,
|
||||
Key_J,
|
||||
Key_K,
|
||||
Key_L,
|
||||
Key_M,
|
||||
Key_N,
|
||||
Key_O,
|
||||
Key_P,
|
||||
Key_Q,
|
||||
Key_R,
|
||||
Key_S,
|
||||
Key_T,
|
||||
Key_U,
|
||||
Key_V,
|
||||
Key_W,
|
||||
Key_X,
|
||||
Key_Y,
|
||||
Key_Z,
|
||||
|
||||
Key_0,
|
||||
Key_1,
|
||||
Key_2,
|
||||
Key_3,
|
||||
Key_4,
|
||||
Key_5,
|
||||
Key_6,
|
||||
Key_7,
|
||||
Key_8,
|
||||
Key_9,
|
||||
|
||||
Key_F1,
|
||||
Key_F2,
|
||||
Key_F3,
|
||||
Key_F4,
|
||||
Key_F5,
|
||||
Key_F6,
|
||||
Key_F7,
|
||||
Key_F8,
|
||||
Key_F9,
|
||||
Key_F10,
|
||||
Key_F11,
|
||||
Key_F12,
|
||||
Key_F13,
|
||||
Key_F14,
|
||||
Key_F15,
|
||||
Key_F16,
|
||||
Key_F17,
|
||||
Key_F18,
|
||||
Key_F19,
|
||||
Key_F20,
|
||||
Key_F21,
|
||||
Key_F22,
|
||||
Key_F23,
|
||||
Key_F24,
|
||||
|
||||
Key_Escape,
|
||||
Key_Space,
|
||||
Key_Return,
|
||||
Key_Backspace,
|
||||
Key_Tab,
|
||||
|
||||
Key_Shift_L,
|
||||
Key_Shift_R,
|
||||
Key_Control_L,
|
||||
Key_Control_R,
|
||||
Key_Alt_L,
|
||||
Key_Alt_R,
|
||||
Key_Win_L,
|
||||
Key_Win_R,
|
||||
Key_Apps,
|
||||
|
||||
Key_CapsLock,
|
||||
Key_NumLock,
|
||||
Key_ScrollLock,
|
||||
|
||||
Key_PrintScreen,
|
||||
Key_Pause,
|
||||
|
||||
Key_Insert,
|
||||
Key_Delete,
|
||||
Key_PageUP,
|
||||
Key_PageDown,
|
||||
Key_Home,
|
||||
Key_End,
|
||||
|
||||
Key_Left,
|
||||
Key_Right,
|
||||
Key_Up,
|
||||
Key_Down,
|
||||
|
||||
Key_Numpad0,
|
||||
Key_Numpad1,
|
||||
Key_Numpad2,
|
||||
Key_Numpad3,
|
||||
Key_Numpad4,
|
||||
Key_Numpad5,
|
||||
Key_Numpad6,
|
||||
Key_Numpad7,
|
||||
Key_Numpad8,
|
||||
Key_Numpad9,
|
||||
|
||||
Key_NumpadAdd,
|
||||
Key_NumpadSubtract,
|
||||
Key_NumpadMultiply,
|
||||
Key_NumpadDivide,
|
||||
Key_NumpadDecimal,
|
||||
Key_NumpadEnter
|
||||
};
|
||||
|
||||
void registerHotkeys();
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
enum class AudioAction {
|
||||
@@ -15,6 +16,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -51,6 +53,8 @@ private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void VolumeChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_audioSources;
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QGroupBox>
|
||||
#include <deque>
|
||||
#include "macro.hpp"
|
||||
#include "section.hpp"
|
||||
|
||||
struct MacroActionInfo {
|
||||
using TCreateMethod = std::shared_ptr<MacroAction> (*)();
|
||||
@@ -32,25 +25,23 @@ private:
|
||||
static std::map<std::string, MacroActionInfo> _methods;
|
||||
};
|
||||
|
||||
class MacroActionEdit : public QWidget {
|
||||
class MacroActionEdit : public MacroSegmentEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionEdit(QWidget *parent = nullptr,
|
||||
std::shared_ptr<MacroAction> * = nullptr,
|
||||
const std::string &id = "scene_switch",
|
||||
bool startCollapsed = false);
|
||||
void UpdateEntryData(const std::string &id, bool collapse);
|
||||
const std::string &id = "scene_switch");
|
||||
void UpdateEntryData(const std::string &id);
|
||||
|
||||
private slots:
|
||||
void ActionSelectionChanged(const QString &text);
|
||||
|
||||
protected:
|
||||
private:
|
||||
MacroSegment *Data();
|
||||
|
||||
QComboBox *_actionSelection;
|
||||
Section *_section;
|
||||
|
||||
std::shared_ptr<MacroAction> *_entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
66
src/headers/macro-action-file.hpp
Normal file
66
src/headers/macro-action-file.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
enum class FileAction {
|
||||
WRITE,
|
||||
APPEND,
|
||||
};
|
||||
|
||||
class MacroActionFile : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionFile>();
|
||||
}
|
||||
|
||||
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
std::string _text = obs_module_text("AdvSceneSwitcher.enterText");
|
||||
FileAction _action = FileAction::WRITE;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionFileEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionFileEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionFile> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionFileEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionFile>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void FilePathChanged();
|
||||
void BrowseButtonClicked();
|
||||
void TextChanged();
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QLineEdit *_filePath;
|
||||
QPushButton *_browseButton;
|
||||
QPlainTextEdit *_text;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionFile> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
enum class FilterAction {
|
||||
ENABLE,
|
||||
DISABLE,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
class MacroActionFilter : public MacroAction {
|
||||
@@ -13,6 +15,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -22,6 +25,7 @@ public:
|
||||
OBSWeakSource _source;
|
||||
OBSWeakSource _filter;
|
||||
FilterAction _action = FilterAction::ENABLE;
|
||||
std::string _settings = "";
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -48,14 +52,20 @@ private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void FilterChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
QComboBox *_filters;
|
||||
QComboBox *_actions;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
std::shared_ptr<MacroActionFilter> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
void SetWidgetVisibility(bool);
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
79
src/headers/macro-action-hotkey.hpp
Normal file
79
src/headers/macro-action-hotkey.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "hotkey.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
class MacroActionHotkey : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionHotkey>();
|
||||
}
|
||||
|
||||
OBSWeakSource _HotkeySource;
|
||||
HotkeyType _key = HotkeyType::Key_NoKey;
|
||||
bool _leftShift = false;
|
||||
bool _rightShift = false;
|
||||
bool _leftCtrl = false;
|
||||
bool _rightCtrl = false;
|
||||
bool _leftAlt = false;
|
||||
bool _rightAlt = false;
|
||||
bool _leftMeta = false;
|
||||
bool _rightMeta = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionHotkeyEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionHotkeyEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionHotkey> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionHotkeyEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionHotkey>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void KeyChanged(int key);
|
||||
void LShiftChanged(int state);
|
||||
void RShiftChanged(int state);
|
||||
void LCtrlChanged(int state);
|
||||
void RCtrlChanged(int state);
|
||||
void LAltChanged(int state);
|
||||
void RAltChanged(int state);
|
||||
void LMetaChanged(int state);
|
||||
void RMetaChanged(int state);
|
||||
|
||||
protected:
|
||||
QComboBox *_keys;
|
||||
QCheckBox *_leftShift;
|
||||
QCheckBox *_rightShift;
|
||||
QCheckBox *_leftCtrl;
|
||||
QCheckBox *_rightCtrl;
|
||||
QCheckBox *_leftAlt;
|
||||
QCheckBox *_rightAlt;
|
||||
QCheckBox *_leftMeta;
|
||||
QCheckBox *_rightMeta;
|
||||
|
||||
std::shared_ptr<MacroActionHotkey> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include <QDoubleSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "macro-selection.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class PerformMacroAction {
|
||||
PAUSE,
|
||||
UNPAUSE,
|
||||
@@ -15,6 +16,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -48,6 +50,8 @@ private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void MacroRemove(const QString &name);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
MacroSelection *_macros;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class MediaAction {
|
||||
PLAY,
|
||||
PAUSE,
|
||||
@@ -17,6 +19,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -50,6 +53,8 @@ public:
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_mediaSources;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#pragma once
|
||||
#include <QDoubleSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class PluginStateAction {
|
||||
STOP,
|
||||
NO_MATCH_BEHAVIOUR,
|
||||
};
|
||||
|
||||
class MacroActionPluginState : public MacroAction {
|
||||
@@ -19,6 +22,8 @@ public:
|
||||
}
|
||||
|
||||
PluginStateAction _action = PluginStateAction::STOP;
|
||||
int _value = 0;
|
||||
OBSWeakSource _scene;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -44,12 +49,17 @@ public:
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
void ValueChanged(int value);
|
||||
void SceneChanged(const QString &text);
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
QComboBox *_values;
|
||||
QComboBox *_scenes;
|
||||
std::shared_ptr<MacroActionPluginState> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(PluginStateAction, int);
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QLabel>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class RecordAction {
|
||||
STOP,
|
||||
START,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include <QDoubleSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class ReplayBufferAction {
|
||||
STOP,
|
||||
START,
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QListWidget>
|
||||
#include <QStringList>
|
||||
|
||||
class MacroActionRun : public MacroAction {
|
||||
public:
|
||||
@@ -10,6 +12,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -17,6 +20,7 @@ public:
|
||||
}
|
||||
|
||||
std::string _path = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
QStringList _args;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -41,6 +45,12 @@ public:
|
||||
private slots:
|
||||
void FilePathChanged();
|
||||
void BrowseButtonClicked();
|
||||
void AddArg();
|
||||
void RemoveArg();
|
||||
void ArgUp();
|
||||
void ArgDown();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MacroActionRun> _entryData;
|
||||
@@ -48,5 +58,10 @@ protected:
|
||||
private:
|
||||
QLineEdit *_filePath;
|
||||
QPushButton *_browseButton;
|
||||
QListWidget *_argList;
|
||||
QPushButton *_addArg;
|
||||
QPushButton *_removeArg;
|
||||
QPushButton *_argUp;
|
||||
QPushButton *_argDown;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
72
src/headers/macro-action-scene-order.hpp
Normal file
72
src/headers/macro-action-scene-order.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
enum class SceneOrderAction {
|
||||
MOVE_UP,
|
||||
MOVE_DOWN,
|
||||
MOVE_TOP,
|
||||
MOVE_BOTTOM,
|
||||
POSITION,
|
||||
};
|
||||
|
||||
class MacroActionSceneOrder : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionSceneOrder>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
SceneOrderAction _action = SceneOrderAction::MOVE_UP;
|
||||
int _position = 0;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSceneOrderEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSceneOrderEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSceneOrder> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSceneOrderEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionSceneOrder>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void PositionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_actions;
|
||||
QSpinBox *_position;
|
||||
std::shared_ptr<MacroActionSceneOrder> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -3,12 +3,15 @@
|
||||
#include "switch-generic.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
// TODO: Switch to using SceneSelection class and widget instead
|
||||
|
||||
class MacroActionSwitchScene : public MacroAction, public SceneSwitcherEntry {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
@@ -42,6 +45,9 @@ public:
|
||||
|
||||
private slots:
|
||||
void DurationChanged(double seconds);
|
||||
void ChangeHeaderInfo(const QString &);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
DurationSelection *_duration;
|
||||
|
||||
66
src/headers/macro-action-scene-transform.hpp
Normal file
66
src/headers/macro-action-scene-transform.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
class MacroActionSceneTransform : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionSceneTransform>();
|
||||
}
|
||||
std::string GetSettings();
|
||||
void SetSettings(std::string &);
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
struct obs_transform_info _info;
|
||||
struct obs_sceneitem_crop _crop;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSceneTransformEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSceneTransformEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSceneTransform> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSceneTransformEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionSceneTransform>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
std::shared_ptr<MacroActionSceneTransform> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
enum class SceneVisibilityAction {
|
||||
SHOW,
|
||||
@@ -13,13 +14,14 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionSceneVisibility>();
|
||||
}
|
||||
|
||||
OBSWeakSource _scene;
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
SceneVisibilityAction _action = SceneVisibilityAction::SHOW;
|
||||
|
||||
@@ -46,12 +48,14 @@ public:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const QString &text);
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_scenes;
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionSceneVisibility> _entryData;
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -54,6 +55,8 @@ private slots:
|
||||
void ActionChanged(int value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
@@ -65,6 +68,5 @@ protected:
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(bool);
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
#include <QDoubleSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QComboBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class StreamAction {
|
||||
STOP,
|
||||
START,
|
||||
|
||||
57
src/headers/macro-action-virtual-cam.hpp
Normal file
57
src/headers/macro-action-virtual-cam.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class VCamAction {
|
||||
STOP,
|
||||
START,
|
||||
};
|
||||
|
||||
class MacroActionVCam : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionVCam>();
|
||||
}
|
||||
|
||||
VCamAction _action = VCamAction::STOP;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionVCamEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionVCamEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionVCam> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionVCamEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionVCam>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionVCam> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
#include <QDoubleSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class WaitType {
|
||||
FIXED,
|
||||
RANDOM,
|
||||
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -60,6 +61,8 @@ private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void VolumeThresholdChanged(int vol);
|
||||
void ConditionChanged(int cond);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_audioSources;
|
||||
|
||||
76
src/headers/macro-condition-cursor.hpp
Normal file
76
src/headers/macro-condition-cursor.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
#include <QFrame>
|
||||
|
||||
enum class CursorCondition {
|
||||
REGION,
|
||||
MOVING,
|
||||
};
|
||||
|
||||
class MacroConditionCursor : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionCursor>();
|
||||
}
|
||||
|
||||
CursorCondition _condition = CursorCondition::REGION;
|
||||
int _minX = 0, _minY = 0, _maxX = 0, _maxY = 0;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionCursorEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionCursorEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionCursor> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionCursorEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionCursor>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ConditionChanged(int cond);
|
||||
void MinXChanged(int pos);
|
||||
void MinYChanged(int pos);
|
||||
void MaxXChanged(int pos);
|
||||
void MaxYChanged(int pos);
|
||||
void UpdateCursorPos();
|
||||
void ToggleFrame();
|
||||
|
||||
protected:
|
||||
QSpinBox *_minX;
|
||||
QSpinBox *_minY;
|
||||
QSpinBox *_maxX;
|
||||
QSpinBox *_maxY;
|
||||
QComboBox *_conditions;
|
||||
QPushButton *_frameToggle;
|
||||
QLabel *_xPos;
|
||||
QLabel *_yPos;
|
||||
std::shared_ptr<MacroConditionCursor> _entryData;
|
||||
|
||||
private:
|
||||
void SetRegionSelectionVisible(bool);
|
||||
void SetupFrame();
|
||||
QTimer _timer;
|
||||
QFrame _frame;
|
||||
bool _loading = true;
|
||||
};
|
||||
82
src/headers/macro-condition-date.hpp
Normal file
82
src/headers/macro-condition-date.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDateTimeEdit>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class DateCondition {
|
||||
AT,
|
||||
AFTER,
|
||||
BEFORE,
|
||||
BETWEEN,
|
||||
};
|
||||
|
||||
class MacroConditionDate : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionDate>();
|
||||
}
|
||||
|
||||
QDateTime _dateTime;
|
||||
QDateTime _dateTime2;
|
||||
bool _ignoreDate = false;
|
||||
bool _ignoreTime = false;
|
||||
bool _repeat = false;
|
||||
Duration _duration;
|
||||
DateCondition _condition = DateCondition::AT;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionDateEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionDateEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionDate> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionDateEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionDate>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ConditionChanged(int cond);
|
||||
void DateTimeChanged(const QDateTime &datetime);
|
||||
void DateTime2Changed(const QDateTime &datetime);
|
||||
void IgnoreDateChanged(int state);
|
||||
void IgnoreTimeChanged(int state);
|
||||
void RepeatChanged(int state);
|
||||
void DurationChanged(double seconds);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_condition;
|
||||
QDateTimeEdit *_dateTime;
|
||||
QDateTimeEdit *_dateTime2;
|
||||
QCheckBox *_ignoreDate;
|
||||
QCheckBox *_ignoreTime;
|
||||
QCheckBox *_repeat;
|
||||
DurationSelection *_duration;
|
||||
std::shared_ptr<MacroConditionDate> _entryData;
|
||||
|
||||
private:
|
||||
void ShowSecondDateSelection(bool visible);
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,12 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "macro-condition-scene.hpp"
|
||||
#include "section.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QGroupBox>
|
||||
|
||||
struct MacroConditionInfo {
|
||||
using TCreateMethod = std::shared_ptr<MacroCondition> (*)();
|
||||
@@ -34,16 +27,16 @@ private:
|
||||
static std::map<std::string, MacroConditionInfo> _methods;
|
||||
};
|
||||
|
||||
class MacroConditionEdit : public QWidget {
|
||||
class MacroConditionEdit : public MacroSegmentEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionEdit(QWidget *parent = nullptr,
|
||||
std::shared_ptr<MacroCondition> * = nullptr,
|
||||
const std::string &id = "scene", bool root = true,
|
||||
bool startCollapsed = false);
|
||||
const std::string &id = "scene", bool root = true);
|
||||
bool IsRootNode();
|
||||
void UpdateEntryData(const std::string &id, bool collapse);
|
||||
void SetRootNode(bool);
|
||||
void UpdateEntryData(const std::string &id);
|
||||
|
||||
private slots:
|
||||
void LogicSelectionChanged(int idx);
|
||||
@@ -52,15 +45,14 @@ private slots:
|
||||
void DurationConditionChanged(DurationCondition cond);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
|
||||
protected:
|
||||
private:
|
||||
MacroSegment *Data();
|
||||
|
||||
QComboBox *_logicSelection;
|
||||
QComboBox *_conditionSelection;
|
||||
Section *_section;
|
||||
DurationConstraintEdit *_dur;
|
||||
|
||||
std::shared_ptr<MacroCondition> *_entryData;
|
||||
|
||||
private:
|
||||
bool _isRoot = true;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -66,6 +67,8 @@ private slots:
|
||||
void UseRegexChanged(int state);
|
||||
void CheckModificationDateChanged(int state);
|
||||
void OnlyMatchIfChangedChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_fileType;
|
||||
|
||||
77
src/headers/macro-condition-filter.hpp
Normal file
77
src/headers/macro-condition-filter.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QCheckBox>
|
||||
|
||||
enum class FilterCondition {
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
class MacroConditionFilter : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionFilter>();
|
||||
}
|
||||
|
||||
OBSWeakSource _source;
|
||||
OBSWeakSource _filter;
|
||||
FilterCondition _condition = FilterCondition::ENABLED;
|
||||
std::string _settings = "";
|
||||
bool _regex = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionFilterEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionFilterEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionFilter> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionFilterEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionFilter>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void FilterChanged(const QString &text);
|
||||
void ConditionChanged(int cond);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void RegexChanged(int);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
QComboBox *_filters;
|
||||
QComboBox *_conditions;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
QCheckBox *_regex;
|
||||
|
||||
std::shared_ptr<MacroConditionFilter> _entryData;
|
||||
|
||||
private:
|
||||
void SetSettingsSelectionVisible(bool visible);
|
||||
bool _loading = true;
|
||||
};
|
||||
54
src/headers/macro-condition-hotkey.hpp
Normal file
54
src/headers/macro-condition-hotkey.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QLineEdit>
|
||||
|
||||
class MacroConditionHotkey : public MacroCondition {
|
||||
public:
|
||||
MacroConditionHotkey();
|
||||
~MacroConditionHotkey();
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionHotkey>();
|
||||
}
|
||||
void SetPressed() { _pressed = true; }
|
||||
|
||||
std::string _name;
|
||||
obs_hotkey_id _hotkeyID = OBS_INVALID_HOTKEY_ID;
|
||||
|
||||
private:
|
||||
bool _pressed = false;
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionHotkeyEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionHotkeyEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionHotkey> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionHotkeyEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionHotkey>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void NameChanged();
|
||||
|
||||
protected:
|
||||
QLineEdit *_name;
|
||||
std::shared_ptr<MacroConditionHotkey> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,70 +1,91 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "macro-selection.hpp"
|
||||
#include <QWidget>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QHBoxLayout>
|
||||
#include <QTimer>
|
||||
|
||||
enum class MacroConditionMacroType {
|
||||
COUNT,
|
||||
STATE,
|
||||
};
|
||||
|
||||
enum class CounterCondition {
|
||||
BELOW,
|
||||
ABOVE,
|
||||
EQUAL,
|
||||
};
|
||||
|
||||
class MacroConditionCounter : public MacroRefCondition {
|
||||
class MacroConditionMacro : public MacroRefCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionCounter>();
|
||||
return std::make_shared<MacroConditionMacro>();
|
||||
}
|
||||
|
||||
CounterCondition _condition = CounterCondition::BELOW;
|
||||
MacroConditionMacroType _type = MacroConditionMacroType::STATE;
|
||||
CounterCondition _counterCondition = CounterCondition::BELOW;
|
||||
int _count = 0;
|
||||
|
||||
private:
|
||||
bool CheckCountCondition();
|
||||
bool CheckStateCondition();
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionCounterEdit : public QWidget {
|
||||
class MacroConditionMacroEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionCounterEdit(
|
||||
MacroConditionMacroEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionCounter> cond = nullptr);
|
||||
std::shared_ptr<MacroConditionMacro> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionCounterEdit(
|
||||
return new MacroConditionMacroEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionCounter>(cond));
|
||||
std::dynamic_pointer_cast<MacroConditionMacro>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void MacroRemove(const QString &name);
|
||||
void TypeChanged(int type);
|
||||
void CountChanged(int value);
|
||||
void ConditionChanged(int cond);
|
||||
void ResetClicked();
|
||||
void UpdateCount();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
MacroSelection *_macros;
|
||||
QComboBox *_conditions;
|
||||
QComboBox *_types;
|
||||
QComboBox *_counterConditions;
|
||||
QSpinBox *_count;
|
||||
QLabel *_currentCount;
|
||||
QPushButton *_resetCount;
|
||||
QHBoxLayout *_settingsLine1;
|
||||
QHBoxLayout *_settingsLine2;
|
||||
std::unique_ptr<QTimer> _timer;
|
||||
std::shared_ptr<MacroConditionCounter> _entryData;
|
||||
std::shared_ptr<MacroConditionMacro> _entryData;
|
||||
|
||||
private:
|
||||
void ClearLayouts();
|
||||
void SetupStateWidgets();
|
||||
void SetupCountWidgets();
|
||||
void ResetTimer();
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -90,6 +91,8 @@ private slots:
|
||||
void TimeRestrictionChanged(int index);
|
||||
void TimeChanged(double seconds);
|
||||
void TimeUnitChanged(DurationUnit unit);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_mediaSources;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
class MacroConditionProcess : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -41,6 +43,8 @@ public:
|
||||
private slots:
|
||||
void ProcessChanged(const QString &text);
|
||||
void FocusChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_processSelection;
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
class MacroConditionRegion : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionRegion>();
|
||||
}
|
||||
|
||||
int _minX = 0, _minY = 0, _maxX = 0, _maxY = 0;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionRegionEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionRegionEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionRegion> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionRegionEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionRegion>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void MinXChanged(int pos);
|
||||
void MinYChanged(int pos);
|
||||
void MaxXChanged(int pos);
|
||||
void MaxYChanged(int pos);
|
||||
|
||||
protected:
|
||||
QSpinBox *_minX;
|
||||
QSpinBox *_minY;
|
||||
QSpinBox *_maxX;
|
||||
QSpinBox *_maxY;
|
||||
std::shared_ptr<MacroConditionRegion> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -3,7 +3,13 @@
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
class MacroConditionVirtDesktop : public MacroCondition {
|
||||
enum class ReplayBufferState {
|
||||
STOP,
|
||||
START,
|
||||
SAVE,
|
||||
};
|
||||
|
||||
class MacroConditionReplayBuffer : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
@@ -11,40 +17,39 @@ public:
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionVirtDesktop>();
|
||||
return std::make_shared<MacroConditionReplayBuffer>();
|
||||
}
|
||||
long _desktop = 0;
|
||||
|
||||
ReplayBufferState _state;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionVirtDesktopEdit : public QWidget {
|
||||
class MacroConditionReplayBufferEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionVirtDesktopEdit(
|
||||
MacroConditionReplayBufferEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionVirtDesktop> cond = nullptr);
|
||||
std::shared_ptr<MacroConditionReplayBuffer> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionVirtDesktopEdit(
|
||||
return new MacroConditionReplayBufferEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionVirtDesktop>(
|
||||
std::dynamic_pointer_cast<MacroConditionReplayBuffer>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void DesktopChanged(int value);
|
||||
void UpdateCurrentDesktop();
|
||||
void StateChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_virtDesktops;
|
||||
QLabel *_currentDesktop;
|
||||
std::shared_ptr<MacroConditionVirtDesktop> _entryData;
|
||||
QComboBox *_state;
|
||||
std::shared_ptr<MacroConditionReplayBuffer> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
76
src/headers/macro-condition-scene-order.hpp
Normal file
76
src/headers/macro-condition-scene-order.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class SceneOrderCondition {
|
||||
ABOVE,
|
||||
BELOW,
|
||||
POSITION,
|
||||
};
|
||||
|
||||
class MacroConditionSceneOrder : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionSceneOrder>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
OBSWeakSource _source2;
|
||||
int _position = 0;
|
||||
SceneOrderCondition _condition = SceneOrderCondition::ABOVE;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionSceneOrderEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionSceneOrderEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionSceneOrder> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionSceneOrderEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionSceneOrder>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void Source2Changed(const QString &text);
|
||||
void ConditionChanged(int cond);
|
||||
void PositionChanged(int cond);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_conditions;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_sources2;
|
||||
QSpinBox *_position;
|
||||
QLabel *_posInfo;
|
||||
|
||||
std::shared_ptr<MacroConditionSceneOrder> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(bool showPos);
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
@@ -13,13 +15,14 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionScene>();
|
||||
}
|
||||
|
||||
OBSWeakSource _scene;
|
||||
SceneSelection _scene;
|
||||
SceneType _type;
|
||||
|
||||
private:
|
||||
@@ -44,11 +47,13 @@ public:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const QString &text);
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void TypeChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sceneSelection;
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sceneType;
|
||||
std::shared_ptr<MacroConditionScene> _entryData;
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QCheckBox>
|
||||
|
||||
enum class SourceCondition {
|
||||
ACTIVE,
|
||||
@@ -14,6 +17,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -52,6 +56,8 @@ private slots:
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void RegexChanged(int);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include "duration-control.hpp"
|
||||
|
||||
class MacroConditionInterval : public MacroCondition {
|
||||
#include <QCheckBox>
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
|
||||
class MacroConditionTimer : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
@@ -12,41 +14,48 @@ public:
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionInterval>();
|
||||
return std::make_shared<MacroConditionTimer>();
|
||||
}
|
||||
|
||||
Duration _duration;
|
||||
bool _oneshot = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionIntervalEdit : public QWidget {
|
||||
class MacroConditionTimerEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionIntervalEdit(
|
||||
MacroConditionTimerEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionInterval> cond = nullptr);
|
||||
std::shared_ptr<MacroConditionTimer> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionIntervalEdit(
|
||||
return new MacroConditionTimerEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionInterval>(
|
||||
cond));
|
||||
std::dynamic_pointer_cast<MacroConditionTimer>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void DurationChanged(double seconds);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
void AutoResetChanged(int state);
|
||||
void ResetClicked();
|
||||
void UpdateTimeRemaining();
|
||||
|
||||
protected:
|
||||
DurationSelection *_duration;
|
||||
std::shared_ptr<MacroConditionInterval> _entryData;
|
||||
QCheckBox *_autoReset;
|
||||
QPushButton *_reset;
|
||||
QLabel *_remaining;
|
||||
std::shared_ptr<MacroConditionTimer> _entryData;
|
||||
|
||||
private:
|
||||
QTimer timer;
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
QImage GetMatchImage() { return _matchImage; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
@@ -65,6 +66,8 @@ private slots:
|
||||
void ConditionChanged(int cond);
|
||||
void FilePathChanged();
|
||||
void BrowseButtonClicked();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_videoSelection;
|
||||
|
||||
54
src/headers/macro-condition-virtual-cam.hpp
Normal file
54
src/headers/macro-condition-virtual-cam.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class VCamState {
|
||||
STOP,
|
||||
START,
|
||||
};
|
||||
|
||||
class MacroConditionVCam : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionVCam>();
|
||||
}
|
||||
|
||||
VCamState _state;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionVCamEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionVCamEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionVCam> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionVCamEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionVCam>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void StateChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_states;
|
||||
std::shared_ptr<MacroConditionVCam> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,13 +1,15 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
class MacroConditionWindow : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -24,6 +26,7 @@ public:
|
||||
bool _fullscreen = false;
|
||||
bool _maximized = false;
|
||||
bool _focus = true;
|
||||
bool _windowFocusChanged = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -50,13 +53,17 @@ private slots:
|
||||
void WindowChanged(const QString &text);
|
||||
void FullscreenChanged(int state);
|
||||
void MaximizedChanged(int state);
|
||||
void FocusChanged(int state);
|
||||
void FocusedChanged(int state);
|
||||
void WindowFocusChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_windowSelection;
|
||||
QCheckBox *_fullscreen;
|
||||
QCheckBox *_maximized;
|
||||
QCheckBox *_focused;
|
||||
QCheckBox *_windowFocusChanged;
|
||||
std::shared_ptr<MacroConditionWindow> _entryData;
|
||||
|
||||
private:
|
||||
|
||||
31
src/headers/macro-controls.hpp
Normal file
31
src/headers/macro-controls.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QScrollArea>
|
||||
#include <QPushButton>
|
||||
#include <QLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class MacroEntryControls : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MacroEntryControls(const int animationDuration = 300,
|
||||
QWidget *parent = 0);
|
||||
|
||||
void Show(bool visible = true);
|
||||
|
||||
signals:
|
||||
void Add();
|
||||
void Remove();
|
||||
void Up();
|
||||
void Down();
|
||||
|
||||
private:
|
||||
QPushButton *_add;
|
||||
QPushButton *_remove;
|
||||
QPushButton *_up;
|
||||
QPushButton *_down;
|
||||
QPropertyAnimation *_animation = nullptr;
|
||||
};
|
||||
71
src/headers/macro-segment.hpp
Normal file
71
src/headers/macro-segment.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
#include <QWidget>
|
||||
#include <obs.hpp>
|
||||
|
||||
class MacroSegment {
|
||||
public:
|
||||
void SetIndex(int idx) { _idx = idx; }
|
||||
int GetIndex() { return _idx; }
|
||||
void SetCollapsed(bool collapsed) { _collapsed = collapsed; }
|
||||
bool GetCollapsed() { return _collapsed; }
|
||||
virtual bool Save(obs_data_t *obj) = 0;
|
||||
virtual bool Load(obs_data_t *obj) = 0;
|
||||
virtual std::string GetShortDesc();
|
||||
virtual std::string GetId() = 0;
|
||||
|
||||
protected:
|
||||
int _idx;
|
||||
bool _collapsed = false;
|
||||
};
|
||||
|
||||
class Section;
|
||||
class QLabel;
|
||||
class MacroEntryControls;
|
||||
|
||||
class MacroSegmentEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroSegmentEdit(QWidget *parent = nullptr);
|
||||
// Use this function to avoid accidental edits when scrolling through
|
||||
// list of actions and conditions
|
||||
void SetFocusPolicyOfWidgets();
|
||||
|
||||
protected slots:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
void Add();
|
||||
void Remove();
|
||||
void Up();
|
||||
void Down();
|
||||
void Collapsed(bool);
|
||||
signals:
|
||||
void MacroAdded(const QString &name);
|
||||
void MacroRemoved(const QString &name);
|
||||
void MacroRenamed(const QString &oldName, const QString newName);
|
||||
void SceneGroupAdded(const QString &name);
|
||||
void SceneGroupRemoved(const QString &name);
|
||||
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
||||
void AddAt(int idx);
|
||||
void RemoveAt(int idx);
|
||||
void UpAt(int idx);
|
||||
void DownAt(int idx);
|
||||
|
||||
protected:
|
||||
void enterEvent(QEvent *e);
|
||||
void leaveEvent(QEvent *e);
|
||||
|
||||
Section *_section;
|
||||
QLabel *_headerInfo;
|
||||
MacroEntryControls *_controls;
|
||||
|
||||
private:
|
||||
virtual MacroSegment *Data() = 0;
|
||||
};
|
||||
|
||||
class MouseWheelWidgetAdjustmentGuard : public QObject {
|
||||
public:
|
||||
explicit MouseWheelWidgetAdjustmentGuard(QObject *parent);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *o, QEvent *e) override;
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "macro-segment.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <string>
|
||||
@@ -36,13 +37,11 @@ struct LogicTypeInfo {
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
class MacroCondition {
|
||||
class MacroCondition : public MacroSegment {
|
||||
public:
|
||||
virtual bool CheckCondition() = 0;
|
||||
virtual bool Save(obs_data_t *obj) = 0;
|
||||
virtual bool Load(obs_data_t *obj) = 0;
|
||||
virtual std::string GetId() = 0;
|
||||
|
||||
LogicType GetLogicType() { return _logic; }
|
||||
void SetLogicType(LogicType logic) { _logic = logic; }
|
||||
static const std::map<LogicType, LogicTypeInfo> logicTypes;
|
||||
@@ -60,12 +59,11 @@ private:
|
||||
DurationConstraint _duration;
|
||||
};
|
||||
|
||||
class MacroAction {
|
||||
class MacroAction : public MacroSegment {
|
||||
public:
|
||||
virtual bool PerformAction() = 0;
|
||||
virtual bool Save(obs_data_t *obj) = 0;
|
||||
virtual bool Load(obs_data_t *obj) = 0;
|
||||
virtual std::string GetId() = 0;
|
||||
virtual void LogAction();
|
||||
};
|
||||
|
||||
@@ -87,6 +85,8 @@ public:
|
||||
{
|
||||
return _conditions;
|
||||
}
|
||||
void UpdateActionIndices();
|
||||
void UpdateConditionIndices();
|
||||
std::deque<std::shared_ptr<MacroAction>> &Actions() { return _actions; }
|
||||
|
||||
bool Save(obs_data_t *obj);
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
static bool AskForName(QWidget *parent, const QString &title,
|
||||
const QString &text, std::string &userTextInput,
|
||||
const QString &placeHolder = QString(""),
|
||||
int maxSize = 170);
|
||||
int maxSize = 170, bool clean = true);
|
||||
|
||||
private:
|
||||
QLabel *label;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "hotkey.hpp"
|
||||
|
||||
void GetWindowList(std::vector<std::string> &windows);
|
||||
void GetWindowList(QStringList &windows);
|
||||
@@ -9,5 +10,6 @@ std::pair<int, int> getCursorPos();
|
||||
int secondsSinceLastInput();
|
||||
void GetProcessList(QStringList &processes);
|
||||
bool isInFocus(const QString &executable);
|
||||
bool GetCurrentVirtualDesktop(long &desktop);
|
||||
bool GetVirtualDesktopCount(long &ndesktops);
|
||||
void PressKeys(const std::vector<HotkeyType> keys);
|
||||
void PlatformInit();
|
||||
void PlatformCleanup();
|
||||
|
||||
@@ -82,3 +82,6 @@ private:
|
||||
|
||||
SceneGroup *sceneGroup = nullptr;
|
||||
};
|
||||
|
||||
SceneGroup *GetSceneGroupByName(const char *name);
|
||||
SceneGroup *GetSceneGroupByQString(const QString &name);
|
||||
|
||||
51
src/headers/scene-selection.hpp
Normal file
51
src/headers/scene-selection.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#include "scene-group.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
enum class SceneSelectionType {
|
||||
SCENE,
|
||||
GROUP,
|
||||
PREVIOUS,
|
||||
CURRENT,
|
||||
};
|
||||
|
||||
class SceneSelection {
|
||||
public:
|
||||
void Save(obs_data_t *obj, const char *name = "scene",
|
||||
const char *typeName = "sceneType");
|
||||
void Load(obs_data_t *obj, const char *name = "scene",
|
||||
const char *typeName = "sceneType");
|
||||
|
||||
SceneSelectionType GetType() { return _type; }
|
||||
OBSWeakSource GetScene(bool advance = true);
|
||||
std::string ToString();
|
||||
|
||||
private:
|
||||
OBSWeakSource _scene;
|
||||
SceneGroup *_group = nullptr;
|
||||
SceneSelectionType _type = SceneSelectionType::SCENE;
|
||||
friend class SceneSelectionWidget;
|
||||
};
|
||||
|
||||
class SceneSelectionWidget : public QComboBox {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SceneSelectionWidget(QWidget *parent, bool sceneGroups = false,
|
||||
bool previous = false, bool current = false);
|
||||
void SetScene(SceneSelection &);
|
||||
signals:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
|
||||
private slots:
|
||||
void SelectionChanged(const QString &name);
|
||||
void SceneGroupAdd(const QString &name);
|
||||
void SceneGroupRemove(const QString &name);
|
||||
void SceneGroupRename(const QString &oldName, const QString &newName);
|
||||
|
||||
private:
|
||||
bool IsCurrentSceneSelected(const QString &name);
|
||||
bool IsPreviousSceneSelected(const QString &name);
|
||||
};
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "switch-generic.hpp"
|
||||
@@ -27,6 +34,9 @@ enum class sceneTriggerAction {
|
||||
|
||||
START_SWITCHER,
|
||||
STOP_SWITCHER,
|
||||
|
||||
START_VCAM,
|
||||
STOP_VCAM,
|
||||
};
|
||||
|
||||
struct SceneTrigger : SceneSwitcherEntry {
|
||||
|
||||
@@ -23,6 +23,8 @@ protected:
|
||||
private slots:
|
||||
void AnimationFinished();
|
||||
void Collapse(bool collapse);
|
||||
signals:
|
||||
void Collapsed(bool);
|
||||
|
||||
private:
|
||||
void SetupAnimations();
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <limits>
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QCheckBox>
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QVBoxLayout>
|
||||
|
||||
@@ -28,11 +35,9 @@ struct SceneSequenceSwitch : SceneSwitcherEntry {
|
||||
bool reduce();
|
||||
SceneSequenceSwitch *extend();
|
||||
|
||||
bool checkMatch(OBSWeakSource currentScene, int &linger,
|
||||
SceneSequenceSwitch *root = nullptr);
|
||||
bool checkMatch(int &linger, SceneSequenceSwitch *root = nullptr);
|
||||
bool checkDurationMatchInterruptible();
|
||||
void prepareUninterruptibleMatch(OBSWeakSource currentScene,
|
||||
int &linger);
|
||||
void prepareUninterruptibleMatch(int &linger);
|
||||
void advanceActiveSequence();
|
||||
void logAdvanceSequence();
|
||||
void logSequenceCanceled();
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QTimeEdit>
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ struct SwitcherData {
|
||||
std::mutex m;
|
||||
bool transitionActive = false;
|
||||
bool waitForTransition = false;
|
||||
std::condition_variable transitionCv;
|
||||
bool stop = false;
|
||||
bool verbose = false;
|
||||
bool disableHints = false;
|
||||
@@ -78,8 +77,8 @@ struct SwitcherData {
|
||||
int interval = default_interval;
|
||||
|
||||
obs_source_t *waitScene = nullptr;
|
||||
OBSWeakSource currentScene = nullptr;
|
||||
OBSWeakSource previousScene = nullptr;
|
||||
OBSWeakSource previousSceneHelper = nullptr;
|
||||
OBSWeakSource lastRandomScene;
|
||||
SceneGroup *lastRandomSceneGroup;
|
||||
OBSWeakSource nonMatchingScene;
|
||||
@@ -92,15 +91,19 @@ struct SwitcherData {
|
||||
std::chrono::high_resolution_clock::time_point lastMatchTime;
|
||||
|
||||
std::deque<Macro> macros;
|
||||
// Allow only one macro scene change per scene switcher interval
|
||||
// with the top macro having the highest priority
|
||||
std::condition_variable macroWaitCv;
|
||||
std::atomic_bool abortMacroWait = {false};
|
||||
bool macroSceneSwitched = false;
|
||||
bool replayBufferSaved = false;
|
||||
|
||||
std::deque<WindowSwitch> windowSwitches;
|
||||
std::vector<std::string> ignoreIdleWindows;
|
||||
std::string lastTitle;
|
||||
std::string currentTitle;
|
||||
|
||||
std::deque<ScreenRegionSwitch> screenRegionSwitches;
|
||||
std::pair<int, int> lastCursorPos = {0, 0};
|
||||
bool cursorPosChanged = false;
|
||||
|
||||
std::vector<std::string> ignoreWindowsSwitches;
|
||||
|
||||
@@ -178,9 +181,9 @@ struct SwitcherData {
|
||||
std::vector<int> tabOrder = std::vector<int>(tab_count);
|
||||
|
||||
bool hotkeysRegistered = false;
|
||||
obs_hotkey_id startHotkey = 0;
|
||||
obs_hotkey_id stopHotkey = 0;
|
||||
obs_hotkey_id toggleHotkey = 0;
|
||||
obs_hotkey_id startHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
obs_hotkey_id stopHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
obs_hotkey_id toggleHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
|
||||
bool saveWindowGeo = false;
|
||||
QPoint windowPos = {};
|
||||
@@ -203,6 +206,7 @@ struct SwitcherData {
|
||||
void writeSceneInfoToFile();
|
||||
void writeToStatusFile(const QString &msg);
|
||||
|
||||
void setPreconditions();
|
||||
bool checkForMatch(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||
int &linger, bool &setPreviousSceneAsMatch,
|
||||
bool ¯oMatch);
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <unordered_map>
|
||||
#include "scene-group.hpp"
|
||||
|
||||
class SceneSelection;
|
||||
|
||||
bool WeakSourceValid(obs_weak_source_t *ws);
|
||||
std::string GetWeakSourceName(obs_weak_source_t *weak_source);
|
||||
OBSWeakSource GetWeakSourceByName(const char *name);
|
||||
@@ -22,7 +24,14 @@ OBSWeakSource GetWeakFilterByName(OBSWeakSource source, const char *name);
|
||||
OBSWeakSource GetWeakFilterByQString(OBSWeakSource source, const QString &name);
|
||||
bool compareIgnoringLineEnding(QString &s1, QString &s2);
|
||||
std::string getSourceSettings(OBSWeakSource ws);
|
||||
void setSourceSettings(obs_source_t *s, const std::string &settings);
|
||||
bool compareSourceSettings(const OBSWeakSource &source,
|
||||
const std::string &settings, bool regex);
|
||||
std::vector<obs_scene_item *> getSceneItemsWithName(OBSScene scene,
|
||||
std::string &name);
|
||||
std::string getDataFilePath(const std::string &file);
|
||||
QString formatJsonString(std::string);
|
||||
QString formatJsonString(const char *);
|
||||
|
||||
/**
|
||||
* Populate layout with labels and widgets based on provided text
|
||||
@@ -35,6 +44,7 @@ std::string getDataFilePath(const std::string &file);
|
||||
void placeWidgets(std::string text, QBoxLayout *layout,
|
||||
std::unordered_map<std::string, QWidget *> placeholders,
|
||||
bool addStretch = true);
|
||||
void deleteLayoutItem(QLayoutItem *item);
|
||||
void clearLayout(QLayout *layout);
|
||||
QMetaObject::Connection PulseWidget(QWidget *widget, QColor endColor,
|
||||
QColor = QColor(0, 0, 0, 0),
|
||||
@@ -57,7 +67,14 @@ void populateMediaSelection(QComboBox *sel, bool addSelect = true);
|
||||
void populateProcessSelection(QComboBox *sel, bool addSelect = true);
|
||||
void populateSourceSelection(QComboBox *list, bool addSelect = true);
|
||||
void populateSceneSelection(QComboBox *sel, bool addPrevious = false,
|
||||
bool addCurrent = false, bool addAny = false,
|
||||
bool addSceneGroup = false,
|
||||
std::deque<SceneGroup> *sceneGroups = nullptr,
|
||||
bool addSelect = true, std::string selectText = "",
|
||||
bool selectable = false);
|
||||
void populateSourcesWithFilterSelection(QComboBox *list);
|
||||
void populateFilterSelection(QComboBox *list,
|
||||
OBSWeakSource weakSource = nullptr);
|
||||
void populateSceneItemSelection(QComboBox *list,
|
||||
OBSWeakSource sceneWeakSource = nullptr);
|
||||
void populateSceneItemSelection(QComboBox *list, SceneSelection &s);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "headers/hotkey.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include <obs-module.h>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
void startHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
|
||||
bool pressed)
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include "../headers/hotkey.hpp"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/extensions/scrnsaver.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
#undef Bool
|
||||
#undef CursorShape
|
||||
#undef Expose
|
||||
@@ -15,11 +19,19 @@
|
||||
#undef Unsorted
|
||||
#include <util/platform.h>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <QStringList>
|
||||
#include <QRegularExpression>
|
||||
#include <QLibrary>
|
||||
|
||||
static Display *xdisplay = 0;
|
||||
|
||||
static QLibrary *libXtstHandle = nullptr;
|
||||
typedef int (*keyPressFunc)(Display *, unsigned int, bool, unsigned long);
|
||||
static keyPressFunc pressFunc = nullptr;
|
||||
bool canSimulateKeyPresses = false;
|
||||
|
||||
Display *disp()
|
||||
{
|
||||
if (!xdisplay)
|
||||
@@ -211,7 +223,7 @@ void GetCurrentWindowTitle(std::string &title)
|
||||
|
||||
int status = 0;
|
||||
XTextProperty text;
|
||||
if (xstatus == Success) {
|
||||
if (xstatus == Success && data[0]) {
|
||||
status = XGetTextProperty(disp(), data[0], &text,
|
||||
XInternAtom(disp(), "_NET_WM_NAME",
|
||||
true));
|
||||
@@ -242,14 +254,13 @@ std::pair<int, int> getCursorPos()
|
||||
int win_y;
|
||||
unsigned int mask;
|
||||
|
||||
dpy = XOpenDisplay(NULL);
|
||||
dpy = disp();
|
||||
root = XDefaultRootWindow(dpy);
|
||||
|
||||
if (XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y,
|
||||
&win_x, &win_y, &mask)) {
|
||||
pos = std::pair<int, int>(root_x, root_y);
|
||||
}
|
||||
XCloseDisplay(dpy);
|
||||
return pos;
|
||||
}
|
||||
|
||||
@@ -382,78 +393,186 @@ int secondsSinceLastInput()
|
||||
|
||||
mit_info = XScreenSaverAllocInfo();
|
||||
|
||||
if ((display = XOpenDisplay(NULL)) == NULL) {
|
||||
return (-1);
|
||||
if ((display = disp()) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
screen = DefaultScreen(display);
|
||||
XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info);
|
||||
idle_time = (mit_info->idle) / 1000;
|
||||
XFree(mit_info);
|
||||
XCloseDisplay(display);
|
||||
|
||||
return idle_time;
|
||||
}
|
||||
|
||||
bool GetCurrentVirtualDesktop(long &desktop)
|
||||
static std::unordered_map<HotkeyType, long> keyTable = {
|
||||
// Chars
|
||||
{HotkeyType::Key_A, XK_A},
|
||||
{HotkeyType::Key_B, XK_B},
|
||||
{HotkeyType::Key_C, XK_C},
|
||||
{HotkeyType::Key_D, XK_D},
|
||||
{HotkeyType::Key_E, XK_E},
|
||||
{HotkeyType::Key_F, XK_F},
|
||||
{HotkeyType::Key_G, XK_G},
|
||||
{HotkeyType::Key_H, XK_H},
|
||||
{HotkeyType::Key_I, XK_I},
|
||||
{HotkeyType::Key_J, XK_J},
|
||||
{HotkeyType::Key_K, XK_K},
|
||||
{HotkeyType::Key_L, XK_L},
|
||||
{HotkeyType::Key_M, XK_M},
|
||||
{HotkeyType::Key_N, XK_N},
|
||||
{HotkeyType::Key_O, XK_O},
|
||||
{HotkeyType::Key_P, XK_P},
|
||||
{HotkeyType::Key_Q, XK_Q},
|
||||
{HotkeyType::Key_R, XK_R},
|
||||
{HotkeyType::Key_S, XK_S},
|
||||
{HotkeyType::Key_T, XK_T},
|
||||
{HotkeyType::Key_U, XK_U},
|
||||
{HotkeyType::Key_V, XK_V},
|
||||
{HotkeyType::Key_W, XK_W},
|
||||
{HotkeyType::Key_X, XK_X},
|
||||
{HotkeyType::Key_Y, XK_Y},
|
||||
{HotkeyType::Key_Z, XK_Z},
|
||||
|
||||
// Numbers
|
||||
{HotkeyType::Key_0, XK_0},
|
||||
{HotkeyType::Key_1, XK_1},
|
||||
{HotkeyType::Key_2, XK_2},
|
||||
{HotkeyType::Key_3, XK_3},
|
||||
{HotkeyType::Key_4, XK_4},
|
||||
{HotkeyType::Key_5, XK_5},
|
||||
{HotkeyType::Key_6, XK_6},
|
||||
{HotkeyType::Key_7, XK_7},
|
||||
{HotkeyType::Key_8, XK_8},
|
||||
{HotkeyType::Key_9, XK_9},
|
||||
|
||||
{HotkeyType::Key_F1, XK_F1},
|
||||
{HotkeyType::Key_F2, XK_F2},
|
||||
{HotkeyType::Key_F3, XK_F3},
|
||||
{HotkeyType::Key_F4, XK_F4},
|
||||
{HotkeyType::Key_F5, XK_F5},
|
||||
{HotkeyType::Key_F6, XK_F6},
|
||||
{HotkeyType::Key_F7, XK_F7},
|
||||
{HotkeyType::Key_F8, XK_F8},
|
||||
{HotkeyType::Key_F9, XK_F9},
|
||||
{HotkeyType::Key_F10, XK_F10},
|
||||
{HotkeyType::Key_F11, XK_F11},
|
||||
{HotkeyType::Key_F12, XK_F12},
|
||||
{HotkeyType::Key_F13, XK_F13},
|
||||
{HotkeyType::Key_F14, XK_F14},
|
||||
{HotkeyType::Key_F15, XK_F15},
|
||||
{HotkeyType::Key_F16, XK_F16},
|
||||
{HotkeyType::Key_F17, XK_F17},
|
||||
{HotkeyType::Key_F18, XK_F18},
|
||||
{HotkeyType::Key_F19, XK_F19},
|
||||
{HotkeyType::Key_F20, XK_F20},
|
||||
{HotkeyType::Key_F21, XK_F21},
|
||||
{HotkeyType::Key_F22, XK_F22},
|
||||
{HotkeyType::Key_F23, XK_F23},
|
||||
{HotkeyType::Key_F24, XK_F24},
|
||||
|
||||
{HotkeyType::Key_Escape, XK_Escape},
|
||||
{HotkeyType::Key_Space, XK_space},
|
||||
{HotkeyType::Key_Return, XK_Return},
|
||||
{HotkeyType::Key_Backspace, XK_BackSpace},
|
||||
{HotkeyType::Key_Tab, XK_Tab},
|
||||
|
||||
{HotkeyType::Key_Shift_L, XK_Shift_L},
|
||||
{HotkeyType::Key_Shift_R, XK_Shift_R},
|
||||
{HotkeyType::Key_Control_L, XK_Control_L},
|
||||
{HotkeyType::Key_Control_R, XK_Control_R},
|
||||
{HotkeyType::Key_Alt_L, XK_Alt_L},
|
||||
{HotkeyType::Key_Alt_R, XK_Alt_R},
|
||||
{HotkeyType::Key_Win_L, XK_Super_L},
|
||||
{HotkeyType::Key_Win_R, XK_Super_R},
|
||||
{HotkeyType::Key_Apps, XK_Hyper_L},
|
||||
|
||||
{HotkeyType::Key_CapsLock, XK_Caps_Lock},
|
||||
{HotkeyType::Key_NumLock, XK_Num_Lock},
|
||||
{HotkeyType::Key_ScrollLock, XK_Scroll_Lock},
|
||||
|
||||
{HotkeyType::Key_PrintScreen, XK_Print},
|
||||
{HotkeyType::Key_Pause, XK_Pause},
|
||||
|
||||
{HotkeyType::Key_Insert, XK_Insert},
|
||||
{HotkeyType::Key_Delete, XK_Delete},
|
||||
{HotkeyType::Key_PageUP, XK_Page_Up},
|
||||
{HotkeyType::Key_PageDown, XK_Page_Down},
|
||||
{HotkeyType::Key_Home, XK_Home},
|
||||
{HotkeyType::Key_End, XK_End},
|
||||
|
||||
{HotkeyType::Key_Left, XK_Left},
|
||||
{HotkeyType::Key_Up, XK_Up},
|
||||
{HotkeyType::Key_Right, XK_Right},
|
||||
{HotkeyType::Key_Down, XK_Down},
|
||||
|
||||
{HotkeyType::Key_Numpad0, XK_KP_0},
|
||||
{HotkeyType::Key_Numpad1, XK_KP_1},
|
||||
{HotkeyType::Key_Numpad2, XK_KP_2},
|
||||
{HotkeyType::Key_Numpad3, XK_KP_3},
|
||||
{HotkeyType::Key_Numpad4, XK_KP_4},
|
||||
{HotkeyType::Key_Numpad5, XK_KP_5},
|
||||
{HotkeyType::Key_Numpad6, XK_KP_6},
|
||||
{HotkeyType::Key_Numpad7, XK_KP_7},
|
||||
{HotkeyType::Key_Numpad8, XK_KP_8},
|
||||
{HotkeyType::Key_Numpad9, XK_KP_9},
|
||||
|
||||
{HotkeyType::Key_NumpadAdd, XK_KP_Add},
|
||||
{HotkeyType::Key_NumpadSubtract, XK_KP_Subtract},
|
||||
{HotkeyType::Key_NumpadMultiply, XK_KP_Multiply},
|
||||
{HotkeyType::Key_NumpadDivide, XK_KP_Divide},
|
||||
{HotkeyType::Key_NumpadDecimal, XK_KP_Decimal},
|
||||
{HotkeyType::Key_NumpadEnter, XK_KP_Enter},
|
||||
};
|
||||
|
||||
void PressKeys(const std::vector<HotkeyType> keys)
|
||||
{
|
||||
Atom type;
|
||||
long unsigned nitems;
|
||||
long unsigned int bytes = 0;
|
||||
int format = 0;
|
||||
unsigned char *data;
|
||||
Window root;
|
||||
Atom request;
|
||||
if (!canSimulateKeyPresses) {
|
||||
return;
|
||||
}
|
||||
|
||||
Display *display = disp();
|
||||
if (display == NULL)
|
||||
return;
|
||||
|
||||
//TODO check for _NET_CURRENT_DESKTOP
|
||||
if (!ewmhIsSupported()) {
|
||||
return false;
|
||||
// Press keys
|
||||
for (auto &key : keys) {
|
||||
auto it = keyTable.find(key);
|
||||
if (it == keyTable.end()) {
|
||||
continue;
|
||||
}
|
||||
pressFunc(display, XKeysymToKeycode(display, it->second), true,
|
||||
CurrentTime);
|
||||
}
|
||||
XFlush(display);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
||||
|
||||
// Release keys
|
||||
for (auto &key : keys) {
|
||||
auto it = keyTable.find(key);
|
||||
if (it == keyTable.end()) {
|
||||
continue;
|
||||
}
|
||||
pressFunc(display, XKeysymToKeycode(display, it->second), false,
|
||||
CurrentTime);
|
||||
}
|
||||
|
||||
request = XInternAtom(display, "_NET_CURRENT_DESKTOP", False);
|
||||
root = XDefaultRootWindow(display);
|
||||
|
||||
int status = XGetWindowProperty(display, root, request, 0L, 1L, false,
|
||||
XA_CARDINAL, &type, &format, &nitems,
|
||||
&bytes, &data);
|
||||
|
||||
if (status == Success && nitems > 0) {
|
||||
desktop = *((long *)data);
|
||||
} else {
|
||||
desktop = -1;
|
||||
}
|
||||
free(data);
|
||||
return desktop != -1;
|
||||
XFlush(display);
|
||||
}
|
||||
|
||||
bool GetVirtualDesktopCount(long &ndesktops)
|
||||
void PlatformInit()
|
||||
{
|
||||
Atom type;
|
||||
long unsigned nitems;
|
||||
long unsigned int bytes = 0;
|
||||
int format = 0;
|
||||
unsigned char *data;
|
||||
Window root;
|
||||
Atom request;
|
||||
Display *display = disp();
|
||||
|
||||
//TODO check for _NET_NUMBER_OF_DESKTOPS
|
||||
if (!ewmhIsSupported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
request = XInternAtom(display, "_NET_NUMBER_OF_DESKTOPS", False);
|
||||
root = XDefaultRootWindow(display);
|
||||
|
||||
int status = XGetWindowProperty(display, root, request, 0L, 1L, false,
|
||||
XA_CARDINAL, &type, &format, &nitems,
|
||||
&bytes, &data);
|
||||
|
||||
if (status == Success && nitems > 0) {
|
||||
ndesktops = *((long *)data);
|
||||
} else {
|
||||
ndesktops = 0;
|
||||
}
|
||||
free(data);
|
||||
return ndesktops != 0;
|
||||
libXtstHandle = new QLibrary("libXtst.so", nullptr);
|
||||
pressFunc = (keyPressFunc)libXtstHandle->resolve("XTestFakeKeyEvent");
|
||||
int _;
|
||||
canSimulateKeyPresses = pressFunc &&
|
||||
!XQueryExtension(disp(), "XTEST", &_, &_, &_);
|
||||
}
|
||||
|
||||
void PlatformCleanup()
|
||||
{
|
||||
delete libXtstHandle;
|
||||
libXtstHandle = nullptr;
|
||||
|
||||
cleanupDisplay();
|
||||
}
|
||||
|
||||
@@ -75,6 +75,14 @@ bool MacroActionAudio::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionAudio::GetShortDesc()
|
||||
{
|
||||
if (_audioSource) {
|
||||
return GetWeakSourceName(_audioSource);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -167,6 +175,8 @@ void MacroActionAudioEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_audioSource = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionAudioEdit::ActionChanged(int value)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/macro-action-edit.hpp"
|
||||
#include "headers/macro-action-scene-switch.hpp"
|
||||
#include "headers/section.hpp"
|
||||
#include "headers/macro-controls.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
std::map<std::string, MacroActionInfo> MacroActionFactory::_methods;
|
||||
|
||||
@@ -59,11 +61,10 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
|
||||
MacroActionEdit::MacroActionEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> *entryData,
|
||||
const std::string &id, bool startCollapsed)
|
||||
: QWidget(parent)
|
||||
const std::string &id)
|
||||
: MacroSegmentEdit(parent), _entryData(entryData)
|
||||
{
|
||||
_actionSelection = new QComboBox();
|
||||
_section = new Section(300);
|
||||
|
||||
QWidget::connect(_actionSelection,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
@@ -72,13 +73,15 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
|
||||
populateActionSelection(_actionSelection);
|
||||
|
||||
_section->AddHeaderWidget(_actionSelection);
|
||||
_section->AddHeaderWidget(_headerInfo);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(_section);
|
||||
mainLayout->addWidget(_controls);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData(id, startCollapsed);
|
||||
UpdateEntryData(id);
|
||||
|
||||
_loading = false;
|
||||
}
|
||||
@@ -90,22 +93,61 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
|
||||
}
|
||||
|
||||
std::string id = MacroActionFactory::GetIdByName(text);
|
||||
HeaderInfoChanged("");
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->reset();
|
||||
*_entryData = MacroActionFactory::Create(id);
|
||||
auto widget =
|
||||
MacroActionFactory::CreateWidget(id, window(), *_entryData);
|
||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||
_section->SetContent(widget, false);
|
||||
SetFocusPolicyOfWidgets();
|
||||
}
|
||||
|
||||
void MacroActionEdit::UpdateEntryData(const std::string &id, bool collapse)
|
||||
void MacroActionEdit::UpdateEntryData(const std::string &id)
|
||||
{
|
||||
_actionSelection->setCurrentText(
|
||||
obs_module_text(MacroActionFactory::GetActionName(id).c_str()));
|
||||
auto widget =
|
||||
MacroActionFactory::CreateWidget(id, window(), *_entryData);
|
||||
_section->SetContent(widget, collapse);
|
||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||
HeaderInfoChanged(
|
||||
QString::fromStdString((*_entryData)->GetShortDesc()));
|
||||
_section->SetContent(widget, (*_entryData)->GetCollapsed());
|
||||
SetFocusPolicyOfWidgets();
|
||||
}
|
||||
|
||||
MacroSegment *MacroActionEdit::Data()
|
||||
{
|
||||
return _entryData->get();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx > (int)macro->Actions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MacroActionSwitchScene temp;
|
||||
std::string id = temp.GetId();
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
auto action = macro->Actions().emplace(macro->Actions().begin() + idx,
|
||||
MacroActionFactory::Create(id));
|
||||
macro->UpdateActionIndices();
|
||||
|
||||
// All entry pointers in existing edit widgets after the new entry will
|
||||
// be invalidated by adding the new entry so we have to recreate them
|
||||
// and because I am lazy I am recreating every widget.
|
||||
//
|
||||
// If performance should become a concern this has to be revisited.
|
||||
SetEditMacro(*macro);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||
@@ -115,15 +157,33 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
MacroActionSwitchScene temp;
|
||||
std::string id = temp.GetId();
|
||||
AddMacroAction((int)macro->Actions().size());
|
||||
ui->macroEditActionHelp->setVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx >= (int)macro->Actions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
macro->Actions().emplace_back(MacroActionFactory::Create(id));
|
||||
auto newEntry =
|
||||
new MacroActionEdit(this, ¯o->Actions().back(), id, false);
|
||||
ui->macroEditActionLayout->addWidget(newEntry);
|
||||
ui->macroEditActionHelp->setVisible(false);
|
||||
macro->Actions().erase(macro->Actions().begin() + idx);
|
||||
switcher->abortMacroWait = true;
|
||||
switcher->macroWaitCv.notify_one();
|
||||
macro->UpdateActionIndices();
|
||||
|
||||
// All entry pointers in existing edit widgets after the new entry will
|
||||
// be invalidated by adding the new entry so we have to recreate them
|
||||
// and because I am lazy I am recreating every widget.
|
||||
//
|
||||
// If performance should become a concern this has to be revisited.
|
||||
SetEditMacro(*macro);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionRemove_clicked()
|
||||
@@ -132,24 +192,61 @@ void AdvSceneSwitcher::on_actionRemove_clicked()
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
if (macro->Actions().empty()) {
|
||||
RemoveMacroAction((int)macro->Actions().size() - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
|
||||
{
|
||||
if (pos1 == pos2) {
|
||||
return;
|
||||
}
|
||||
macro->Actions().pop_back();
|
||||
|
||||
int count = ui->macroEditActionLayout->count();
|
||||
auto item = ui->macroEditActionLayout->takeAt(count - 1);
|
||||
|
||||
if (item) {
|
||||
auto widget = item->widget();
|
||||
if (widget) {
|
||||
widget->setVisible(false);
|
||||
}
|
||||
delete item;
|
||||
if (pos1 > pos2) {
|
||||
std::swap(pos1, pos2);
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
ui->macroEditActionHelp->setVisible(true);
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
iter_swap(m->Actions().begin() + pos1, m->Actions().begin() + pos2);
|
||||
m->UpdateActionIndices();
|
||||
|
||||
auto a1 = m->Actions().begin() + pos1;
|
||||
auto a2 = m->Actions().begin() + pos2;
|
||||
|
||||
auto item1 = ui->macroEditActionLayout->takeAt(pos1);
|
||||
auto item2 = ui->macroEditActionLayout->takeAt(pos2 - 1);
|
||||
deleteLayoutItem(item1);
|
||||
deleteLayoutItem(item2);
|
||||
auto widget1 = new MacroActionEdit(this, &(*a1), (*a1)->GetId());
|
||||
auto widget2 = new MacroActionEdit(this, &(*a2), (*a2)->GetId());
|
||||
ConnectControlSignals(widget1);
|
||||
ConnectControlSignals(widget2);
|
||||
ui->macroEditActionLayout->insertWidget(pos1, widget1);
|
||||
ui->macroEditActionLayout->insertWidget(pos2, widget2);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MoveMacroActionUp(int idx)
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 1 || idx >= (int)macro->Actions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwapActions(macro, idx, idx - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MoveMacroActionDown(int idx)
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx >= (int)macro->Actions().size() - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwapActions(macro, idx, idx + 1);
|
||||
}
|
||||
|
||||
187
src/macro-action-file.cpp
Normal file
187
src/macro-action-file.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
#include "headers/macro-action-file.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QFileDialog>
|
||||
|
||||
const std::string MacroActionFile::id = "file";
|
||||
|
||||
bool MacroActionFile::_registered = MacroActionFactory::Register(
|
||||
MacroActionFile::id,
|
||||
{MacroActionFile::Create, MacroActionFileEdit::Create,
|
||||
"AdvSceneSwitcher.action.file"});
|
||||
|
||||
const static std::map<FileAction, std::string> actionTypes = {
|
||||
{FileAction::WRITE, "AdvSceneSwitcher.action.file.type.write"},
|
||||
{FileAction::APPEND, "AdvSceneSwitcher.action.file.type.append"},
|
||||
};
|
||||
|
||||
bool MacroActionFile::PerformAction()
|
||||
{
|
||||
QString path = QString::fromStdString(_file);
|
||||
QFile file(path);
|
||||
bool open = false;
|
||||
switch (_action) {
|
||||
case FileAction::WRITE:
|
||||
open = file.open(QIODevice::WriteOnly);
|
||||
break;
|
||||
case FileAction::APPEND:
|
||||
open = file.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (open) {
|
||||
QTextStream out(&file);
|
||||
out << QString::fromStdString(_text);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionFile::LogAction()
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO, "performed action \"%s\" for file \"%s\"",
|
||||
it->second.c_str(), _file.c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown file action %d",
|
||||
static_cast<int>(_action));
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionFile::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_string(obj, "file", _file.c_str());
|
||||
obs_data_set_string(obj, "text", _text.c_str());
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionFile::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_file = obs_data_get_string(obj, "file");
|
||||
_text = obs_data_get_string(obj, "text");
|
||||
_action = static_cast<FileAction>(obs_data_get_int(obj, "action"));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionFile::GetShortDesc()
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionFileEdit::MacroActionFileEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionFile> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_filePath = new QLineEdit();
|
||||
_browseButton =
|
||||
new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
|
||||
_text = new QPlainTextEdit();
|
||||
_actions = new QComboBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
|
||||
SLOT(FilePathChanged()));
|
||||
QWidget::connect(_browseButton, SIGNAL(clicked()), this,
|
||||
SLOT(BrowseButtonClicked()));
|
||||
QWidget::connect(_text, SIGNAL(textChanged()), this,
|
||||
SLOT(TextChanged()));
|
||||
;
|
||||
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{filePath}}", _filePath},
|
||||
{"{{browseButton}}", _browseButton},
|
||||
{"{{matchText}}", _text},
|
||||
{"{{actions}}", _actions},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.file.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_text);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_filePath->setText(QString::fromStdString(_entryData->_file));
|
||||
_text->setPlainText(QString::fromStdString(_entryData->_text));
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::FilePathChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_file = _filePath->text().toUtf8().constData();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::BrowseButtonClicked()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString path = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr(obs_module_text("AdvSceneSwitcher.fileTab.selectWrite")),
|
||||
QDir::currentPath(),
|
||||
tr(obs_module_text("AdvSceneSwitcher.fileTab.anyFileType")));
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_filePath->setText(path);
|
||||
FilePathChanged();
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::TextChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_text = _text->toPlainText().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<FileAction>(value);
|
||||
}
|
||||
@@ -12,6 +12,8 @@ bool MacroActionFilter::_registered = MacroActionFactory::Register(
|
||||
const static std::map<FilterAction, std::string> actionTypes = {
|
||||
{FilterAction::ENABLE, "AdvSceneSwitcher.action.filter.type.enable"},
|
||||
{FilterAction::DISABLE, "AdvSceneSwitcher.action.filter.type.disable"},
|
||||
{FilterAction::SETTINGS,
|
||||
"AdvSceneSwitcher.action.filter.type.settings"},
|
||||
};
|
||||
|
||||
bool MacroActionFilter::PerformAction()
|
||||
@@ -24,6 +26,9 @@ bool MacroActionFilter::PerformAction()
|
||||
case FilterAction::DISABLE:
|
||||
obs_source_set_enabled(s, false);
|
||||
break;
|
||||
case FilterAction::SETTINGS:
|
||||
setSourceSettings(s, _settings);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -51,6 +56,7 @@ bool MacroActionFilter::Save(obs_data_t *obj)
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
obs_data_set_string(obj, "filter", GetWeakSourceName(_filter).c_str());
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_string(obj, "settings", _settings.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,9 +68,19 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
||||
const char *filterName = obs_data_get_string(obj, "filter");
|
||||
_filter = GetWeakFilterByQString(_source, filterName);
|
||||
_action = static_cast<FilterAction>(obs_data_get_int(obj, "action"));
|
||||
_settings = obs_data_get_string(obj, "settings");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionFilter::GetShortDesc()
|
||||
{
|
||||
if (_filter && _source) {
|
||||
return GetWeakSourceName(_source) + " - " +
|
||||
GetWeakSourceName(_filter);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -72,56 +88,6 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateFilters(QComboBox *list,
|
||||
OBSWeakSource weakSource = nullptr)
|
||||
{
|
||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *ptr) {
|
||||
QComboBox *list = reinterpret_cast<QComboBox *>(ptr);
|
||||
auto name = obs_source_get_name(filter);
|
||||
list->addItem(name);
|
||||
};
|
||||
|
||||
auto s = obs_weak_source_get_source(weakSource);
|
||||
obs_source_enum_filters(s, enumFilters, list);
|
||||
list->model()->sort(0);
|
||||
addSelectionEntry(list,
|
||||
obs_module_text("AdvSceneSwitcher.selectFilter"));
|
||||
obs_source_release(s);
|
||||
list->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
static inline void hasFilterEnum(obs_source_t *, obs_source_t *filter,
|
||||
void *ptr)
|
||||
{
|
||||
if (!filter) {
|
||||
return;
|
||||
}
|
||||
bool *hasFilter = reinterpret_cast<bool *>(ptr);
|
||||
*hasFilter = true;
|
||||
}
|
||||
|
||||
static inline void populateSourcesWithFilter(QComboBox *list)
|
||||
{
|
||||
auto enumSourcesWithFilters = [](void *param, obs_source_t *source) {
|
||||
if (!source) {
|
||||
return true;
|
||||
}
|
||||
QComboBox *list = reinterpret_cast<QComboBox *>(param);
|
||||
bool hasFilter = false;
|
||||
obs_source_enum_filters(source, hasFilterEnum, &hasFilter);
|
||||
if (hasFilter) {
|
||||
list->addItem(obs_source_get_name(source));
|
||||
}
|
||||
return true;
|
||||
};
|
||||
obs_enum_sources(enumSourcesWithFilters, list);
|
||||
obs_enum_scenes(enumSourcesWithFilters, list);
|
||||
list->model()->sort(0);
|
||||
addSelectionEntry(list,
|
||||
obs_module_text("AdvSceneSwitcher.selectSource"));
|
||||
list->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionFilter> entryData)
|
||||
: QWidget(parent)
|
||||
@@ -129,9 +95,12 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
_sources = new QComboBox();
|
||||
_filters = new QComboBox();
|
||||
_actions = new QComboBox();
|
||||
_getSettings = new QPushButton(
|
||||
obs_module_text("AdvSceneSwitcher.action.filter.getSettings"));
|
||||
_settings = new QPlainTextEdit();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
populateSourcesWithFilter(_sources);
|
||||
populateSourcesWithFilterSelection(_sources);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
@@ -139,15 +108,29 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(FilterChanged(const QString &)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsChanged()));
|
||||
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{sources}}", _sources},
|
||||
{"{{filters}}", _filters},
|
||||
{"{{actions}}", _actions},
|
||||
{"{{sources}}", _sources}, {"{{filters}}", _filters},
|
||||
{"{{actions}}", _actions}, {"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->addWidget(_getSettings);
|
||||
buttonLayout->addStretch();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_settings);
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -164,9 +147,11 @@ void MacroActionFilterEdit::UpdateEntryData()
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
populateFilters(_filters, _entryData->_source);
|
||||
populateFilterSelection(_filters, _entryData->_source);
|
||||
_filters->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_filter).c_str());
|
||||
_settings->setPlainText(QString::fromStdString(_entryData->_settings));
|
||||
SetWidgetVisibility(_entryData->_action == FilterAction::SETTINGS);
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SourceChanged(const QString &text)
|
||||
@@ -179,7 +164,7 @@ void MacroActionFilterEdit::SourceChanged(const QString &text)
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
}
|
||||
_filters->clear();
|
||||
populateFilters(_filters, _entryData->_source);
|
||||
populateFilterSelection(_filters, _entryData->_source);
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::FilterChanged(const QString &text)
|
||||
@@ -190,6 +175,8 @@ void MacroActionFilterEdit::FilterChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_filter = GetWeakFilterByQString(_entryData->_source, text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::ActionChanged(int value)
|
||||
@@ -200,4 +187,33 @@ void MacroActionFilterEdit::ActionChanged(int value)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<FilterAction>(value);
|
||||
SetWidgetVisibility(_entryData->_action == FilterAction::SETTINGS);
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_source ||
|
||||
!_entryData->_filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
_settings->setPlainText(
|
||||
formatJsonString(getSourceSettings(_entryData->_filter)));
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SettingsChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_settings = _settings->toPlainText().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SetWidgetVisibility(bool showSettings)
|
||||
{
|
||||
_settings->setVisible(showSettings);
|
||||
_getSettings->setVisible(showSettings);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
377
src/macro-action-hotkey.cpp
Normal file
377
src/macro-action-hotkey.cpp
Normal file
@@ -0,0 +1,377 @@
|
||||
#include "headers/macro-action-hotkey.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
const std::string MacroActionHotkey::id = "hotkey";
|
||||
|
||||
// TODO:
|
||||
// I can't seem to get this to work so drop support for this functionality
|
||||
// on MacOS
|
||||
#if !__APPLE__
|
||||
bool MacroActionHotkey::_registered = MacroActionFactory::Register(
|
||||
MacroActionHotkey::id,
|
||||
{MacroActionHotkey::Create, MacroActionHotkeyEdit::Create,
|
||||
"AdvSceneSwitcher.action.hotkey"});
|
||||
#endif
|
||||
|
||||
bool MacroActionHotkey::PerformAction()
|
||||
{
|
||||
std::vector<HotkeyType> keys;
|
||||
if (_leftShift) {
|
||||
keys.push_back(HotkeyType::Key_Shift_L);
|
||||
}
|
||||
if (_rightShift) {
|
||||
keys.push_back(HotkeyType::Key_Shift_R);
|
||||
}
|
||||
if (_leftCtrl) {
|
||||
keys.push_back(HotkeyType::Key_Control_L);
|
||||
}
|
||||
if (_rightCtrl) {
|
||||
keys.push_back(HotkeyType::Key_Control_R);
|
||||
}
|
||||
if (_leftAlt) {
|
||||
keys.push_back(HotkeyType::Key_Alt_L);
|
||||
}
|
||||
if (_rightAlt) {
|
||||
keys.push_back(HotkeyType::Key_Alt_R);
|
||||
}
|
||||
if (_key != HotkeyType::Key_NoKey) {
|
||||
keys.push_back(_key);
|
||||
}
|
||||
|
||||
if (!keys.empty()) {
|
||||
std::thread t([keys]() { PressKeys(keys); });
|
||||
t.detach();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionHotkey::LogAction()
|
||||
{
|
||||
vblog(LOG_INFO, "sent hotkey");
|
||||
}
|
||||
|
||||
bool MacroActionHotkey::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "key", static_cast<int>(_key));
|
||||
obs_data_set_bool(obj, "left_shift", _leftShift);
|
||||
obs_data_set_bool(obj, "right_shift", _rightShift);
|
||||
obs_data_set_bool(obj, "left_ctrl", _leftCtrl);
|
||||
obs_data_set_bool(obj, "right_ctrl", _rightCtrl);
|
||||
obs_data_set_bool(obj, "left_alt", _leftAlt);
|
||||
obs_data_set_bool(obj, "right_alt", _rightAlt);
|
||||
obs_data_set_bool(obj, "left_meta", _leftMeta);
|
||||
obs_data_set_bool(obj, "right_meta", _rightMeta);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionHotkey::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_key = static_cast<HotkeyType>(obs_data_get_int(obj, "key"));
|
||||
_leftShift = obs_data_get_bool(obj, "left_shift");
|
||||
_rightShift = obs_data_get_bool(obj, "right_shift");
|
||||
_leftCtrl = obs_data_get_bool(obj, "left_ctrl");
|
||||
_rightCtrl = obs_data_get_bool(obj, "right_ctrl");
|
||||
_leftAlt = obs_data_get_bool(obj, "left_alt");
|
||||
_rightAlt = obs_data_get_bool(obj, "right_alt");
|
||||
_leftMeta = obs_data_get_bool(obj, "left_meta");
|
||||
_rightMeta = obs_data_get_bool(obj, "right_meta");
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateKeySelection(QComboBox *list)
|
||||
{
|
||||
list->addItem("No key");
|
||||
list->addItem("A");
|
||||
list->addItem("B");
|
||||
list->addItem("C");
|
||||
list->addItem("D");
|
||||
list->addItem("E");
|
||||
list->addItem("F");
|
||||
list->addItem("G");
|
||||
list->addItem("H");
|
||||
list->addItem("I");
|
||||
list->addItem("J");
|
||||
list->addItem("K");
|
||||
list->addItem("L");
|
||||
list->addItem("M");
|
||||
list->addItem("N");
|
||||
list->addItem("O");
|
||||
list->addItem("P");
|
||||
list->addItem("Q");
|
||||
list->addItem("R");
|
||||
list->addItem("S");
|
||||
list->addItem("T");
|
||||
list->addItem("U");
|
||||
list->addItem("V");
|
||||
list->addItem("W");
|
||||
list->addItem("X");
|
||||
list->addItem("Y");
|
||||
list->addItem("Z");
|
||||
list->addItem("0");
|
||||
list->addItem("1");
|
||||
list->addItem("2");
|
||||
list->addItem("3");
|
||||
list->addItem("4");
|
||||
list->addItem("5");
|
||||
list->addItem("6");
|
||||
list->addItem("7");
|
||||
list->addItem("8");
|
||||
list->addItem("9");
|
||||
list->addItem("F1");
|
||||
list->addItem("F2");
|
||||
list->addItem("F3");
|
||||
list->addItem("F4");
|
||||
list->addItem("F5");
|
||||
list->addItem("F6");
|
||||
list->addItem("F7");
|
||||
list->addItem("F8");
|
||||
list->addItem("F9");
|
||||
list->addItem("F10");
|
||||
list->addItem("F11");
|
||||
list->addItem("F12");
|
||||
list->addItem("F13");
|
||||
list->addItem("F14");
|
||||
list->addItem("F15");
|
||||
list->addItem("F16");
|
||||
list->addItem("F17");
|
||||
list->addItem("F18");
|
||||
list->addItem("F19");
|
||||
list->addItem("F20");
|
||||
list->addItem("F21");
|
||||
list->addItem("F22");
|
||||
list->addItem("F23");
|
||||
list->addItem("F24");
|
||||
list->addItem("Escape");
|
||||
list->addItem("Space");
|
||||
list->addItem("Return");
|
||||
list->addItem("Backspace");
|
||||
list->addItem("Tab");
|
||||
list->addItem("Shift_L");
|
||||
list->addItem("Shift_R");
|
||||
list->addItem("Control_L");
|
||||
list->addItem("Control_R");
|
||||
list->addItem("Alt_L");
|
||||
list->addItem("Alt_R");
|
||||
list->addItem("Win_L");
|
||||
list->addItem("Win_R");
|
||||
list->addItem("Apps");
|
||||
list->addItem("CapsLock");
|
||||
list->addItem("NumLock");
|
||||
list->addItem("ScrollLock");
|
||||
list->addItem("PrintScreen");
|
||||
list->addItem("Pause");
|
||||
list->addItem("Insert");
|
||||
list->addItem("Delete");
|
||||
list->addItem("PageUP");
|
||||
list->addItem("PageDown");
|
||||
list->addItem("Home");
|
||||
list->addItem("End");
|
||||
list->addItem("Left");
|
||||
list->addItem("Right");
|
||||
list->addItem("Up");
|
||||
list->addItem("Down");
|
||||
list->addItem("Numpad0");
|
||||
list->addItem("Numpad1");
|
||||
list->addItem("Numpad2");
|
||||
list->addItem("Numpad3");
|
||||
list->addItem("Numpad4");
|
||||
list->addItem("Numpad5");
|
||||
list->addItem("Numpad6");
|
||||
list->addItem("Numpad7");
|
||||
list->addItem("Numpad8");
|
||||
list->addItem("Numpad9");
|
||||
list->addItem("NumpadAdd");
|
||||
list->addItem("NumpadSubtract");
|
||||
list->addItem("NumpadMultiply");
|
||||
list->addItem("NumpadDivide");
|
||||
list->addItem("NumpadDecimal");
|
||||
list->addItem("NumpadEnter");
|
||||
}
|
||||
|
||||
MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionHotkey> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_keys = new QComboBox();
|
||||
_leftShift = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftShift"));
|
||||
_rightShift = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightShift"));
|
||||
_leftCtrl = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftCtrl"));
|
||||
_rightCtrl = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightCtrl"));
|
||||
_leftAlt = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftAlt"));
|
||||
_rightAlt = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightAlt"));
|
||||
_leftMeta = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftMeta"));
|
||||
_rightMeta = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightMeta"));
|
||||
|
||||
populateKeySelection(_keys);
|
||||
|
||||
QWidget::connect(_keys, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(KeyChanged(int)));
|
||||
QWidget::connect(_leftShift, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(LShiftChanged(int)));
|
||||
QWidget::connect(_rightShift, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RShiftChanged(int)));
|
||||
QWidget::connect(_leftCtrl, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(LCtrlChanged(int)));
|
||||
QWidget::connect(_rightCtrl, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RCtrlChanged(int)));
|
||||
QWidget::connect(_leftAlt, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(LAltChanged(int)));
|
||||
QWidget::connect(_rightAlt, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RAltChanged(int)));
|
||||
QWidget::connect(_leftMeta, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(LMetaChanged(int)));
|
||||
QWidget::connect(_rightMeta, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RMetaChanged(int)));
|
||||
|
||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{keys}}", _keys},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.hotkey.entry"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
line2Layout->addWidget(_leftShift);
|
||||
line2Layout->addWidget(_rightShift);
|
||||
line2Layout->addWidget(_leftCtrl);
|
||||
line2Layout->addWidget(_rightCtrl);
|
||||
line2Layout->addWidget(_leftAlt);
|
||||
line2Layout->addWidget(_rightAlt);
|
||||
line2Layout->addWidget(_leftMeta);
|
||||
line2Layout->addWidget(_rightMeta);
|
||||
line2Layout->addStretch();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
|
||||
if (!canSimulateKeyPresses) {
|
||||
mainLayout->addWidget(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.action.hotkey.disabled")));
|
||||
}
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_keys->setCurrentIndex(static_cast<int>(_entryData->_key));
|
||||
_leftShift->setChecked(_entryData->_leftShift);
|
||||
_rightShift->setChecked(_entryData->_rightShift);
|
||||
_leftCtrl->setChecked(_entryData->_leftCtrl);
|
||||
_rightCtrl->setChecked(_entryData->_rightCtrl);
|
||||
_leftAlt->setChecked(_entryData->_leftAlt);
|
||||
_rightAlt->setChecked(_entryData->_rightAlt);
|
||||
_leftMeta->setChecked(_entryData->_leftMeta);
|
||||
_rightMeta->setChecked(_entryData->_rightMeta);
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::LShiftChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftShift = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::RShiftChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightShift = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::LCtrlChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftCtrl = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::RCtrlChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightCtrl = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::LAltChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftAlt = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::RAltChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightAlt = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::LMetaChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftMeta = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::RMetaChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightMeta = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::KeyChanged(int key)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_key = static_cast<HotkeyType>(key);
|
||||
}
|
||||
@@ -77,6 +77,14 @@ bool MacroActionMacro::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionMacro::GetShortDesc()
|
||||
{
|
||||
if (_macro.get()) {
|
||||
return _macro->Name();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -131,6 +139,8 @@ void MacroActionMacroEdit::MacroChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_macro.UpdateRef(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::ActionChanged(int value)
|
||||
|
||||
@@ -84,6 +84,14 @@ bool MacroActionMedia::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionMedia::GetShortDesc()
|
||||
{
|
||||
if (_mediaSource) {
|
||||
return GetWeakSourceName(_mediaSource);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -140,6 +148,8 @@ void MacroActionMediaEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_mediaSource = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::ActionChanged(int value)
|
||||
|
||||
@@ -14,6 +14,17 @@ bool MacroActionPluginState::_registered = MacroActionFactory::Register(
|
||||
const static std::map<PluginStateAction, std::string> actionTypes = {
|
||||
{PluginStateAction::STOP,
|
||||
"AdvSceneSwitcher.action.pluginState.type.stop"},
|
||||
{PluginStateAction::NO_MATCH_BEHAVIOUR,
|
||||
"AdvSceneSwitcher.action.pluginState.type.noMatch"},
|
||||
};
|
||||
|
||||
const static std::map<NoMatch, std::string> noMatchValues = {
|
||||
{NO_SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch"},
|
||||
{SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo"},
|
||||
{RANDOM_SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom"},
|
||||
};
|
||||
|
||||
void stopPlugin()
|
||||
@@ -22,12 +33,23 @@ void stopPlugin()
|
||||
t.detach();
|
||||
}
|
||||
|
||||
void setNoMatchBehaviour(int value, OBSWeakSource &scene)
|
||||
{
|
||||
switcher->switchIfNotMatching = static_cast<NoMatch>(value);
|
||||
if (switcher->switchIfNotMatching == SWITCH) {
|
||||
switcher->nonMatchingScene = scene;
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionPluginState::PerformAction()
|
||||
{
|
||||
switch (_action) {
|
||||
case PluginStateAction::STOP:
|
||||
stopPlugin();
|
||||
break;
|
||||
case PluginStateAction::NO_MATCH_BEHAVIOUR:
|
||||
setNoMatchBehaviour(_value, _scene);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -36,10 +58,9 @@ bool MacroActionPluginState::PerformAction()
|
||||
|
||||
void MacroActionPluginState::LogAction()
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
switch (_action) {
|
||||
case PluginStateAction::STOP:
|
||||
blog(LOG_INFO, "stop() called by macro", it->second.c_str());
|
||||
blog(LOG_INFO, "stop() called by macro");
|
||||
break;
|
||||
default:
|
||||
blog(LOG_WARNING, "ignored unknown pluginState action %d",
|
||||
@@ -52,6 +73,8 @@ bool MacroActionPluginState::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_int(obj, "value", _value);
|
||||
obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -60,6 +83,9 @@ bool MacroActionPluginState::Load(obs_data_t *obj)
|
||||
MacroAction::Load(obj);
|
||||
_action =
|
||||
static_cast<PluginStateAction>(obs_data_get_int(obj, "action"));
|
||||
_value = obs_data_get_int(obj, "value");
|
||||
const char *sceneName = obs_data_get_string(obj, "scene");
|
||||
_scene = GetWeakSourceByName(sceneName);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -70,20 +96,39 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateValueSelection(QComboBox *list,
|
||||
PluginStateAction action)
|
||||
{
|
||||
if (action == PluginStateAction::NO_MATCH_BEHAVIOUR) {
|
||||
for (auto entry : noMatchValues) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionPluginStateEdit::MacroActionPluginStateEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionPluginState> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_actions = new QComboBox();
|
||||
_values = new QComboBox();
|
||||
_scenes = new QComboBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
populateSceneSelection(_scenes);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_values, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ValueChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SceneChanged(const QString &)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{actions}}", _actions},
|
||||
{"{{values}}", _values},
|
||||
{"{{scenes}}", _scenes},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.pluginState.entry"),
|
||||
@@ -101,6 +146,10 @@ void MacroActionPluginStateEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
populateValueSelection(_values, _entryData->_action);
|
||||
_values->setCurrentIndex(_entryData->_value);
|
||||
_scenes->setCurrentText(GetWeakSourceName(_entryData->_scene).c_str());
|
||||
SetWidgetVisibility(_entryData->_action, _entryData->_value);
|
||||
}
|
||||
|
||||
void MacroActionPluginStateEdit::ActionChanged(int value)
|
||||
@@ -109,6 +158,46 @@ void MacroActionPluginStateEdit::ActionChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<PluginStateAction>(value);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<PluginStateAction>(value);
|
||||
SetWidgetVisibility(_entryData->_action, _entryData->_value);
|
||||
}
|
||||
|
||||
_values->clear();
|
||||
populateValueSelection(_values, _entryData->_action);
|
||||
}
|
||||
|
||||
void MacroActionPluginStateEdit::ValueChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_value = value;
|
||||
SetWidgetVisibility(_entryData->_action, _entryData->_value);
|
||||
}
|
||||
|
||||
void MacroActionPluginStateEdit::SceneChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = GetWeakSourceByQString(text);
|
||||
}
|
||||
|
||||
void MacroActionPluginStateEdit::SetWidgetVisibility(PluginStateAction action,
|
||||
int value)
|
||||
{
|
||||
_values->hide();
|
||||
_scenes->hide();
|
||||
if (action == PluginStateAction::NO_MATCH_BEHAVIOUR) {
|
||||
_values->show();
|
||||
if ((NoMatch)value == SWITCH) {
|
||||
_scenes->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "headers/macro-action-run.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/name-dialog.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
#include <QProcess>
|
||||
@@ -13,7 +14,7 @@ bool MacroActionRun::_registered = MacroActionFactory::Register(
|
||||
|
||||
bool MacroActionRun::PerformAction()
|
||||
{
|
||||
QProcess::startDetached(QString::fromStdString(_path), QStringList());
|
||||
QProcess::startDetached(QString::fromStdString(_path), _args);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -26,6 +27,16 @@ bool MacroActionRun::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_string(obj, "path", _path.c_str());
|
||||
obs_data_array_t *args = obs_data_array_create();
|
||||
for (auto &arg : _args) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
obs_data_set_string(array_obj, "arg",
|
||||
arg.toStdString().c_str());
|
||||
obs_data_array_push_back(args, array_obj);
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "args", args);
|
||||
obs_data_array_release(args);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33,9 +44,23 @@ bool MacroActionRun::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_path = obs_data_get_string(obj, "path");
|
||||
obs_data_array_t *args = obs_data_get_array(obj, "args");
|
||||
size_t count = obs_data_array_count(args);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(args, i);
|
||||
_args << QString::fromStdString(
|
||||
obs_data_get_string(array_obj, "arg"));
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(args);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionRun::GetShortDesc()
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
MacroActionRunEdit::MacroActionRunEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
|
||||
: QWidget(parent)
|
||||
@@ -43,20 +68,63 @@ MacroActionRunEdit::MacroActionRunEdit(
|
||||
_filePath = new QLineEdit();
|
||||
_browseButton =
|
||||
new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
|
||||
_browseButton->setStyleSheet("border:1px solid gray;");
|
||||
_argList = new QListWidget();
|
||||
_addArg = new QPushButton();
|
||||
_addArg->setMaximumSize(QSize(22, 22));
|
||||
_addArg->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("addIconSmall")));
|
||||
_addArg->setFlat(true);
|
||||
_removeArg = new QPushButton();
|
||||
_removeArg->setMaximumSize(QSize(22, 22));
|
||||
_removeArg->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||
_removeArg->setFlat(true);
|
||||
_argUp = new QPushButton();
|
||||
_argUp->setMaximumSize(QSize(22, 22));
|
||||
_argUp->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("upArrowIconSmall")));
|
||||
_argUp->setFlat(true);
|
||||
_argDown = new QPushButton();
|
||||
_argDown->setMaximumSize(QSize(22, 22));
|
||||
_argDown->setProperty(
|
||||
"themeID", QVariant(QString::fromUtf8("downArrowIconSmall")));
|
||||
_argDown->setFlat(true);
|
||||
|
||||
QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
|
||||
SLOT(FilePathChanged()));
|
||||
QWidget::connect(_browseButton, SIGNAL(clicked()), this,
|
||||
SLOT(BrowseButtonClicked()));
|
||||
QWidget::connect(_addArg, SIGNAL(clicked()), this, SLOT(AddArg()));
|
||||
QWidget::connect(_removeArg, SIGNAL(clicked()), this,
|
||||
SLOT(RemoveArg()));
|
||||
QWidget::connect(_argUp, SIGNAL(clicked()), this, SLOT(ArgUp()));
|
||||
QWidget::connect(_argDown, SIGNAL(clicked()), this, SLOT(ArgDown()));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
auto *entryLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{filePath}}", _filePath},
|
||||
{"{{browseButton}}", _browseButton},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
auto *argButtonLayout = new QHBoxLayout;
|
||||
argButtonLayout->addWidget(_addArg);
|
||||
argButtonLayout->addWidget(_removeArg);
|
||||
QFrame *line = new QFrame();
|
||||
line->setFrameShape(QFrame::VLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
argButtonLayout->addWidget(line);
|
||||
argButtonLayout->addWidget(_argUp);
|
||||
argButtonLayout->addWidget(_argDown);
|
||||
argButtonLayout->addStretch();
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.run.arguments")));
|
||||
mainLayout->addWidget(_argList);
|
||||
mainLayout->addLayout(argButtonLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -70,6 +138,10 @@ void MacroActionRunEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
_filePath->setText(QString::fromStdString(_entryData->_path));
|
||||
for (auto &arg : _entryData->_args) {
|
||||
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
||||
item->setData(Qt::UserRole, arg);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::FilePathChanged()
|
||||
@@ -80,6 +152,8 @@ void MacroActionRunEdit::FilePathChanged()
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_path = _filePath->text().toUtf8().constData();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::BrowseButtonClicked()
|
||||
@@ -96,3 +170,77 @@ void MacroActionRunEdit::BrowseButtonClicked()
|
||||
_filePath->setText(path);
|
||||
FilePathChanged();
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::AddArg()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
bool accepted = AdvSSNameDialog::AskForName(
|
||||
this,
|
||||
obs_module_text("AdvSceneSwitcher.action.run.addArgument"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.run.addArgumentDescription"),
|
||||
name, "", 170, false);
|
||||
|
||||
if (!accepted || name.empty()) {
|
||||
return;
|
||||
}
|
||||
auto arg = QString::fromStdString(name);
|
||||
QVariant v = QVariant::fromValue(arg);
|
||||
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
||||
item->setData(Qt::UserRole, arg);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args << arg;
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::RemoveArg()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
int idx = _argList->currentRow();
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
_entryData->_args.removeAt(idx);
|
||||
|
||||
QListWidgetItem *item = _argList->currentItem();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
delete item;
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::ArgUp()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = _argList->currentRow();
|
||||
if (idx != -1 && idx != 0) {
|
||||
_argList->insertItem(idx - 1, _argList->takeItem(idx));
|
||||
_argList->setCurrentRow(idx - 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args.move(idx, idx - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::ArgDown()
|
||||
{
|
||||
int idx = _argList->currentRow();
|
||||
if (idx != -1 && idx != _argList->count() - 1) {
|
||||
_argList->insertItem(idx + 1, _argList->takeItem(idx));
|
||||
_argList->setCurrentRow(idx + 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args.move(idx, idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
208
src/macro-action-scene-order.cpp
Normal file
208
src/macro-action-scene-order.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
#include "headers/macro-action-scene-order.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
const std::string MacroActionSceneOrder::id = "scene_order";
|
||||
|
||||
bool MacroActionSceneOrder::_registered = MacroActionFactory::Register(
|
||||
MacroActionSceneOrder::id,
|
||||
{MacroActionSceneOrder::Create, MacroActionSceneOrderEdit::Create,
|
||||
"AdvSceneSwitcher.action.sceneOrder"});
|
||||
|
||||
const static std::map<SceneOrderAction, std::string> actionTypes = {
|
||||
{SceneOrderAction::MOVE_UP,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.moveUp"},
|
||||
{SceneOrderAction::MOVE_DOWN,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.moveDown"},
|
||||
{SceneOrderAction::MOVE_TOP,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.moveTop"},
|
||||
{SceneOrderAction::MOVE_BOTTOM,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.moveBottom"},
|
||||
{SceneOrderAction::POSITION,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.movePosition"},
|
||||
};
|
||||
|
||||
bool MacroActionSceneOrder::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_scene.GetScene());
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto name = GetWeakSourceName(_source);
|
||||
auto items = getSceneItemsWithName(scene, name);
|
||||
|
||||
for (auto &i : items) {
|
||||
switch (_action) {
|
||||
case SceneOrderAction::MOVE_UP:
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_UP);
|
||||
break;
|
||||
case SceneOrderAction::MOVE_DOWN:
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_DOWN);
|
||||
break;
|
||||
case SceneOrderAction::MOVE_TOP:
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_TOP);
|
||||
break;
|
||||
case SceneOrderAction::MOVE_BOTTOM:
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_BOTTOM);
|
||||
break;
|
||||
case SceneOrderAction::POSITION:
|
||||
obs_sceneitem_set_order_position(i, _position);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
obs_sceneitem_release(i);
|
||||
}
|
||||
|
||||
obs_source_release(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionSceneOrder::LogAction()
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO,
|
||||
"performed order action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(), GetWeakSourceName(_source).c_str(),
|
||||
_scene.ToString().c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown scene order action %d",
|
||||
static_cast<int>(_action));
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionSceneOrder::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_scene.Save(obj);
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_int(obj, "position", _position);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionSceneOrder::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_scene.Load(obj);
|
||||
const char *sourceName = obs_data_get_string(obj, "source");
|
||||
_source = GetWeakSourceByName(sourceName);
|
||||
_action =
|
||||
static_cast<SceneOrderAction>(obs_data_get_int(obj, "action"));
|
||||
_position = obs_data_get_int(obj, "position");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSceneOrder::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return _scene.ToString() + " - " + GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionSceneOrderEdit::MacroActionSceneOrderEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSceneOrder> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_scenes = new SceneSelectionWidget(window(), false, false, true);
|
||||
_sources = new QComboBox();
|
||||
_actions = new QComboBox();
|
||||
_position = new QSpinBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
QWidget::connect(_position, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(PositionChanged(int)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{actions}}", _actions},
|
||||
{"{{position}}", _position},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.sceneOrder.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
_position->setValue(_entryData->_position);
|
||||
_position->setVisible(_entryData->_action ==
|
||||
SceneOrderAction::POSITION);
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
_sources->clear();
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::SourceChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<SceneOrderAction>(value);
|
||||
_position->setVisible(_entryData->_action ==
|
||||
SceneOrderAction::POSITION);
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::PositionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_position = value;
|
||||
}
|
||||
@@ -39,6 +39,17 @@ bool MacroActionSwitchScene::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSwitchScene::GetShortDesc()
|
||||
{
|
||||
if (targetType == SwitchTargetType::Scene && scene) {
|
||||
return GetWeakSourceName(scene);
|
||||
}
|
||||
if (targetType == SwitchTargetType::SceneGroup && group) {
|
||||
return group->name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSwitchScene> entryData)
|
||||
: SwitchWidget(parent, entryData.get(), true, true)
|
||||
@@ -46,6 +57,8 @@ MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
|
||||
_duration = new DurationSelection(parent, false);
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(scenes, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(ChangeHeaderInfo(const QString &)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
@@ -71,3 +84,9 @@ void MacroActionSwitchSceneEdit::DurationChanged(double seconds)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.seconds = seconds;
|
||||
}
|
||||
|
||||
void MacroActionSwitchSceneEdit::ChangeHeaderInfo(const QString &)
|
||||
{
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
271
src/macro-action-scene-transform.cpp
Normal file
271
src/macro-action-scene-transform.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
#include "headers/macro-action-scene-transform.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
const std::string MacroActionSceneTransform::id = "scene_transform";
|
||||
|
||||
bool MacroActionSceneTransform::_registered = MacroActionFactory::Register(
|
||||
MacroActionSceneTransform::id,
|
||||
{MacroActionSceneTransform::Create,
|
||||
MacroActionSceneTransformEdit::Create,
|
||||
"AdvSceneSwitcher.action.sceneTransform"});
|
||||
|
||||
static void load_transform_state(obs_data_t *obj,
|
||||
struct obs_transform_info &info,
|
||||
struct obs_sceneitem_crop &crop)
|
||||
{
|
||||
obs_data_get_vec2(obj, "pos", &info.pos);
|
||||
obs_data_get_vec2(obj, "scale", &info.scale);
|
||||
info.rot = (float)obs_data_get_double(obj, "rot");
|
||||
info.alignment = (uint32_t)obs_data_get_int(obj, "alignment");
|
||||
info.bounds_type =
|
||||
(enum obs_bounds_type)obs_data_get_int(obj, "bounds_type");
|
||||
info.bounds_alignment =
|
||||
(uint32_t)obs_data_get_int(obj, "bounds_alignment");
|
||||
obs_data_get_vec2(obj, "bounds", &info.bounds);
|
||||
crop.top = (int)obs_data_get_int(obj, "top");
|
||||
crop.bottom = (int)obs_data_get_int(obj, "bottom");
|
||||
crop.left = (int)obs_data_get_int(obj, "left");
|
||||
crop.right = (int)obs_data_get_int(obj, "right");
|
||||
}
|
||||
|
||||
bool save_transform_state(obs_data_t *obj, struct obs_transform_info &info,
|
||||
struct obs_sceneitem_crop &crop)
|
||||
{
|
||||
struct vec2 pos = info.pos;
|
||||
struct vec2 scale = info.scale;
|
||||
float rot = info.rot;
|
||||
uint32_t alignment = info.alignment;
|
||||
uint32_t bounds_type = info.bounds_type;
|
||||
uint32_t bounds_alignment = info.bounds_alignment;
|
||||
struct vec2 bounds = info.bounds;
|
||||
|
||||
obs_data_set_vec2(obj, "pos", &pos);
|
||||
obs_data_set_vec2(obj, "scale", &scale);
|
||||
obs_data_set_double(obj, "rot", rot);
|
||||
obs_data_set_int(obj, "alignment", alignment);
|
||||
obs_data_set_int(obj, "bounds_type", bounds_type);
|
||||
obs_data_set_vec2(obj, "bounds", &bounds);
|
||||
obs_data_set_int(obj, "bounds_alignment", bounds_alignment);
|
||||
obs_data_set_int(obj, "top", crop.top);
|
||||
obs_data_set_int(obj, "bottom", crop.bottom);
|
||||
obs_data_set_int(obj, "left", crop.left);
|
||||
obs_data_set_int(obj, "right", crop.right);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionSceneTransform::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_scene.GetScene(false));
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto name = GetWeakSourceName(_source);
|
||||
auto items = getSceneItemsWithName(scene, name);
|
||||
|
||||
for (auto &item : items) {
|
||||
// Merge new settings with current settings
|
||||
struct obs_transform_info info;
|
||||
struct obs_sceneitem_crop crop;
|
||||
obs_sceneitem_get_info(item, &info);
|
||||
obs_sceneitem_get_crop(item, &crop);
|
||||
auto temp = obs_data_create();
|
||||
save_transform_state(temp, info, crop);
|
||||
auto temp2 = obs_data_create();
|
||||
save_transform_state(temp, _info, _crop);
|
||||
obs_data_apply(temp, temp2);
|
||||
load_transform_state(temp, info, crop);
|
||||
obs_data_release(temp);
|
||||
obs_data_release(temp2);
|
||||
|
||||
// Apply settings
|
||||
obs_sceneitem_defer_update_begin(item);
|
||||
obs_sceneitem_set_info(item, &info);
|
||||
obs_sceneitem_set_crop(item, &crop);
|
||||
obs_sceneitem_defer_update_end(item);
|
||||
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
|
||||
obs_source_release(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionSceneTransform::LogAction()
|
||||
{
|
||||
vblog(LOG_INFO,
|
||||
"performed transform action for source \"%s\" on scene \"%s\"",
|
||||
GetWeakSourceName(_source).c_str(), _scene.ToString().c_str());
|
||||
}
|
||||
|
||||
bool MacroActionSceneTransform::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_scene.Save(obj);
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
save_transform_state(obj, _info, _crop);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionSceneTransform::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_scene.Load(obj);
|
||||
const char *sourceName = obs_data_get_string(obj, "source");
|
||||
_source = GetWeakSourceByName(sourceName);
|
||||
load_transform_state(obj, _info, _crop);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSceneTransform::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return _scene.ToString() + " - " + GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MacroActionSceneTransform::GetSettings()
|
||||
{
|
||||
auto data = obs_data_create();
|
||||
save_transform_state(data, _info, _crop);
|
||||
std::string json = obs_data_get_json(data);
|
||||
obs_data_release(data);
|
||||
return json;
|
||||
}
|
||||
|
||||
void MacroActionSceneTransform::SetSettings(std::string &settings)
|
||||
{
|
||||
auto data = obs_data_create_from_json(settings.c_str());
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
load_transform_state(data, _info, _crop);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
MacroActionSceneTransformEdit::MacroActionSceneTransformEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSceneTransform> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_scenes = new SceneSelectionWidget(window(), false, false, true);
|
||||
_sources = new QComboBox();
|
||||
_getSettings = new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneTransform.getTransform"));
|
||||
_settings = new QPlainTextEdit();
|
||||
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsChanged()));
|
||||
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.sceneTransform.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->addWidget(_getSettings);
|
||||
buttonLayout->addStretch();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_settings);
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
if (_entryData->_source) {
|
||||
_settings->setPlainText(
|
||||
formatJsonString(_entryData->GetSettings()));
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
_sources->clear();
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::SourceChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_scene.GetScene(false) ||
|
||||
!_entryData->_source) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto s = obs_weak_source_get_source(_entryData->_scene.GetScene(false));
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto name = GetWeakSourceName(_entryData->_source);
|
||||
auto item = obs_scene_find_source_recursive(scene, name.c_str());
|
||||
obs_source_release(s);
|
||||
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct obs_transform_info info;
|
||||
struct obs_sceneitem_crop crop;
|
||||
obs_sceneitem_get_info(item, &info);
|
||||
obs_sceneitem_get_crop(item, &crop);
|
||||
|
||||
auto data = obs_data_create();
|
||||
save_transform_state(data, info, crop);
|
||||
auto json = obs_data_get_json(data);
|
||||
_settings->setPlainText(formatJsonString(json));
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::SettingsChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
auto json = _settings->toPlainText().toStdString();
|
||||
_entryData->SetSettings(json);
|
||||
}
|
||||
@@ -40,7 +40,7 @@ static bool visibilityEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
||||
|
||||
bool MacroActionSceneVisibility::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_scene);
|
||||
auto s = obs_weak_source_get_source(_scene.GetScene());
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto sourceName = GetWeakSourceName(_source);
|
||||
VisInfo vInfo = {sourceName, _action == SceneVisibilityAction::SHOW};
|
||||
@@ -64,9 +64,9 @@ void MacroActionSceneVisibility::LogAction()
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO,
|
||||
"performed action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(), GetWeakSourceName(_scene).c_str(),
|
||||
GetWeakSourceName(_scene).c_str());
|
||||
"performed visibility action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(), GetWeakSourceName(_source).c_str(),
|
||||
_scene.ToString().c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown SceneVisibility action %d",
|
||||
static_cast<int>(_action));
|
||||
@@ -76,7 +76,7 @@ void MacroActionSceneVisibility::LogAction()
|
||||
bool MacroActionSceneVisibility::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
|
||||
_scene.Save(obj);
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
@@ -85,8 +85,7 @@ bool MacroActionSceneVisibility::Save(obs_data_t *obj)
|
||||
bool MacroActionSceneVisibility::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
const char *sceneName = obs_data_get_string(obj, "scene");
|
||||
_scene = GetWeakSourceByName(sceneName);
|
||||
_scene.Load(obj);
|
||||
const char *sourceName = obs_data_get_string(obj, "source");
|
||||
_source = GetWeakSourceByName(sourceName);
|
||||
_action = static_cast<SceneVisibilityAction>(
|
||||
@@ -94,6 +93,14 @@ bool MacroActionSceneVisibility::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSceneVisibility::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return _scene.ToString() + " - " + GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -101,51 +108,20 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
}
|
||||
}
|
||||
|
||||
static bool enumItem(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
||||
{
|
||||
std::set<QString> *names = reinterpret_cast<std::set<QString> *>(ptr);
|
||||
|
||||
if (obs_sceneitem_is_group(item)) {
|
||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||
obs_scene_enum_items(scene, enumItem, ptr);
|
||||
}
|
||||
auto name = obs_source_get_name(obs_sceneitem_get_source(item));
|
||||
names->emplace(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateSceneItems(QComboBox *list,
|
||||
OBSWeakSource sceneWeakSource = nullptr)
|
||||
{
|
||||
std::set<QString> names;
|
||||
auto s = obs_weak_source_get_source(sceneWeakSource);
|
||||
auto scene = obs_scene_from_source(s);
|
||||
obs_scene_enum_items(scene, enumItem, &names);
|
||||
obs_source_release(s);
|
||||
|
||||
for (auto &name : names) {
|
||||
list->addItem(name);
|
||||
}
|
||||
list->model()->sort(0);
|
||||
addSelectionEntry(list, obs_module_text("AdvSceneSwitcher.selectItem"));
|
||||
list->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSceneVisibility> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_scenes = new QComboBox();
|
||||
_scenes = new SceneSelectionWidget(window(), false, false, true);
|
||||
_sources = new QComboBox();
|
||||
_actions = new QComboBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
populateSceneSelection(_scenes);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SceneChanged(const QString &)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
|
||||
@@ -172,23 +148,23 @@ void MacroActionSceneVisibilityEdit::UpdateEntryData()
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_scenes->setCurrentText(GetWeakSourceName(_entryData->_scene).c_str());
|
||||
populateSceneItems(_sources, _entryData->_scene);
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SceneChanged(const QString &text)
|
||||
void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = GetWeakSourceByQString(text);
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
_sources->clear();
|
||||
populateSceneItems(_sources, _entryData->_scene);
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text)
|
||||
@@ -199,6 +175,8 @@ void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::ActionChanged(int value)
|
||||
|
||||
@@ -16,22 +16,6 @@ const static std::map<SourceAction, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.source.type.settings"},
|
||||
};
|
||||
|
||||
void setSourceSettings(obs_source_t *s, const std::string &settings)
|
||||
{
|
||||
if (settings.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_data_t *data = obs_data_create_from_json(settings.c_str());
|
||||
if (!data) {
|
||||
blog(LOG_WARNING, "invalid source settings provided: \n%s",
|
||||
settings.c_str());
|
||||
return;
|
||||
}
|
||||
obs_source_update(s, data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
bool MacroActionSource::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_source);
|
||||
@@ -83,6 +67,14 @@ bool MacroActionSource::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSource::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -159,6 +151,8 @@ void MacroActionSourceEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::ActionChanged(int value)
|
||||
@@ -179,7 +173,7 @@ void MacroActionSourceEdit::GetSettingsClicked()
|
||||
}
|
||||
|
||||
_settings->setPlainText(
|
||||
QString::fromStdString(getSourceSettings(_entryData->_source)));
|
||||
formatJsonString(getSourceSettings(_entryData->_source)));
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SettingsChanged()
|
||||
|
||||
109
src/macro-action-virtual-cam.cpp
Normal file
109
src/macro-action-virtual-cam.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "headers/macro-action-virtual-cam.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
const std::string MacroActionVCam::id = "virtual_cam";
|
||||
|
||||
bool MacroActionVCam::_registered = MacroActionFactory::Register(
|
||||
MacroActionVCam::id,
|
||||
{MacroActionVCam::Create, MacroActionVCamEdit::Create,
|
||||
"AdvSceneSwitcher.action.virtualCamera"});
|
||||
|
||||
const static std::map<VCamAction, std::string> actionTypes = {
|
||||
{VCamAction::STOP, "AdvSceneSwitcher.action.virtualCamera.type.stop"},
|
||||
{VCamAction::START, "AdvSceneSwitcher.action.virtualCamera.type.start"},
|
||||
};
|
||||
|
||||
bool MacroActionVCam::PerformAction()
|
||||
{
|
||||
switch (_action) {
|
||||
case VCamAction::STOP:
|
||||
if (obs_frontend_virtualcam_active()) {
|
||||
obs_frontend_stop_virtualcam();
|
||||
}
|
||||
break;
|
||||
case VCamAction::START:
|
||||
if (!obs_frontend_virtualcam_active()) {
|
||||
obs_frontend_start_virtualcam();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionVCam::LogAction()
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO, "performed action \"%s\"", it->second.c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown virtual camera action %d",
|
||||
static_cast<int>(_action));
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionVCam::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionVCam::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_action = static_cast<VCamAction>(obs_data_get_int(obj, "action"));
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionVCamEdit::MacroActionVCamEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVCam> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_actions = new QComboBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{actions}}", _actions},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.virtualCamera.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionVCamEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
}
|
||||
|
||||
void MacroActionVCamEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<VCamAction>(value);
|
||||
}
|
||||
@@ -38,9 +38,12 @@ bool MacroActionWait::PerformAction()
|
||||
sleep_duration);
|
||||
|
||||
std::unique_lock<std::mutex> lock(switcher->m);
|
||||
switcher->cv.wait_for(lock, std::chrono::milliseconds((
|
||||
long long)(sleep_duration * 1000)));
|
||||
return !switcher->stop;
|
||||
switcher->abortMacroWait = false;
|
||||
switcher->macroWaitCv.wait_for(
|
||||
lock,
|
||||
std::chrono::milliseconds((long long)(sleep_duration * 1000)),
|
||||
[] { return switcher->abortMacroWait.load(); });
|
||||
return !switcher->abortMacroWait;
|
||||
}
|
||||
|
||||
bool MacroActionWait::Save(obs_data_t *obj)
|
||||
|
||||
@@ -77,6 +77,14 @@ bool MacroConditionAudio::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionAudio::GetShortDesc()
|
||||
{
|
||||
if (_audioSource) {
|
||||
return GetWeakSourceName(_audioSource);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void MacroConditionAudio::SetVolumeLevel(
|
||||
void *data, const float magnitude[MAX_AUDIO_CHANNELS],
|
||||
const float peak[MAX_AUDIO_CHANNELS],
|
||||
@@ -181,6 +189,8 @@ void MacroConditionAudioEdit::SourceChanged(const QString &text)
|
||||
_entryData->_audioSource = GetWeakSourceByQString(text);
|
||||
_entryData->ResetVolmeter();
|
||||
UpdateVolmeterSource();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionAudioEdit::VolumeThresholdChanged(int vol)
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-counter.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionCounter::id = "counter";
|
||||
|
||||
bool MacroConditionCounter::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionCounter::id,
|
||||
{MacroConditionCounter::Create, MacroConditionCounterEdit::Create,
|
||||
"AdvSceneSwitcher.condition.counter"});
|
||||
|
||||
static std::map<CounterCondition, std::string> counterConditionTypes = {
|
||||
{CounterCondition::BELOW,
|
||||
"AdvSceneSwitcher.condition.counter.type.below"},
|
||||
{CounterCondition::ABOVE,
|
||||
"AdvSceneSwitcher.condition.counter.type.above"},
|
||||
{CounterCondition::EQUAL,
|
||||
"AdvSceneSwitcher.condition.counter.type.equal"},
|
||||
};
|
||||
|
||||
bool MacroConditionCounter::CheckCondition()
|
||||
{
|
||||
if (!_macro.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (_condition) {
|
||||
case CounterCondition::BELOW:
|
||||
return _macro->GetCount() < _count;
|
||||
case CounterCondition::ABOVE:
|
||||
return _macro->GetCount() > _count;
|
||||
case CounterCondition::EQUAL:
|
||||
return _macro->GetCount() == _count;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionCounter::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_macro.Save(obj);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
obs_data_set_int(obj, "count", _count);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionCounter::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_macro.Load(obj);
|
||||
_condition = static_cast<CounterCondition>(
|
||||
obs_data_get_int(obj, "condition"));
|
||||
_count = obs_data_get_int(obj, "count");
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : counterConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionCounterEdit::MacroConditionCounterEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionCounter> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_macros = new MacroSelection(parent);
|
||||
_conditions = new QComboBox();
|
||||
_count = new QSpinBox();
|
||||
_currentCount = new QLabel();
|
||||
_resetCount = new QPushButton(
|
||||
obs_module_text("AdvSceneSwitcher.condition.counter.reset"));
|
||||
|
||||
_count->setMaximum(10000000);
|
||||
populateConditionSelection(_conditions);
|
||||
|
||||
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(MacroChanged(const QString &)));
|
||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
||||
SLOT(MacroRemove(const QString &)));
|
||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_count, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(CountChanged(int)));
|
||||
QWidget::connect(_resetCount, SIGNAL(clicked()), this,
|
||||
SLOT(ResetClicked()));
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{macros}}", _macros},
|
||||
{"{{conditions}}", _conditions},
|
||||
{"{{count}}", _count},
|
||||
{"{{currentCount}}", _currentCount},
|
||||
{"{{resetCount}}", _resetCount},
|
||||
};
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.counter.entry.line1"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.counter.entry.line2"),
|
||||
line2Layout, widgetPlaceholders);
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_macros->SetCurrentMacro(_entryData->_macro.get());
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_count->setValue(_entryData->_count);
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::MacroChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_macro.UpdateRef(text);
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::CountChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_count = value;
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::ConditionChanged(int cond)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_condition = static_cast<CounterCondition>(cond);
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::MacroRemove(const QString &name)
|
||||
{
|
||||
UNUSED_PARAMETER(name);
|
||||
if (_entryData) {
|
||||
_entryData->_macro.UpdateRef();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::ResetClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_macro.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_entryData->_macro->ResetCount();
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::UpdateCount()
|
||||
{
|
||||
if (_entryData && _entryData->_macro.get()) {
|
||||
_currentCount->setText(
|
||||
QString::number(_entryData->_macro->GetCount()));
|
||||
} else {
|
||||
_currentCount->setText("-");
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::ResetTimer()
|
||||
{
|
||||
_timer.reset(new QTimer(this));
|
||||
connect(_timer.get(), SIGNAL(timeout()), this, SLOT(UpdateCount()));
|
||||
_timer->start(1000);
|
||||
}
|
||||
261
src/macro-condition-cursor.cpp
Normal file
261
src/macro-condition-cursor.cpp
Normal file
@@ -0,0 +1,261 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-cursor.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionCursor::id = "cursor";
|
||||
|
||||
bool MacroConditionCursor::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionCursor::id,
|
||||
{MacroConditionCursor::Create, MacroConditionCursorEdit::Create,
|
||||
"AdvSceneSwitcher.condition.cursor"});
|
||||
|
||||
static std::map<CursorCondition, std::string> cursorConditionTypes = {
|
||||
{CursorCondition::REGION,
|
||||
"AdvSceneSwitcher.condition.cursor.type.region"},
|
||||
{CursorCondition::MOVING,
|
||||
"AdvSceneSwitcher.condition.cursor.type.moving"},
|
||||
};
|
||||
|
||||
bool MacroConditionCursor::CheckCondition()
|
||||
{
|
||||
std::pair<int, int> cursorPos = getCursorPos();
|
||||
switch (_condition) {
|
||||
case CursorCondition::REGION:
|
||||
return cursorPos.first >= _minX && cursorPos.second >= _minY &&
|
||||
cursorPos.first <= _maxX && cursorPos.second <= _maxY;
|
||||
case CursorCondition::MOVING:
|
||||
return switcher->cursorPosChanged;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionCursor::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
obs_data_set_int(obj, "minX", _minX);
|
||||
obs_data_set_int(obj, "minY", _minY);
|
||||
obs_data_set_int(obj, "maxX", _maxX);
|
||||
obs_data_set_int(obj, "maxY", _maxY);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionCursor::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_condition = static_cast<CursorCondition>(
|
||||
obs_data_get_int(obj, "condition"));
|
||||
_minX = obs_data_get_int(obj, "minX");
|
||||
_minY = obs_data_get_int(obj, "minY");
|
||||
_maxX = obs_data_get_int(obj, "maxX");
|
||||
_maxY = obs_data_get_int(obj, "maxY");
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : cursorConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionCursorEdit::MacroConditionCursorEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionCursor> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_conditions = new QComboBox();
|
||||
_minX = new QSpinBox();
|
||||
_minY = new QSpinBox();
|
||||
_maxX = new QSpinBox();
|
||||
_maxY = new QSpinBox();
|
||||
_frameToggle = new QPushButton(
|
||||
obs_module_text("AdvSceneSwitcher.condition.cursor.showFrame"));
|
||||
_xPos = new QLabel("-");
|
||||
_yPos = new QLabel("-");
|
||||
|
||||
populateConditionSelection(_conditions);
|
||||
|
||||
_minX->setPrefix("Min X: ");
|
||||
_minY->setPrefix("Min Y: ");
|
||||
_maxX->setPrefix("Max X: ");
|
||||
_maxY->setPrefix("Max Y: ");
|
||||
|
||||
_minX->setMinimum(-1000000);
|
||||
_minY->setMinimum(-1000000);
|
||||
_maxX->setMinimum(-1000000);
|
||||
_maxY->setMinimum(-1000000);
|
||||
|
||||
_minX->setMaximum(1000000);
|
||||
_minY->setMaximum(1000000);
|
||||
_maxX->setMaximum(1000000);
|
||||
_maxY->setMaximum(1000000);
|
||||
|
||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_minX, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(MinXChanged(int)));
|
||||
QWidget::connect(_minY, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(MinYChanged(int)));
|
||||
QWidget::connect(_maxX, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(MaxXChanged(int)));
|
||||
QWidget::connect(_maxY, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(MaxYChanged(int)));
|
||||
QWidget::connect(_frameToggle, SIGNAL(clicked()), this,
|
||||
SLOT(ToggleFrame()));
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{conditions}}", _conditions},
|
||||
{"{{minX}}", _minX},
|
||||
{"{{minY}}", _minY},
|
||||
{"{{maxX}}", _maxX},
|
||||
{"{{maxY}}", _maxY},
|
||||
{"{{xPos}}", _xPos},
|
||||
{"{{yPos}}", _yPos},
|
||||
{"{{toggleFrameButton}}", _frameToggle},
|
||||
};
|
||||
QHBoxLayout *line1 = new QHBoxLayout;
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.cursor.entry.line1"),
|
||||
line1, widgetPlaceholders);
|
||||
QHBoxLayout *line2 = new QHBoxLayout;
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.cursor.entry.line2"),
|
||||
line2, widgetPlaceholders);
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(line1);
|
||||
mainLayout->addLayout(line2);
|
||||
setLayout(mainLayout);
|
||||
|
||||
connect(&_timer, &QTimer::timeout, this,
|
||||
&MacroConditionCursorEdit::UpdateCursorPos);
|
||||
_timer.start(1000);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::ConditionChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_condition = static_cast<CursorCondition>(index);
|
||||
SetRegionSelectionVisible(_entryData->_condition ==
|
||||
CursorCondition::REGION);
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::MinXChanged(int pos)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_minX = pos;
|
||||
SetupFrame();
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::MinYChanged(int pos)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_minY = pos;
|
||||
SetupFrame();
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::MaxXChanged(int pos)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_maxX = pos;
|
||||
SetupFrame();
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::MaxYChanged(int pos)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_maxY = pos;
|
||||
SetupFrame();
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::UpdateCursorPos()
|
||||
{
|
||||
std::pair<int, int> position = getCursorPos();
|
||||
_xPos->setText(QString::number(position.first));
|
||||
_yPos->setText(QString::number(position.second));
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::ToggleFrame()
|
||||
{
|
||||
SetupFrame();
|
||||
if (_frame.isVisible()) {
|
||||
_frameToggle->setText(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.cursor.showFrame"));
|
||||
_frame.hide();
|
||||
} else {
|
||||
_frameToggle->setText(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.cursor.hideFrame"));
|
||||
_frame.show();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::SetRegionSelectionVisible(bool visible)
|
||||
{
|
||||
_minX->setVisible(visible);
|
||||
_minY->setVisible(visible);
|
||||
_maxX->setVisible(visible);
|
||||
_maxY->setVisible(visible);
|
||||
_frameToggle->setVisible(visible);
|
||||
if (_frame.isVisible()) {
|
||||
ToggleFrame();
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::SetupFrame()
|
||||
{
|
||||
_frame.setFrameStyle(QFrame::Box | QFrame::Plain);
|
||||
_frame.setWindowFlags(Qt::FramelessWindowHint | Qt::Tool |
|
||||
Qt::WindowTransparentForInput |
|
||||
Qt::WindowDoesNotAcceptFocus |
|
||||
Qt::WindowStaysOnTopHint);
|
||||
_frame.setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
|
||||
if (_entryData) {
|
||||
_frame.setGeometry(_entryData->_minX, _entryData->_minY,
|
||||
_entryData->_maxX - _entryData->_minX,
|
||||
_entryData->_maxY - _entryData->_minY);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionCursorEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_minX->setValue(_entryData->_minX);
|
||||
_minY->setValue(_entryData->_minY);
|
||||
_maxX->setValue(_entryData->_maxX);
|
||||
_maxY->setValue(_entryData->_maxY);
|
||||
SetRegionSelectionVisible(_entryData->_condition ==
|
||||
CursorCondition::REGION);
|
||||
}
|
||||
279
src/macro-condition-date.cpp
Normal file
279
src/macro-condition-date.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-date.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionDate::id = "date";
|
||||
|
||||
bool MacroConditionDate::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionDate::id,
|
||||
{MacroConditionDate::Create, MacroConditionDateEdit::Create,
|
||||
"AdvSceneSwitcher.condition.date", false});
|
||||
|
||||
static std::map<DateCondition, std::string> dateConditionTypes = {
|
||||
{DateCondition::AT, "AdvSceneSwitcher.condition.date.state.at"},
|
||||
{DateCondition::AFTER, "AdvSceneSwitcher.condition.date.state.after"},
|
||||
{DateCondition::BEFORE, "AdvSceneSwitcher.condition.date.state.before"},
|
||||
{DateCondition::BETWEEN,
|
||||
"AdvSceneSwitcher.condition.date.state.between"},
|
||||
};
|
||||
|
||||
bool MacroConditionDate::CheckCondition()
|
||||
{
|
||||
bool match = false;
|
||||
QDateTime cur = QDateTime::currentDateTime();
|
||||
if (_ignoreDate) {
|
||||
_dateTime.setDate(cur.date());
|
||||
_dateTime2.setDate(cur.date());
|
||||
}
|
||||
if (_ignoreTime) {
|
||||
_dateTime.setTime(cur.time());
|
||||
_dateTime2.setTime(cur.time());
|
||||
}
|
||||
|
||||
switch (_condition) {
|
||||
case DateCondition::AT:
|
||||
match = _dateTime >= cur &&
|
||||
_dateTime <= cur.addMSecs(switcher->interval);
|
||||
break;
|
||||
case DateCondition::AFTER:
|
||||
match = cur >= _dateTime;
|
||||
break;
|
||||
case DateCondition::BEFORE:
|
||||
match = cur <= _dateTime;
|
||||
break;
|
||||
case DateCondition::BETWEEN:
|
||||
if (_dateTime2 > _dateTime) {
|
||||
match = cur >= _dateTime && cur <= _dateTime2;
|
||||
} else {
|
||||
match = cur >= _dateTime2 && cur <= _dateTime;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (match && _repeat) {
|
||||
_dateTime = _dateTime.addSecs(_duration.seconds);
|
||||
_dateTime2 = _dateTime2.addSecs(_duration.seconds);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
bool MacroConditionDate::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
obs_data_set_string(obj, "dateTime",
|
||||
_dateTime.toString().toStdString().c_str());
|
||||
obs_data_set_string(obj, "dateTime2",
|
||||
_dateTime2.toString().toStdString().c_str());
|
||||
obs_data_set_bool(obj, "ignoreDate", _ignoreDate);
|
||||
obs_data_set_bool(obj, "ignoreTime", _ignoreTime);
|
||||
obs_data_set_bool(obj, "repeat", _repeat);
|
||||
_duration.Save(obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionDate::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_condition =
|
||||
static_cast<DateCondition>(obs_data_get_int(obj, "condition"));
|
||||
_dateTime = QDateTime::fromString(
|
||||
QString::fromStdString(obs_data_get_string(obj, "dateTime")));
|
||||
_dateTime2 = QDateTime::fromString(
|
||||
QString::fromStdString(obs_data_get_string(obj, "dateTime2")));
|
||||
_ignoreDate = obs_data_get_bool(obj, "ignoreDate");
|
||||
_ignoreTime = obs_data_get_bool(obj, "ignoreTime");
|
||||
_repeat = obs_data_get_bool(obj, "repeat");
|
||||
_duration.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionDate::GetShortDesc()
|
||||
{
|
||||
return _dateTime.toString().toStdString();
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : dateConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionDateEdit::MacroConditionDateEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionDate> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_condition = new QComboBox();
|
||||
_dateTime = new QDateTimeEdit();
|
||||
_dateTime->setCalendarPopup(true);
|
||||
_dateTime->setDisplayFormat("yyyy.MM.dd hh:mm:ss");
|
||||
_dateTime2 = new QDateTimeEdit();
|
||||
_dateTime2->setCalendarPopup(true);
|
||||
_dateTime2->setDisplayFormat("yyyy.MM.dd hh:mm:ss");
|
||||
_ignoreDate = new QCheckBox();
|
||||
_ignoreTime = new QCheckBox();
|
||||
_repeat = new QCheckBox();
|
||||
_duration = new DurationSelection();
|
||||
|
||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_dateTime, SIGNAL(dateTimeChanged(const QDateTime &)),
|
||||
this, SLOT(DateTimeChanged(const QDateTime &)));
|
||||
QWidget::connect(_dateTime2, SIGNAL(dateTimeChanged(const QDateTime &)),
|
||||
this, SLOT(DateTime2Changed(const QDateTime &)));
|
||||
QWidget::connect(_ignoreDate, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(IgnoreDateChanged(int)));
|
||||
QWidget::connect(_ignoreTime, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(IgnoreTimeChanged(int)));
|
||||
QWidget::connect(_repeat, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RepeatChanged(int)));
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||
SLOT(DurationUnitChanged(DurationUnit)));
|
||||
|
||||
populateConditionSelection(_condition);
|
||||
|
||||
auto line1Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{condition}}", _condition},
|
||||
{"{{dateTime}}", _dateTime},
|
||||
{"{{dateTime2}}", _dateTime2},
|
||||
{"{{ignoreDate}}", _ignoreDate},
|
||||
{"{{ignoreTime}}", _ignoreTime},
|
||||
{"{{repeat}}", _repeat},
|
||||
{"{{duration}}", _duration},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.date.entry.line1"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
auto line2Layout = new QHBoxLayout;
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.date.entry.line2"),
|
||||
line2Layout, widgetPlaceholders);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::ConditionChanged(int cond)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_condition = static_cast<DateCondition>(cond);
|
||||
ShowSecondDateSelection(_entryData->_condition ==
|
||||
DateCondition::BETWEEN);
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_dateTime = datetime;
|
||||
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::DateTime2Changed(const QDateTime &datetime)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_dateTime2 = datetime;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::IgnoreDateChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_ignoreDate = state;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::IgnoreTimeChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_ignoreTime = state;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::RepeatChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_repeat = state;
|
||||
_duration->setDisabled(!state);
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::DurationChanged(double seconds)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.seconds = seconds;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::DurationUnitChanged(DurationUnit unit)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.displayUnit = unit;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_condition->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_dateTime->setDateTime(_entryData->_dateTime);
|
||||
_dateTime2->setDateTime(_entryData->_dateTime2);
|
||||
_ignoreDate->setChecked(_entryData->_ignoreDate);
|
||||
_ignoreTime->setChecked(_entryData->_ignoreTime);
|
||||
_repeat->setChecked(_entryData->_repeat);
|
||||
_duration->SetDuration(_entryData->_duration);
|
||||
_duration->setDisabled(!_entryData->_repeat);
|
||||
ShowSecondDateSelection(_entryData->_condition ==
|
||||
DateCondition::BETWEEN);
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::ShowSecondDateSelection(bool visible)
|
||||
{
|
||||
_dateTime2->setVisible(visible);
|
||||
adjustSize();
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-scene.hpp"
|
||||
#include "headers/section.hpp"
|
||||
#include "headers/macro-controls.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
std::map<std::string, MacroConditionInfo> MacroConditionFactory::_methods;
|
||||
|
||||
@@ -87,12 +91,11 @@ static inline void populateConditionSelection(QComboBox *list)
|
||||
|
||||
MacroConditionEdit::MacroConditionEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
|
||||
const std::string &id, bool root, bool startCollapsed)
|
||||
: QWidget(parent)
|
||||
const std::string &id, bool root)
|
||||
: MacroSegmentEdit(parent), _entryData(entryData), _isRoot(root)
|
||||
{
|
||||
_logicSelection = new QComboBox();
|
||||
_conditionSelection = new QComboBox();
|
||||
_section = new Section(300);
|
||||
_dur = new DurationConstraintEdit();
|
||||
|
||||
QWidget::connect(_logicSelection, SIGNAL(currentIndexChanged(int)),
|
||||
@@ -113,15 +116,15 @@ MacroConditionEdit::MacroConditionEdit(
|
||||
|
||||
_section->AddHeaderWidget(_logicSelection);
|
||||
_section->AddHeaderWidget(_conditionSelection);
|
||||
_section->AddHeaderWidget(_headerInfo);
|
||||
_section->AddHeaderWidget(_dur);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(_section);
|
||||
mainLayout->addWidget(_controls);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
_isRoot = root;
|
||||
UpdateEntryData(id, startCollapsed);
|
||||
UpdateEntryData(id);
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
@@ -147,12 +150,23 @@ bool MacroConditionEdit::IsRootNode()
|
||||
return _isRoot;
|
||||
}
|
||||
|
||||
void MacroConditionEdit::UpdateEntryData(const std::string &id, bool collapse)
|
||||
void MacroConditionEdit::SetRootNode(bool root)
|
||||
{
|
||||
const QSignalBlocker blocker(_logicSelection);
|
||||
_logicSelection->clear();
|
||||
populateLogicSelection(_logicSelection, root);
|
||||
}
|
||||
|
||||
void MacroConditionEdit::UpdateEntryData(const std::string &id)
|
||||
{
|
||||
_conditionSelection->setCurrentText(obs_module_text(
|
||||
MacroConditionFactory::GetConditionName(id).c_str()));
|
||||
auto widget =
|
||||
MacroConditionFactory::CreateWidget(id, window(), *_entryData);
|
||||
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||
HeaderInfoChanged(
|
||||
QString::fromStdString((*_entryData)->GetShortDesc()));
|
||||
auto logic = (*_entryData)->GetLogicType();
|
||||
if (IsRootNode()) {
|
||||
_logicSelection->setCurrentIndex(static_cast<int>(logic));
|
||||
@@ -160,11 +174,12 @@ void MacroConditionEdit::UpdateEntryData(const std::string &id, bool collapse)
|
||||
_logicSelection->setCurrentIndex(static_cast<int>(logic) -
|
||||
logic_root_offset);
|
||||
}
|
||||
_section->SetContent(widget, collapse);
|
||||
_section->SetContent(widget, (*_entryData)->GetCollapsed());
|
||||
|
||||
_dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id));
|
||||
auto constraint = (*_entryData)->GetDurationConstraint();
|
||||
_dur->SetValue(constraint);
|
||||
SetFocusPolicyOfWidgets();
|
||||
}
|
||||
|
||||
void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
||||
@@ -177,6 +192,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
||||
|
||||
auto temp = DurationConstraint();
|
||||
_dur->SetValue(temp);
|
||||
HeaderInfoChanged("");
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
auto logic = (*_entryData)->GetLogicType();
|
||||
@@ -184,9 +200,12 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
||||
*_entryData = MacroConditionFactory::Create(id);
|
||||
(*_entryData)->SetLogicType(logic);
|
||||
auto widget =
|
||||
MacroConditionFactory::CreateWidget(id, window(), *_entryData);
|
||||
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||
_section->SetContent(widget, false);
|
||||
_dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id));
|
||||
SetFocusPolicyOfWidgets();
|
||||
}
|
||||
|
||||
void MacroConditionEdit::DurationChanged(double seconds)
|
||||
@@ -219,24 +238,83 @@ void MacroConditionEdit::DurationUnitChanged(DurationUnit unit)
|
||||
(*_entryData)->SetDurationUnit(unit);
|
||||
}
|
||||
|
||||
MacroSegment *MacroConditionEdit::Data()
|
||||
{
|
||||
return _entryData->get();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::AddMacroCondition(int idx)
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx > (int)macro->Conditions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MacroConditionScene temp;
|
||||
std::string id = temp.GetId();
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
bool root = idx == 0;
|
||||
auto cond =
|
||||
macro->Conditions().emplace(macro->Conditions().begin() + idx,
|
||||
MacroConditionFactory::Create(id));
|
||||
auto logic = root ? LogicType::ROOT_NONE : LogicType::NONE;
|
||||
(*cond)->SetLogicType(logic);
|
||||
macro->UpdateConditionIndices();
|
||||
|
||||
// All entry pointers in existing edit widgets after the new entry will
|
||||
// be invalidated by adding the new entry so we have to recreate them
|
||||
// and because I am lazy I am recreating every widget.
|
||||
//
|
||||
// If performance should become a concern this has to be revisited.
|
||||
SetEditMacro(*macro);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_conditionAdd_clicked()
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
MacroConditionScene temp;
|
||||
std::string id = temp.GetId();
|
||||
|
||||
AddMacroCondition((int)macro->Conditions().size());
|
||||
ui->macroEditConditionHelp->setVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroCondition(int idx)
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx >= (int)macro->Conditions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
bool root = macro->Conditions().size() == 0;
|
||||
macro->Conditions().emplace_back(MacroConditionFactory::Create(id));
|
||||
auto logic = root ? LogicType::ROOT_NONE : LogicType::NONE;
|
||||
macro->Conditions().back()->SetLogicType(logic);
|
||||
auto newEntry = new MacroConditionEdit(
|
||||
this, ¯o->Conditions().back(), id, root, false);
|
||||
ui->macroEditConditionLayout->addWidget(newEntry);
|
||||
ui->macroEditConditionHelp->setVisible(false);
|
||||
macro->Conditions().erase(macro->Conditions().begin() + idx);
|
||||
macro->UpdateConditionIndices();
|
||||
|
||||
if (macro->Conditions().size() == 0) {
|
||||
ui->macroEditConditionHelp->setVisible(true);
|
||||
}
|
||||
|
||||
if (idx == 0 && macro->Conditions().size() > 0) {
|
||||
auto newRoot = macro->Conditions().at(0);
|
||||
newRoot->SetLogicType(LogicType::ROOT_NONE);
|
||||
}
|
||||
|
||||
// All entry pointers in existing edit widgets after the new entry will
|
||||
// be invalidated by adding the new entry so we have to recreate them
|
||||
// and because I am lazy I am recreating every widget.
|
||||
//
|
||||
// If performance should become a concern this has to be revisited.
|
||||
SetEditMacro(*macro);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_conditionRemove_clicked()
|
||||
@@ -245,24 +323,71 @@ void AdvSceneSwitcher::on_conditionRemove_clicked()
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
if (macro->Conditions().empty()) {
|
||||
RemoveMacroCondition((int)macro->Conditions().size() - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SwapConditions(Macro *m, int pos1, int pos2)
|
||||
{
|
||||
if (pos1 == pos2) {
|
||||
return;
|
||||
}
|
||||
macro->Conditions().pop_back();
|
||||
|
||||
int count = ui->macroEditConditionLayout->count();
|
||||
auto item = ui->macroEditConditionLayout->takeAt(count - 1);
|
||||
|
||||
if (item) {
|
||||
auto widget = item->widget();
|
||||
if (widget) {
|
||||
widget->setVisible(false);
|
||||
}
|
||||
delete item;
|
||||
if (pos1 > pos2) {
|
||||
std::swap(pos1, pos2);
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
ui->macroEditConditionHelp->setVisible(true);
|
||||
bool root = pos1 == 0;
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
iter_swap(m->Conditions().begin() + pos1,
|
||||
m->Conditions().begin() + pos2);
|
||||
m->UpdateConditionIndices();
|
||||
|
||||
auto c1 = m->Conditions().begin() + pos1;
|
||||
auto c2 = m->Conditions().begin() + pos2;
|
||||
if (root) {
|
||||
auto logic1 = (*c1)->GetLogicType();
|
||||
auto logic2 = (*c2)->GetLogicType();
|
||||
(*c1)->SetLogicType(logic2);
|
||||
(*c2)->SetLogicType(logic1);
|
||||
}
|
||||
|
||||
auto item1 = ui->macroEditConditionLayout->takeAt(pos1);
|
||||
auto item2 = ui->macroEditConditionLayout->takeAt(pos2 - 1);
|
||||
deleteLayoutItem(item1);
|
||||
deleteLayoutItem(item2);
|
||||
auto widget1 =
|
||||
new MacroConditionEdit(this, &(*c1), (*c1)->GetId(), root);
|
||||
auto widget2 =
|
||||
new MacroConditionEdit(this, &(*c2), (*c2)->GetId(), false);
|
||||
ConnectControlSignals(widget1);
|
||||
ConnectControlSignals(widget2);
|
||||
ui->macroEditConditionLayout->insertWidget(pos1, widget1);
|
||||
ui->macroEditConditionLayout->insertWidget(pos2, widget2);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MoveMacroConditionUp(int idx)
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 1 || idx >= (int)macro->Conditions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwapConditions(macro, idx, idx - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MoveMacroConditionDown(int idx)
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx >= (int)macro->Conditions().size() - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwapConditions(macro, idx, idx + 1);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,14 @@ static std::string getRemoteData(std::string &url)
|
||||
f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION,
|
||||
WriteCallback);
|
||||
f_curl_setopt(switcher->curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||
|
||||
// Set timeout to at least one second
|
||||
int timeout = switcher->interval / 1000;
|
||||
if (timeout == 0) {
|
||||
timeout = 1;
|
||||
}
|
||||
f_curl_setopt(switcher->curl, CURLOPT_TIMEOUT, 1);
|
||||
|
||||
f_curl_perform(switcher->curl);
|
||||
}
|
||||
return readBuffer;
|
||||
@@ -67,7 +75,7 @@ bool MacroConditionFile::checkLocalFileContent()
|
||||
{
|
||||
QString t = QString::fromStdString(_text);
|
||||
QFile file(QString::fromStdString(_file));
|
||||
if (_file.empty() || !file.open(QIODevice::ReadOnly)) {
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -119,6 +127,11 @@ bool MacroConditionFile::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionFile::GetShortDesc()
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
MacroConditionFileEdit::MacroConditionFileEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionFile> entryData)
|
||||
: QWidget(parent)
|
||||
@@ -231,6 +244,8 @@ void MacroConditionFileEdit::FilePathChanged()
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_file = _filePath->text().toUtf8().constData();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionFileEdit::BrowseButtonClicked()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user