Compare commits

..

11 Commits

Author SHA1 Message Date
WarmUpTill
7d381b9ba1 Adjust to merge 2021-06-06 19:24:10 +02:00
WarmUpTill
d66a2dc408 Merge branch 'master' into virtual-desktop 2021-06-06 19:14:14 +02:00
WarmUpTill
2ac1a226e2 Implement virtual desktop funcs for windows 2021-05-16 14:58:43 +02:00
WarmUpTill
f56b0b56a7 Merge branch 'master' into virtual-desktop 2021-05-16 13:42:13 +02:00
WarmUpTill
6c1eb3ffab Fix random order of various macro entries 2021-05-15 00:40:43 +02:00
WarmUpTill
e9d6067db2 Show currently active virtual desktop 2021-05-15 00:19:00 +02:00
WarmUpTill
d691492a31 Populate virt desktop selection 2021-05-15 00:04:49 +02:00
WarmUpTill
950dfe8688 Request correct information to get virt desktop count 2021-05-15 00:04:35 +02:00
WarmUpTill
fb38f60609 Drop static used for testing ... 2021-05-14 23:55:23 +02:00
WarmUpTill
3c283a0818 Format 2021-05-14 23:35:57 +02:00
WarmUpTill
271bbcbe95 Add macro condition "virtual desktop" (draft) 2021-05-14 23:34:39 +02:00
137 changed files with 1889 additions and 7433 deletions

View File

@@ -160,7 +160,6 @@ jobs:
libxcb-xinerama0-dev \ libxcb-xinerama0-dev \
libxcomposite-dev \ libxcomposite-dev \
libxinerama-dev \ libxinerama-dev \
libxtst-dev \
libmbedtls-dev \ libmbedtls-dev \
pkg-config \ pkg-config \
python3-dev \ python3-dev \

View File

@@ -1,131 +0,0 @@
# 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
```

View File

@@ -1,347 +1,294 @@
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.5)
project(advanced-scene-switcher) project(advanced-scene-switcher)
add_definitions(-DASIO_STANDALONE)
if(NOT CMAKE_BUILD_TYPE) # generate version info
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/") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(GetGitRevisionDescription) include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1) get_git_head_revision(GIT_REFSPEC GIT_SHA1)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in" configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
"${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
if(WIN32) if(WIN32)
get_filename_component(ISS_PLUGIN_FILES_DIR get_filename_component(ISS_PLUGIN_FILES_DIR "${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
"${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE) file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR) get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}" ISS_MSVC_REDIST_HELPER_DIR)
"${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
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() endif()
# Windows installer
if(WIN32) if(WIN32)
get_filename_component(ISS_PLUGIN_FILES_DIR get_filename_component(ISS_PLUGIN_FILES_DIR "${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
"${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE) file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR) get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}" ISS_MSVC_REDIST_HELPER_DIR)
"${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
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() endif()
# Out of tree specific settings
if(BUILD_OUT_OF_TREE) if(BUILD_OUT_OF_TREE)
set(CMAKE_PREFIX_PATH "${QTDIR}") set(CMAKE_PREFIX_PATH "${QTDIR}")
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/external") 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_directories("${LIBOBS_INCLUDE_DIRS}" "${LIBOBS_FRONTEND_INCLUDE_DIR}" include(external/FindLibObs.cmake)
${Qt5Core_INCLUDES} ${Qt5Widgets_INCLUDES}) 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} )
endif() endif()
# Platform specific settings
if(APPLE) if(APPLE)
find_library(COCOA Cocoa) find_library(COCOA Cocoa)
if(BUILD_OUT_OF_TREE) if(BUILD_OUT_OF_TREE)
find_package(Qt5MacExtras REQUIRED) find_package(Qt5MacExtras REQUIRED)
endif() endif()
include_directories(${COCOA}) include_directories(${COCOA})
endif() endif()
find_package(Libcurl REQUIRED)
include_directories("${LIBCURL_INCLUDE_DIRS}")
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
find_package(X11 REQUIRED COMPONENTS Xtst Xss) find_package(X11 REQUIRED)
link_libraries(${X11_LIBRARIES}) link_libraries(${X11_LIBRARIES})
include_directories("${X11_INCLUDE_DIR}" "${X11_Xtst_INCLUDE_PATH}" include_directories(${X11_INCLUDE_DIR})
"${X11_Xss_INCLUDE_PATH}")
endif() endif()
if(WIN32) include_directories(
set(advanced-scene-switcher_PLATFORM_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
src/win/advanced-scene-switcher-win.cpp) "${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp"
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})
else()
set(advanced-scene-switcher_PLATFORM_SOURCES
src/linux/advanced-scene-switcher-nix.cpp)
set(advanced-scene-switcher_PLATFORM_LIBS Xss)
endif()
# 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()
# 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 set(advanced-scene-switcher_HEADERS
${advanced-scene-switcher_HEADERS} ${advanced-scene-switcher_HEADERS}
src/headers/advanced-scene-switcher.hpp src/headers/advanced-scene-switcher.hpp
src/headers/switcher-data-structs.hpp src/headers/switcher-data-structs.hpp
src/headers/scene-group.hpp src/headers/scene-group.hpp
src/headers/scene-trigger.hpp src/headers/scene-trigger.hpp
src/headers/switch-audio.hpp src/headers/switch-audio.hpp
src/headers/switch-executable.hpp src/headers/switch-executable.hpp
src/headers/switch-file.hpp src/headers/switch-file.hpp
src/headers/switch-idle.hpp src/headers/switch-idle.hpp
src/headers/switch-media.hpp src/headers/switch-media.hpp
src/headers/switch-network.hpp src/headers/switch-network.hpp
src/headers/switch-pause.hpp src/headers/switch-pause.hpp
src/headers/switch-random.hpp src/headers/switch-random.hpp
src/headers/switch-screen-region.hpp src/headers/switch-screen-region.hpp
src/headers/switch-time.hpp src/headers/switch-time.hpp
src/headers/switch-transitions.hpp src/headers/switch-transitions.hpp
src/headers/switch-window.hpp src/headers/switch-window.hpp
src/headers/switch-sequence.hpp src/headers/switch-sequence.hpp
src/headers/switch-video.hpp src/headers/switch-video.hpp
src/headers/switch-generic.hpp src/headers/switch-generic.hpp
src/headers/macro-action-edit.hpp src/headers/macro-action-edit.hpp
src/headers/macro-action-audio.hpp src/headers/macro-action-audio.hpp
src/headers/macro-action-file.hpp src/headers/macro-action-filter.hpp
src/headers/macro-action-filter.hpp src/headers/macro-action-macro.hpp
src/headers/macro-action-hotkey.hpp src/headers/macro-action-media.hpp
src/headers/macro-action-macro.hpp src/headers/macro-action-plugin-state.hpp
src/headers/macro-action-media.hpp src/headers/macro-action-recording.hpp
src/headers/macro-action-plugin-state.hpp src/headers/macro-action-replay-buffer.hpp
src/headers/macro-action-recording.hpp src/headers/macro-action-run.hpp
src/headers/macro-action-replay-buffer.hpp src/headers/macro-action-scene-switch.hpp
src/headers/macro-action-run.hpp src/headers/macro-action-scene-visibility.hpp
src/headers/macro-action-scene-order.hpp src/headers/macro-action-source.hpp
src/headers/macro-action-scene-switch.hpp src/headers/macro-action-streaming.hpp
src/headers/macro-action-scene-transform.hpp src/headers/macro-action-wait.hpp
src/headers/macro-action-scene-visibility.hpp src/headers/macro-condition-edit.hpp
src/headers/macro-action-source.hpp src/headers/macro-condition-audio.hpp
src/headers/macro-action-streaming.hpp src/headers/macro-condition-counter.hpp
src/headers/macro-action-virtual-cam.hpp src/headers/macro-condition-file.hpp
src/headers/macro-action-wait.hpp src/headers/macro-condition-idle.hpp
src/headers/macro-condition-edit.hpp src/headers/macro-condition-interval.hpp
src/headers/macro-condition-audio.hpp src/headers/macro-condition-media.hpp
src/headers/macro-condition-cursor.hpp src/headers/macro-condition-plugin-state.hpp
src/headers/macro-condition-date.hpp src/headers/macro-condition-process.hpp
src/headers/macro-condition-file.hpp src/headers/macro-condition-recording.hpp
src/headers/macro-condition-filter.hpp src/headers/macro-condition-region.hpp
src/headers/macro-condition-hotkey.hpp src/headers/macro-condition-scene.hpp
src/headers/macro-condition-idle.hpp src/headers/macro-condition-source.hpp
src/headers/macro-condition-macro.hpp src/headers/macro-condition-streaming.hpp
src/headers/macro-condition-media.hpp src/headers/macro-condition-video.hpp
src/headers/macro-condition-plugin-state.hpp src/headers/macro-condition-virt-desktop.hpp
src/headers/macro-condition-process.hpp src/headers/macro-condition-window.hpp
src/headers/macro-condition-recording.hpp src/headers/macro.hpp
src/headers/macro-condition-replay-buffer.hpp src/headers/macro-selection.hpp
src/headers/macro-condition-scene-order.hpp src/headers/curl-helper.hpp
src/headers/macro-condition-scene.hpp src/headers/screenshot-helper.hpp
src/headers/macro-condition-source.hpp src/headers/name-dialog.hpp
src/headers/macro-condition-streaming.hpp src/headers/duration-control.hpp
src/headers/macro-condition-timer.hpp src/headers/section.hpp
src/headers/macro-condition-video.hpp src/headers/platform-funcs.hpp
src/headers/macro-condition-virtual-cam.hpp src/headers/utility.hpp
src/headers/macro-condition-window.hpp src/headers/volume-control.hpp
src/headers/macro.hpp src/headers/version.h
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 set(advanced-scene-switcher_SOURCES
${advanced-scene-switcher_SOURCES} ${advanced-scene-switcher_SOURCES}
src/advanced-scene-switcher.cpp src/advanced-scene-switcher.cpp
src/advanced-scene-switcher-module.c src/advanced-scene-switcher-module.c
src/switcher-data-structs.cpp src/switcher-data-structs.cpp
src/scene-group.cpp src/scene-group.cpp
src/scene-trigger.cpp src/scene-trigger.cpp
src/switch-transitions.cpp src/switch-transitions.cpp
src/switch-screen-region.cpp src/switch-screen-region.cpp
src/switch-priority.cpp src/switch-priority.cpp
src/switch-executable.cpp src/switch-executable.cpp
src/switch-idle.cpp src/switch-idle.cpp
src/switch-sequence.cpp src/switch-sequence.cpp
src/switch-file.cpp src/switch-file.cpp
src/switch-window.cpp src/switch-window.cpp
src/switch-media.cpp src/switch-media.cpp
src/switch-network.cpp src/switch-network.cpp
src/hotkey.cpp src/hotkey.cpp
src/general.cpp src/general.cpp
src/switch-pause.cpp src/switch-pause.cpp
src/switch-random.cpp src/switch-random.cpp
src/switch-time.cpp src/switch-time.cpp
src/switch-audio.cpp src/switch-audio.cpp
src/switch-video.cpp src/switch-video.cpp
src/switch-generic.cpp src/switch-generic.cpp
src/macro-action-edit.cpp src/macro-action-edit.cpp
src/macro-action-audio.cpp src/macro-action-audio.cpp
src/macro-action-file.cpp src/macro-action-filter.cpp
src/macro-action-filter.cpp src/macro-action-macro.cpp
src/macro-action-hotkey.cpp src/macro-action-media.cpp
src/macro-action-macro.cpp src/macro-action-plugin-state.cpp
src/macro-action-media.cpp src/macro-action-recording.cpp
src/macro-action-plugin-state.cpp src/macro-action-replay-buffer.cpp
src/macro-action-recording.cpp src/macro-action-run.cpp
src/macro-action-replay-buffer.cpp src/macro-action-scene-switch.cpp
src/macro-action-run.cpp src/macro-action-scene-visibility.cpp
src/macro-action-scene-order.cpp src/macro-action-source.cpp
src/macro-action-scene-switch.cpp src/macro-action-streaming.cpp
src/macro-action-scene-transform.cpp src/macro-action-wait.cpp
src/macro-action-scene-visibility.cpp src/macro-condition-edit.cpp
src/macro-action-source.cpp src/macro-condition-audio.cpp
src/macro-action-streaming.cpp src/macro-condition-counter.cpp
src/macro-action-virtual-cam.cpp src/macro-condition-file.cpp
src/macro-action-wait.cpp src/macro-condition-idle.cpp
src/macro-condition-edit.cpp src/macro-condition-interval.cpp
src/macro-condition-audio.cpp src/macro-condition-media.cpp
src/macro-condition-cursor.cpp src/macro-condition-plugin-state.cpp
src/macro-condition-date.cpp src/macro-condition-process.cpp
src/macro-condition-file.cpp src/macro-condition-recording.cpp
src/macro-condition-filter.cpp src/macro-condition-region.cpp
src/macro-condition-hotkey.cpp src/macro-condition-scene.cpp
src/macro-condition-idle.cpp src/macro-condition-source.cpp
src/macro-condition-macro.cpp src/macro-condition-streaming.cpp
src/macro-condition-media.cpp src/macro-condition-video.cpp
src/macro-condition-plugin-state.cpp src/macro-condition-virt-desktop.cpp
src/macro-condition-process.cpp src/macro-condition-window.cpp
src/macro-condition-recording.cpp src/macro.cpp
src/macro-condition-replay-buffer.cpp src/macro-selection.cpp
src/macro-condition-scene-order.cpp src/macro-tab.cpp
src/macro-condition-scene.cpp src/curl-helper.cpp
src/macro-condition-source.cpp src/screenshot-helper.cpp
src/macro-condition-streaming.cpp src/name-dialog.cpp
src/macro-condition-timer.cpp src/duration-control.cpp
src/macro-condition-video.cpp src/section.cpp
src/macro-condition-virtual-cam.cpp src/utility.cpp
src/macro-condition-window.cpp src/volume-control.cpp
src/macro.cpp src/version.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( set(advanced-scene-switcher_UI
advanced-scene-switcher MODULE ${advanced-scene-switcher_UI}
${advanced-scene-switcher_HEADERS} forms/advanced-scene-switcher.ui
${advanced-scene-switcher_SOURCES} )
${advanced-scene-switcher_UI_HEADERS}
${advanced-scene-switcher_PLATFORM_SOURCES}
${advanced-scene-switcher_PLATFORM_HEADERS})
# Out of tree build if(WIN32)
if(BUILD_OUT_OF_TREE) add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
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 set(advanced-scene-switcher_PLATFORM_SOURCES
# translation files so we can copy them to the correct place later on. src/win/advanced-scene-switcher-win.cpp)
file(GLOB ASS_TRANSLATION_FILES "data/locale/*.ini") elseif(APPLE)
set(advanced-scene-switcher_PLATFORM_SOURCES
# OSX src/osx/advanced-scene-switcher-osx.mm)
if(APPLE) set_source_files_properties(advanced-scene-switcher-osx.mm
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "") PROPERTIES COMPILE_FLAGS "-fobjc-arc")
endif() set(advanced-scene-switcher_PLATFORM_LIBS
${COCOA})
# 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() else()
# In tree build set(advanced-scene-switcher_PLATFORM_SOURCES
target_link_libraries( src/linux/advanced-scene-switcher-nix.cpp)
advanced-scene-switcher ${advanced-scene-switcher_PLATFORM_LIBS} set(advanced-scene-switcher_PLATFORM_LIBS
obs-frontend-api Qt5::Widgets libobs) Xss)
install_obs_plugin_with_data(advanced-scene-switcher data) endif()
qt5_wrap_ui(advanced-scene-switcher_UI_HEADERS
${advanced-scene-switcher_UI}
${advanced-scene-switcher_PLATFORM_UI})
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}
)
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)
# 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"
)
# 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()
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)
endif() endif()

126
README.md
View File

@@ -1,27 +1,119 @@
# SceneSwitcher # SceneSwitcher
An automated scene switcher for OBS Studio An automated scene switcher for OBS Studio
More information can be found on https://obsproject.com/forum/resources/automatic-scene-switching.395/. 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.
## Downloads ## Compiling in tree (recommended)
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
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:
``` ```
sudo snap install obs-studi cd obs-studio/UI/frontend-plugins/
git clone https://github.com/WarmUpTill/SceneSwitcher.git
``` ```
If that is not an option you will have to ... Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt file and add an entry for the scene switcher:
1. Copy the library to the plugins folder of you obs installation. add_subdirectory(SceneSwitcher)
2. Copy the contents of the data directory to its respective folders of your obs installation.
Unfortunately the exact location of these folders may vary from system to system. ## 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
```
## Compiling the plugin ### 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)
See the [build instructions](BUILDING.md). 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
```

View File

@@ -284,8 +284,6 @@ AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="Audio Quelle stu
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="Audio Quelle aktiv schalten" AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="Audio Quelle aktiv schalten"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="Szenenwechsler starten" AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="Szenenwechsler starten"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="Szenenwechsler stoppen" 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.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." 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."

View File

@@ -68,8 +68,6 @@ AdvSceneSwitcher.macroTab.name="Name:"
AdvSceneSwitcher.macroTab.defaultname="Macro %1" AdvSceneSwitcher.macroTab.defaultname="Macro %1"
AdvSceneSwitcher.macroTab.exists="Macro name exists already" AdvSceneSwitcher.macroTab.exists="Macro name exists already"
AdvSceneSwitcher.macroTab.copy="Create copy" AdvSceneSwitcher.macroTab.copy="Create copy"
AdvSceneSwitcher.macroTab.expandAll="Expand all"
AdvSceneSwitcher.macroTab.collapseAll="Collapse all"
; Macro Logic ; Macro Logic
AdvSceneSwitcher.logic.none="Ignore entry" AdvSceneSwitcher.logic.none="Ignore entry"
@@ -85,20 +83,15 @@ AdvSceneSwitcher.condition.audio="Audio"
AdvSceneSwitcher.condition.audio.state.below="Below" AdvSceneSwitcher.condition.audio.state.below="Below"
AdvSceneSwitcher.condition.audio.state.above="Above" AdvSceneSwitcher.condition.audio.state.above="Above"
AdvSceneSwitcher.condition.audio.entry="Volume of {{audioSources}} is {{condition}} {{volume}}" AdvSceneSwitcher.condition.audio.entry="Volume of {{audioSources}} is {{condition}} {{volume}}"
AdvSceneSwitcher.condition.cursor="Cursor" AdvSceneSwitcher.condition.region="Screen region"
AdvSceneSwitcher.condition.cursor.type.region="is in region" AdvSceneSwitcher.condition.region.entry="Cursor is in {{minX}} {{minY}} x {{maxX}} {{maxY}}"
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="Scene"
AdvSceneSwitcher.condition.scene.type.current="Current" AdvSceneSwitcher.condition.scene.type.current="Current"
AdvSceneSwitcher.condition.scene.type.previous="Previous" AdvSceneSwitcher.condition.scene.type.previous="Previous"
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} scene is {{scenes}}" AdvSceneSwitcher.condition.scene.entry="{{sceneType}} scene is {{scenes}}"
AdvSceneSwitcher.condition.window="Window" AdvSceneSwitcher.condition.window="Window"
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} exist and ..." AdvSceneSwitcher.condition.window.entry.line1="{{windows}} exist and ..."
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused {{windowFocusChanged}} foreground window changed" AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused"
AdvSceneSwitcher.condition.file="File" AdvSceneSwitcher.condition.file="File"
AdvSceneSwitcher.condition.file.entry.line1="Content of {{fileType}} {{filePath}} {{browseButton}} matches:" AdvSceneSwitcher.condition.file.entry.line1="Content of {{fileType}} {{filePath}} {{browseButton}} matches:"
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}" AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
@@ -131,22 +124,19 @@ AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for {{duratio
AdvSceneSwitcher.condition.pluginState="Plugin state" AdvSceneSwitcher.condition.pluginState="Plugin state"
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene change was triggered in this interval" AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene change was triggered in this interval"
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}" AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
AdvSceneSwitcher.condition.timer="Timer" AdvSceneSwitcher.condition.virtDesktop="Virtual desktop"
AdvSceneSwitcher.condition.timer.entry.line1="{{duration}} have passed" AdvSceneSwitcher.condition.virtDesktop.notAvailable="Not availbale"
AdvSceneSwitcher.condition.timer.entry.line2="Time remaining: {{remaining}} seconds" AdvSceneSwitcher.condition.virtDesktop.entry.line1="Active virtual desktop is {{virtDesktops}}"
AdvSceneSwitcher.condition.timer.entry.line3="{{reset}} {{autoReset}} Automatically reset timer after duration was reached" AdvSceneSwitcher.condition.virtDesktop.entry.line2="Current: {{currentDesktop}}"
AdvSceneSwitcher.condition.timer.reset="Reset" AdvSceneSwitcher.condition.interval="Interval"
AdvSceneSwitcher.condition.macro="Macro" AdvSceneSwitcher.condition.interval.entry="{{duration}} have passed"
AdvSceneSwitcher.condition.macro.type.count="Count" AdvSceneSwitcher.condition.counter="Count"
AdvSceneSwitcher.condition.macro.type.state="State" AdvSceneSwitcher.condition.counter.type.below="Less than"
AdvSceneSwitcher.condition.macro.type.selection="Condition type: {{types}}" AdvSceneSwitcher.condition.counter.type.above="More than"
AdvSceneSwitcher.condition.macro.count.type.below="Less than" AdvSceneSwitcher.condition.counter.type.equal="Exactly"
AdvSceneSwitcher.condition.macro.count.type.above="More than" AdvSceneSwitcher.condition.counter.reset="Reset"
AdvSceneSwitcher.condition.macro.count.type.equal="Exactly" AdvSceneSwitcher.condition.counter.entry.line1="{{macros}} was executed {{conditions}} {{count}} times"
AdvSceneSwitcher.condition.macro.count.reset="Reset" AdvSceneSwitcher.condition.counter.entry.line2="Current count: {{currentCount}} {{resetCount}}"
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="Source"
AdvSceneSwitcher.condition.source.type.active="Is active" AdvSceneSwitcher.condition.source.type.active="Is active"
AdvSceneSwitcher.condition.source.type.showing="Is showing" AdvSceneSwitcher.condition.source.type.showing="Is showing"
@@ -156,41 +146,6 @@ AdvSceneSwitcher.condition.source.getSettings="Get current settings"
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}" AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}" AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.source.entry.line3="{{regex}} {{getSettings}}" 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 ; Macro Actions
AdvSceneSwitcher.action.switchScene="Switch scene" AdvSceneSwitcher.action.switchScene="Switch scene"
@@ -223,9 +178,6 @@ AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
AdvSceneSwitcher.action.streaming.type.start="Start streaming" AdvSceneSwitcher.action.streaming.type.start="Start streaming"
AdvSceneSwitcher.action.streaming.entry="{{actions}}" AdvSceneSwitcher.action.streaming.entry="{{actions}}"
AdvSceneSwitcher.action.run="Run" 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.run.entry="Run {{filePath}} {{browseButton}}"
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility" AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
AdvSceneSwitcher.action.sceneVisibility.type.show="Show" AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
@@ -234,9 +186,7 @@ AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sourc
AdvSceneSwitcher.action.filter="Filter" AdvSceneSwitcher.action.filter="Filter"
AdvSceneSwitcher.action.filter.type.enable="Enable" AdvSceneSwitcher.action.filter.type.enable="Enable"
AdvSceneSwitcher.action.filter.type.disable="Disable" AdvSceneSwitcher.action.filter.type.disable="Disable"
AdvSceneSwitcher.action.filter.type.settings="Set settings"
AdvSceneSwitcher.action.filter.entry="On {{sources}} {{actions}} {{filters}}" AdvSceneSwitcher.action.filter.entry="On {{sources}} {{actions}} {{filters}}"
AdvSceneSwitcher.action.filter.getSettings="Get current settings"
AdvSceneSwitcher.action.source="Source" AdvSceneSwitcher.action.source="Source"
AdvSceneSwitcher.action.source.type.enable="Enable" AdvSceneSwitcher.action.source.type.enable="Enable"
AdvSceneSwitcher.action.source.type.disable="Disable" AdvSceneSwitcher.action.source.type.disable="Disable"
@@ -259,37 +209,7 @@ AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter"
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}" AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
AdvSceneSwitcher.action.pluginState="Plugin state" AdvSceneSwitcher.action.pluginState="Plugin state"
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin" AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:" AdvSceneSwitcher.action.pluginState.entry="{{actions}}"
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 ; Transition Tab
AdvSceneSwitcher.transitionTab.title="Transition" AdvSceneSwitcher.transitionTab.title="Transition"
@@ -461,7 +381,6 @@ AdvSceneSwitcher.videoTab.help="<html><head/><body><p>This tab will allow you to
; Network Tab ; Network Tab
AdvSceneSwitcher.networkTab.title="Network" 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.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.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)" AdvSceneSwitcher.networkTab.server="Start server (Sends scene switch messages to all connected clients)"
@@ -524,8 +443,6 @@ AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="mute source"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="unmute source" AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="unmute source"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="start the scene switcher" AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="start the scene switcher"
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="stop 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.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." AdvSceneSwitcher.sceneTriggerTab.help="This tab allows you to trigger actions on scene changes, like stopping recording or streaming."
@@ -543,8 +460,6 @@ AdvSceneSwitcher.browse="Browse"
AdvSceneSwitcher.selectScene="--select scene--" AdvSceneSwitcher.selectScene="--select scene--"
AdvSceneSwitcher.selectPreviousScene="Previous Scene" AdvSceneSwitcher.selectPreviousScene="Previous Scene"
AdvSceneSwitcher.selectCurrentScene="Current Scene"
AdvSceneSwitcher.selectAnyScene="Any Scene"
AdvSceneSwitcher.currentTransition="Current Transition" AdvSceneSwitcher.currentTransition="Current Transition"
AdvSceneSwitcher.selectTransition="--select transition--" AdvSceneSwitcher.selectTransition="--select transition--"
AdvSceneSwitcher.selectWindow="--select window--" AdvSceneSwitcher.selectWindow="--select window--"

View File

@@ -81,7 +81,8 @@ AdvSceneSwitcher.condition.audio="Аудио"
AdvSceneSwitcher.ondition.audio.state.below="Ниже" AdvSceneSwitcher.ondition.audio.state.below="Ниже"
AdvSceneSwitcher.ondition.audio.state.above="Выше" AdvSceneSwitcher.ondition.audio.state.above="Выше"
AdvSceneSwitcher.condition.audio.entry="Громкость {{audioSources}} равна {{condition}} {{volume}} в течении {{duration}} секунд" AdvSceneSwitcher.condition.audio.entry="Громкость {{audioSources}} равна {{condition}} {{volume}} в течении {{duration}} секунд"
AdvSceneSwitcher.condition.cursor="Область экрана" AdvSceneSwitcher.condition.region="Область экрана"
AdvSceneSwitcher.condition.region.entry="Курсор находится в {{minX}} {{minY}} x {{maxX}} {{maxY}}"
AdvSceneSwitcher.condition.scene="Сцена" AdvSceneSwitcher.condition.scene="Сцена"
AdvSceneSwitcher.condition.scene.type.current="Текущий" AdvSceneSwitcher.condition.scene.type.current="Текущий"
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий" AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"

View File

@@ -693,6 +693,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_65"> <spacer name="horizontalSpacer_65">
<property name="orientation"> <property name="orientation">
@@ -3716,13 +3723,6 @@
<string>AdvSceneSwitcher.networkTab.title</string> <string>AdvSceneSwitcher.networkTab.title</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_30"> <layout class="QVBoxLayout" name="verticalLayout_30">
<item>
<widget class="QLabel" name="networkTabDescription">
<property name="text">
<string>AdvSceneSwitcher.networkTab.description</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="networkTabWarningLabel"> <widget class="QLabel" name="networkTabWarningLabel">
<property name="text"> <property name="text">

View File

@@ -1,7 +1,6 @@
#include <QMainWindow> #include <QMainWindow>
#include <QAction> #include <QAction>
#include <QFileDialog> #include <QFileDialog>
#include <regex>
#include <obs-module.h> #include <obs-module.h>
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
@@ -200,7 +199,6 @@ void SwitcherData::Thread()
if (checkPause()) { if (checkPause()) {
continue; continue;
} }
setPreconditions();
match = checkForMatch(scene, transition, linger, match = checkForMatch(scene, transition, linger,
setPrevSceneAfterLinger, macroMatch); setPrevSceneAfterLinger, macroMatch);
if (stop) { if (stop) {
@@ -254,37 +252,6 @@ void SwitcherData::Thread()
blog(LOG_INFO, "stopped"); 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, bool SwitcherData::checkForMatch(OBSWeakSource &scene,
OBSWeakSource &transition, int &linger, OBSWeakSource &transition, int &linger,
bool &setPrevSceneAfterLinger, bool &setPrevSceneAfterLinger,
@@ -360,8 +327,7 @@ void switchScene(const sceneSwitchInfo &sceneSwitch)
} }
obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene); obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene);
obs_source_t *currentSource = obs_source_t *currentSource = obs_frontend_get_current_scene();
obs_weak_source_get_source(switcher->currentScene);
if (source && source != currentSource) { if (source && source != currentSource) {
transitionData currentTransitionData; transitionData currentTransitionData;
@@ -424,9 +390,8 @@ void SwitcherData::Stop()
{ {
if (th && th->isRunning()) { if (th && th->isRunning()) {
stop = true; stop = true;
transitionCv.notify_one();
cv.notify_one(); cv.notify_one();
abortMacroWait = true;
macroWaitCv.notify_one();
th->wait(); th->wait();
delete th; delete th;
th = nullptr; th = nullptr;
@@ -468,8 +433,6 @@ extern "C" void FreeSceneSwitcher()
loaded_curl_lib = nullptr; loaded_curl_lib = nullptr;
} }
PlatformCleanup();
delete switcher; delete switcher;
switcher = nullptr; switcher = nullptr;
} }
@@ -481,21 +444,15 @@ void handleSceneChange()
switcher->cv.notify_one(); switcher->cv.notify_one();
} }
// Set current and previous scene // Set previous scene
obs_source_t *source = obs_frontend_get_current_scene(); obs_source_t *source = obs_frontend_get_current_scene();
obs_weak_source_t *ws = obs_source_get_weak_source(source); 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_source_release(source);
obs_weak_source_release(ws); obs_weak_source_release(ws);
if (source && switcher->previousSceneHelper != ws) {
switcher->previousScene = switcher->previousSceneHelper;
switcher->previousSceneHelper = ws;
}
switcher->checkTriggers(); switcher->checkTriggers();
switcher->checkDefaultSceneTransitions(); switcher->checkDefaultSceneTransitions();
@@ -540,11 +497,6 @@ void handlePeviewSceneChange()
} }
} }
void setReplayBufferSaved()
{
switcher->replayBufferSaved = true;
}
// Note to future self: // Note to future self:
// be careful using switcher->m here as there is potential for deadlocks when using // be careful using switcher->m here as there is potential for deadlocks when using
// frontend functions such as obs_frontend_set_current_scene() // frontend functions such as obs_frontend_set_current_scene()
@@ -576,9 +528,6 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
case OBS_FRONTEND_EVENT_STREAMING_STOPPED: case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
resetLiveTime(); resetLiveTime();
break; break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
setReplayBufferSaved();
break;
default: default:
break; break;
} }
@@ -597,8 +546,6 @@ extern "C" void InitSceneSwitcher()
switcher->curl = f_curl_init(); switcher->curl = f_curl_init();
} }
PlatformInit();
auto cb = []() { auto cb = []() {
QMainWindow *window = QMainWindow *window =
(QMainWindow *)obs_frontend_get_main_window(); (QMainWindow *)obs_frontend_get_main_window();

View File

@@ -33,17 +33,6 @@ bool resolveCurl()
bool loadCurl() 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; QStringList locations;
locations << QDir::currentPath(); locations << QDir::currentPath();
#if defined(__linux__) || defined(__APPLE__) #if defined(__linux__) || defined(__APPLE__)

View File

@@ -32,20 +32,6 @@ bool Duration::DurationReached()
return runTime.count() >= seconds * 1000; 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() void Duration::Reset()
{ {
_startTime = {}; _startTime = {};

View File

@@ -14,8 +14,6 @@
} }
class QCloseEvent; class QCloseEvent;
class MacroActionEdit;
class MacroConditionEdit;
/******************************************************************************* /*******************************************************************************
* Advanced Scene Switcher window * Advanced Scene Switcher window
@@ -49,10 +47,6 @@ public:
bool addNewMacro(std::string &name); bool addNewMacro(std::string &name);
Macro *getSelectedMacro(); Macro *getSelectedMacro();
void SetEditMacro(Macro &m); 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 loadUI();
void setupGeneralTab(); void setupGeneralTab();
@@ -115,22 +109,8 @@ public slots:
void on_conditionRemove_clicked(); void on_conditionRemove_clicked();
void on_actionAdd_clicked(); void on_actionAdd_clicked();
void on_actionRemove_clicked(); void on_actionRemove_clicked();
void ShowMacroContextMenu(const QPoint &); void showMacroContextMenu(const QPoint &);
void ShowMacroActionsContextMenu(const QPoint &); void copyMacro();
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_screenRegionSwitches_currentRowChanged(int idx);
void on_showFrame_clicked(); void on_showFrame_clicked();

View File

@@ -5,9 +5,9 @@
#if defined(WIN32) #if defined(WIN32)
constexpr auto curl_library_name = "libcurl.dll"; constexpr auto curl_library_name = "libcurl.dll";
#elif __APPLE__ #elif __APPLE__
constexpr auto curl_library_name = "libcurl.4.dylib"; #define curl_library_name "libcurl.4.dylib"
#else #else
constexpr auto curl_library_name = "libcurl.so.4"; #define curl_library_name "libcurl.so.4"
#endif #endif
typedef CURL *(*initFunction)(void); typedef CURL *(*initFunction)(void);

View File

@@ -21,7 +21,6 @@ public:
const char *unitName = "displayUnit"); const char *unitName = "displayUnit");
bool DurationReached(); bool DurationReached();
double TimeRemaining();
void Reset(); void Reset();
std::string ToString(); std::string ToString();

View File

@@ -1,125 +0,0 @@
#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();

View File

@@ -1,6 +1,5 @@
#pragma once #pragma once
#include <QSpinBox> #include <QSpinBox>
#include <QHBoxLayout>
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
enum class AudioAction { enum class AudioAction {
@@ -16,7 +15,6 @@ public:
void LogAction(); void LogAction();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroAction> Create() static std::shared_ptr<MacroAction> Create()
{ {
@@ -53,8 +51,6 @@ private slots:
void SourceChanged(const QString &text); void SourceChanged(const QString &text);
void ActionChanged(int value); void ActionChanged(int value);
void VolumeChanged(int value); void VolumeChanged(int value);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_audioSources; QComboBox *_audioSources;

View File

@@ -1,5 +1,12 @@
#pragma once #pragma once
#include <QWidget>
#include <QComboBox>
#include <QVBoxLayout>
#include <QGroupBox>
#include <deque>
#include "macro.hpp" #include "macro.hpp"
#include "section.hpp"
struct MacroActionInfo { struct MacroActionInfo {
using TCreateMethod = std::shared_ptr<MacroAction> (*)(); using TCreateMethod = std::shared_ptr<MacroAction> (*)();
@@ -25,23 +32,25 @@ private:
static std::map<std::string, MacroActionInfo> _methods; static std::map<std::string, MacroActionInfo> _methods;
}; };
class MacroActionEdit : public MacroSegmentEdit { class MacroActionEdit : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
MacroActionEdit(QWidget *parent = nullptr, MacroActionEdit(QWidget *parent = nullptr,
std::shared_ptr<MacroAction> * = nullptr, std::shared_ptr<MacroAction> * = nullptr,
const std::string &id = "scene_switch"); const std::string &id = "scene_switch",
void UpdateEntryData(const std::string &id); bool startCollapsed = false);
void UpdateEntryData(const std::string &id, bool collapse);
private slots: private slots:
void ActionSelectionChanged(const QString &text); void ActionSelectionChanged(const QString &text);
private: protected:
MacroSegment *Data();
QComboBox *_actionSelection; QComboBox *_actionSelection;
Section *_section;
std::shared_ptr<MacroAction> *_entryData; std::shared_ptr<MacroAction> *_entryData;
private:
bool _loading = true; bool _loading = true;
}; };

View File

@@ -1,66 +0,0 @@
#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;
};

View File

@@ -1,12 +1,10 @@
#pragma once #pragma once
#include <QSpinBox> #include <QSpinBox>
#include <QPlainTextEdit>
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
enum class FilterAction { enum class FilterAction {
ENABLE, ENABLE,
DISABLE, DISABLE,
SETTINGS,
}; };
class MacroActionFilter : public MacroAction { class MacroActionFilter : public MacroAction {
@@ -15,7 +13,6 @@ public:
void LogAction(); void LogAction();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroAction> Create() static std::shared_ptr<MacroAction> Create()
{ {
@@ -25,7 +22,6 @@ public:
OBSWeakSource _source; OBSWeakSource _source;
OBSWeakSource _filter; OBSWeakSource _filter;
FilterAction _action = FilterAction::ENABLE; FilterAction _action = FilterAction::ENABLE;
std::string _settings = "";
private: private:
static bool _registered; static bool _registered;
@@ -52,20 +48,14 @@ private slots:
void SourceChanged(const QString &text); void SourceChanged(const QString &text);
void FilterChanged(const QString &text); void FilterChanged(const QString &text);
void ActionChanged(int value); void ActionChanged(int value);
void GetSettingsClicked();
void SettingsChanged();
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_sources; QComboBox *_sources;
QComboBox *_filters; QComboBox *_filters;
QComboBox *_actions; QComboBox *_actions;
QPushButton *_getSettings;
QPlainTextEdit *_settings;
std::shared_ptr<MacroActionFilter> _entryData; std::shared_ptr<MacroActionFilter> _entryData;
private: private:
void SetWidgetVisibility(bool); QHBoxLayout *_mainLayout;
bool _loading = true; bool _loading = true;
}; };

View File

@@ -1,79 +0,0 @@
#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;
};

View File

@@ -1,9 +1,8 @@
#pragma once #pragma once
#include <QDoubleSpinBox>
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "macro-selection.hpp" #include "macro-selection.hpp"
#include <QHBoxLayout>
enum class PerformMacroAction { enum class PerformMacroAction {
PAUSE, PAUSE,
UNPAUSE, UNPAUSE,
@@ -16,7 +15,6 @@ public:
void LogAction(); void LogAction();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroAction> Create() static std::shared_ptr<MacroAction> Create()
{ {
@@ -50,8 +48,6 @@ private slots:
void MacroChanged(const QString &text); void MacroChanged(const QString &text);
void MacroRemove(const QString &name); void MacroRemove(const QString &name);
void ActionChanged(int value); void ActionChanged(int value);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
MacroSelection *_macros; MacroSelection *_macros;

View File

@@ -1,8 +1,6 @@
#pragma once #pragma once
#include "macro-action-edit.hpp"
#include <QSpinBox> #include <QSpinBox>
#include <QHBoxLayout> #include "macro-action-edit.hpp"
enum class MediaAction { enum class MediaAction {
PLAY, PLAY,
@@ -19,7 +17,6 @@ public:
void LogAction(); void LogAction();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroAction> Create() static std::shared_ptr<MacroAction> Create()
{ {
@@ -53,8 +50,6 @@ public:
private slots: private slots:
void SourceChanged(const QString &text); void SourceChanged(const QString &text);
void ActionChanged(int value); void ActionChanged(int value);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_mediaSources; QComboBox *_mediaSources;

View File

@@ -1,12 +1,9 @@
#pragma once #pragma once
#include "macro-action-edit.hpp"
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QHBoxLayout> #include "macro-action-edit.hpp"
enum class PluginStateAction { enum class PluginStateAction {
STOP, STOP,
NO_MATCH_BEHAVIOUR,
}; };
class MacroActionPluginState : public MacroAction { class MacroActionPluginState : public MacroAction {
@@ -22,8 +19,6 @@ public:
} }
PluginStateAction _action = PluginStateAction::STOP; PluginStateAction _action = PluginStateAction::STOP;
int _value = 0;
OBSWeakSource _scene;
private: private:
static bool _registered; static bool _registered;
@@ -49,17 +44,12 @@ public:
private slots: private slots:
void ActionChanged(int value); void ActionChanged(int value);
void ValueChanged(int value);
void SceneChanged(const QString &text);
protected: protected:
QComboBox *_actions; QComboBox *_actions;
QComboBox *_values;
QComboBox *_scenes;
std::shared_ptr<MacroActionPluginState> _entryData; std::shared_ptr<MacroActionPluginState> _entryData;
private: private:
void SetWidgetVisibility(PluginStateAction, int);
QHBoxLayout *_mainLayout; QHBoxLayout *_mainLayout;
bool _loading = true; bool _loading = true;
}; };

View File

@@ -1,9 +1,8 @@
#pragma once #pragma once
#include <QDoubleSpinBox>
#include <QLabel>
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include <QComboBox>
#include <QHBoxLayout>
enum class RecordAction { enum class RecordAction {
STOP, STOP,
START, START,

View File

@@ -1,9 +1,8 @@
#pragma once #pragma once
#include <QDoubleSpinBox>
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "duration-control.hpp" #include "duration-control.hpp"
#include <QHBoxLayout>
enum class ReplayBufferAction { enum class ReplayBufferAction {
STOP, STOP,
START, START,

View File

@@ -3,8 +3,6 @@
#include <QLineEdit> #include <QLineEdit>
#include <QPushButton> #include <QPushButton>
#include <QListWidget>
#include <QStringList>
class MacroActionRun : public MacroAction { class MacroActionRun : public MacroAction {
public: public:
@@ -12,7 +10,6 @@ public:
void LogAction(); void LogAction();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroAction> Create() static std::shared_ptr<MacroAction> Create()
{ {
@@ -20,7 +17,6 @@ public:
} }
std::string _path = obs_module_text("AdvSceneSwitcher.enterPath"); std::string _path = obs_module_text("AdvSceneSwitcher.enterPath");
QStringList _args;
private: private:
static bool _registered; static bool _registered;
@@ -45,12 +41,6 @@ public:
private slots: private slots:
void FilePathChanged(); void FilePathChanged();
void BrowseButtonClicked(); void BrowseButtonClicked();
void AddArg();
void RemoveArg();
void ArgUp();
void ArgDown();
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
std::shared_ptr<MacroActionRun> _entryData; std::shared_ptr<MacroActionRun> _entryData;
@@ -58,10 +48,5 @@ protected:
private: private:
QLineEdit *_filePath; QLineEdit *_filePath;
QPushButton *_browseButton; QPushButton *_browseButton;
QListWidget *_argList;
QPushButton *_addArg;
QPushButton *_removeArg;
QPushButton *_argUp;
QPushButton *_argDown;
bool _loading = true; bool _loading = true;
}; };

View File

@@ -1,72 +0,0 @@
#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;
};

View File

@@ -3,15 +3,12 @@
#include "switch-generic.hpp" #include "switch-generic.hpp"
#include "duration-control.hpp" #include "duration-control.hpp"
// TODO: Switch to using SceneSelection class and widget instead
class MacroActionSwitchScene : public MacroAction, public SceneSwitcherEntry { class MacroActionSwitchScene : public MacroAction, public SceneSwitcherEntry {
public: public:
bool PerformAction(); bool PerformAction();
void LogAction(); void LogAction();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroAction> Create() static std::shared_ptr<MacroAction> Create()
@@ -45,9 +42,6 @@ public:
private slots: private slots:
void DurationChanged(double seconds); void DurationChanged(double seconds);
void ChangeHeaderInfo(const QString &);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
DurationSelection *_duration; DurationSelection *_duration;

View File

@@ -1,66 +0,0 @@
#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;
};

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
#include <QSpinBox> #include <QSpinBox>
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "scene-selection.hpp"
enum class SceneVisibilityAction { enum class SceneVisibilityAction {
SHOW, SHOW,
@@ -14,14 +13,13 @@ public:
void LogAction(); void LogAction();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroAction> Create() static std::shared_ptr<MacroAction> Create()
{ {
return std::make_shared<MacroActionSceneVisibility>(); return std::make_shared<MacroActionSceneVisibility>();
} }
SceneSelection _scene; OBSWeakSource _scene;
OBSWeakSource _source; OBSWeakSource _source;
SceneVisibilityAction _action = SceneVisibilityAction::SHOW; SceneVisibilityAction _action = SceneVisibilityAction::SHOW;
@@ -48,14 +46,12 @@ public:
} }
private slots: private slots:
void SceneChanged(const SceneSelection &); void SceneChanged(const QString &text);
void SourceChanged(const QString &text); void SourceChanged(const QString &text);
void ActionChanged(int value); void ActionChanged(int value);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
SceneSelectionWidget *_scenes; QComboBox *_scenes;
QComboBox *_sources; QComboBox *_sources;
QComboBox *_actions; QComboBox *_actions;
std::shared_ptr<MacroActionSceneVisibility> _entryData; std::shared_ptr<MacroActionSceneVisibility> _entryData;

View File

@@ -18,7 +18,6 @@ public:
void LogAction(); void LogAction();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroAction> Create() static std::shared_ptr<MacroAction> Create()
{ {
@@ -55,8 +54,6 @@ private slots:
void ActionChanged(int value); void ActionChanged(int value);
void GetSettingsClicked(); void GetSettingsClicked();
void SettingsChanged(); void SettingsChanged();
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_sources; QComboBox *_sources;
@@ -68,5 +65,6 @@ protected:
private: private:
void SetWidgetVisibility(bool); void SetWidgetVisibility(bool);
QHBoxLayout *_mainLayout;
bool _loading = true; bool _loading = true;
}; };

View File

@@ -1,11 +1,8 @@
#pragma once #pragma once
#include <QDoubleSpinBox>
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "duration-control.hpp" #include "duration-control.hpp"
#include <QDoubleSpinBox>
#include <QComboBox>
#include <QHBoxLayout>
enum class StreamAction { enum class StreamAction {
STOP, STOP,
START, START,

View File

@@ -1,57 +0,0 @@
#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;
};

View File

@@ -1,10 +1,8 @@
#pragma once #pragma once
#include <QDoubleSpinBox>
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "duration-control.hpp" #include "duration-control.hpp"
#include <QDoubleSpinBox>
#include <QHBoxLayout>
enum class WaitType { enum class WaitType {
FIXED, FIXED,
RANDOM, RANDOM,

View File

@@ -17,7 +17,6 @@ public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
@@ -61,8 +60,6 @@ private slots:
void SourceChanged(const QString &text); void SourceChanged(const QString &text);
void VolumeThresholdChanged(int vol); void VolumeThresholdChanged(int vol);
void ConditionChanged(int cond); void ConditionChanged(int cond);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_audioSources; QComboBox *_audioSources;

View File

@@ -1,91 +1,70 @@
#pragma once #pragma once
#include "macro.hpp" #include "macro.hpp"
#include "macro-selection.hpp" #include "macro-selection.hpp"
#include <QWidget>
#include <QComboBox>
#include <QSpinBox> #include <QSpinBox>
#include <QPushButton> #include <QLabel>
#include <QHBoxLayout>
#include <QTimer> #include <QTimer>
enum class MacroConditionMacroType {
COUNT,
STATE,
};
enum class CounterCondition { enum class CounterCondition {
BELOW, BELOW,
ABOVE, ABOVE,
EQUAL, EQUAL,
}; };
class MacroConditionMacro : public MacroRefCondition { class MacroConditionCounter : public MacroRefCondition {
public: public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
return std::make_shared<MacroConditionMacro>(); return std::make_shared<MacroConditionCounter>();
} }
MacroConditionMacroType _type = MacroConditionMacroType::STATE; CounterCondition _condition = CounterCondition::BELOW;
CounterCondition _counterCondition = CounterCondition::BELOW;
int _count = 0; int _count = 0;
private: private:
bool CheckCountCondition();
bool CheckStateCondition();
static bool _registered; static bool _registered;
static const std::string id; static const std::string id;
}; };
class MacroConditionMacroEdit : public QWidget { class MacroConditionCounterEdit : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
MacroConditionMacroEdit( MacroConditionCounterEdit(
QWidget *parent, QWidget *parent,
std::shared_ptr<MacroConditionMacro> cond = nullptr); std::shared_ptr<MacroConditionCounter> cond = nullptr);
void UpdateEntryData(); void UpdateEntryData();
static QWidget *Create(QWidget *parent, static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroCondition> cond) std::shared_ptr<MacroCondition> cond)
{ {
return new MacroConditionMacroEdit( return new MacroConditionCounterEdit(
parent, parent,
std::dynamic_pointer_cast<MacroConditionMacro>(cond)); std::dynamic_pointer_cast<MacroConditionCounter>(cond));
} }
private slots: private slots:
void MacroChanged(const QString &text); void MacroChanged(const QString &text);
void MacroRemove(const QString &name); void MacroRemove(const QString &name);
void TypeChanged(int type);
void CountChanged(int value); void CountChanged(int value);
void ConditionChanged(int cond); void ConditionChanged(int cond);
void ResetClicked(); void ResetClicked();
void UpdateCount(); void UpdateCount();
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
MacroSelection *_macros; MacroSelection *_macros;
QComboBox *_types; QComboBox *_conditions;
QComboBox *_counterConditions;
QSpinBox *_count; QSpinBox *_count;
QLabel *_currentCount; QLabel *_currentCount;
QPushButton *_resetCount; QPushButton *_resetCount;
QHBoxLayout *_settingsLine1;
QHBoxLayout *_settingsLine2;
std::unique_ptr<QTimer> _timer; std::unique_ptr<QTimer> _timer;
std::shared_ptr<MacroConditionMacro> _entryData; std::shared_ptr<MacroConditionCounter> _entryData;
private: private:
void ClearLayouts();
void SetupStateWidgets();
void SetupCountWidgets();
void ResetTimer(); void ResetTimer();
bool _loading = true; bool _loading = true;
}; };

View File

@@ -1,76 +0,0 @@
#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;
};

View File

@@ -1,82 +0,0 @@
#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;
};

View File

@@ -1,5 +1,12 @@
#pragma once #pragma once
#include "advanced-scene-switcher.hpp"
#include "macro.hpp" #include "macro.hpp"
#include "macro-condition-scene.hpp"
#include "section.hpp"
#include "utility.hpp"
#include <QGroupBox>
struct MacroConditionInfo { struct MacroConditionInfo {
using TCreateMethod = std::shared_ptr<MacroCondition> (*)(); using TCreateMethod = std::shared_ptr<MacroCondition> (*)();
@@ -27,16 +34,16 @@ private:
static std::map<std::string, MacroConditionInfo> _methods; static std::map<std::string, MacroConditionInfo> _methods;
}; };
class MacroConditionEdit : public MacroSegmentEdit { class MacroConditionEdit : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
MacroConditionEdit(QWidget *parent = nullptr, MacroConditionEdit(QWidget *parent = nullptr,
std::shared_ptr<MacroCondition> * = nullptr, std::shared_ptr<MacroCondition> * = nullptr,
const std::string &id = "scene", bool root = true); const std::string &id = "scene", bool root = true,
bool startCollapsed = false);
bool IsRootNode(); bool IsRootNode();
void SetRootNode(bool); void UpdateEntryData(const std::string &id, bool collapse);
void UpdateEntryData(const std::string &id);
private slots: private slots:
void LogicSelectionChanged(int idx); void LogicSelectionChanged(int idx);
@@ -45,14 +52,15 @@ private slots:
void DurationConditionChanged(DurationCondition cond); void DurationConditionChanged(DurationCondition cond);
void DurationUnitChanged(DurationUnit unit); void DurationUnitChanged(DurationUnit unit);
private: protected:
MacroSegment *Data();
QComboBox *_logicSelection; QComboBox *_logicSelection;
QComboBox *_conditionSelection; QComboBox *_conditionSelection;
Section *_section;
DurationConstraintEdit *_dur; DurationConstraintEdit *_dur;
std::shared_ptr<MacroCondition> *_entryData; std::shared_ptr<MacroCondition> *_entryData;
private:
bool _isRoot = true; bool _isRoot = true;
bool _loading = true; bool _loading = true;
}; };

View File

@@ -18,7 +18,6 @@ public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
@@ -67,8 +66,6 @@ private slots:
void UseRegexChanged(int state); void UseRegexChanged(int state);
void CheckModificationDateChanged(int state); void CheckModificationDateChanged(int state);
void OnlyMatchIfChangedChanged(int state); void OnlyMatchIfChangedChanged(int state);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_fileType; QComboBox *_fileType;

View File

@@ -1,77 +0,0 @@
#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;
};

View File

@@ -1,54 +0,0 @@
#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;
};

View File

@@ -1,12 +1,10 @@
#pragma once #pragma once
#include "macro.hpp" #include "macro.hpp"
#include <QWidget>
#include <QComboBox>
#include "duration-control.hpp" #include "duration-control.hpp"
#include <QCheckBox> class MacroConditionInterval : public MacroCondition {
#include <QPushButton>
#include <QTimer>
class MacroConditionTimer : public MacroCondition {
public: public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
@@ -14,48 +12,41 @@ public:
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
return std::make_shared<MacroConditionTimer>(); return std::make_shared<MacroConditionInterval>();
} }
Duration _duration; Duration _duration;
bool _oneshot = false;
private: private:
static bool _registered; static bool _registered;
static const std::string id; static const std::string id;
}; };
class MacroConditionTimerEdit : public QWidget { class MacroConditionIntervalEdit : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
MacroConditionTimerEdit( MacroConditionIntervalEdit(
QWidget *parent, QWidget *parent,
std::shared_ptr<MacroConditionTimer> cond = nullptr); std::shared_ptr<MacroConditionInterval> cond = nullptr);
void UpdateEntryData(); void UpdateEntryData();
static QWidget *Create(QWidget *parent, static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroCondition> cond) std::shared_ptr<MacroCondition> cond)
{ {
return new MacroConditionTimerEdit( return new MacroConditionIntervalEdit(
parent, parent,
std::dynamic_pointer_cast<MacroConditionTimer>(cond)); std::dynamic_pointer_cast<MacroConditionInterval>(
cond));
} }
private slots: private slots:
void DurationChanged(double seconds); void DurationChanged(double seconds);
void DurationUnitChanged(DurationUnit unit); void DurationUnitChanged(DurationUnit unit);
void AutoResetChanged(int state);
void ResetClicked();
void UpdateTimeRemaining();
protected: protected:
DurationSelection *_duration; DurationSelection *_duration;
QCheckBox *_autoReset; std::shared_ptr<MacroConditionInterval> _entryData;
QPushButton *_reset;
QLabel *_remaining;
std::shared_ptr<MacroConditionTimer> _entryData;
private: private:
QTimer timer;
bool _loading = true; bool _loading = true;
}; };

View File

@@ -39,7 +39,6 @@ public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
@@ -91,8 +90,6 @@ private slots:
void TimeRestrictionChanged(int index); void TimeRestrictionChanged(int index);
void TimeChanged(double seconds); void TimeChanged(double seconds);
void TimeUnitChanged(DurationUnit unit); void TimeUnitChanged(DurationUnit unit);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_mediaSources; QComboBox *_mediaSources;

View File

@@ -1,15 +1,13 @@
#pragma once #pragma once
#include "macro.hpp" #include "macro.hpp"
#include <QWidget>
#include <QComboBox> #include <QComboBox>
#include <QCheckBox>
class MacroConditionProcess : public MacroCondition { class MacroConditionProcess : public MacroCondition {
public: public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
@@ -43,8 +41,6 @@ public:
private slots: private slots:
void ProcessChanged(const QString &text); void ProcessChanged(const QString &text);
void FocusChanged(int state); void FocusChanged(int state);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_processSelection; QComboBox *_processSelection;

View File

@@ -0,0 +1,55 @@
#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;
};

View File

@@ -1,76 +0,0 @@
#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;
};

View File

@@ -1,7 +1,5 @@
#pragma once #pragma once
#include "macro.hpp" #include "macro.hpp"
#include "scene-selection.hpp"
#include <QWidget> #include <QWidget>
#include <QComboBox> #include <QComboBox>
@@ -15,14 +13,13 @@ public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
return std::make_shared<MacroConditionScene>(); return std::make_shared<MacroConditionScene>();
} }
SceneSelection _scene; OBSWeakSource _scene;
SceneType _type; SceneType _type;
private: private:
@@ -47,13 +44,11 @@ public:
} }
private slots: private slots:
void SceneChanged(const SceneSelection &); void SceneChanged(const QString &text);
void TypeChanged(int value); void TypeChanged(int value);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
SceneSelectionWidget *_scenes; QComboBox *_sceneSelection;
QComboBox *_sceneType; QComboBox *_sceneType;
std::shared_ptr<MacroConditionScene> _entryData; std::shared_ptr<MacroConditionScene> _entryData;

View File

@@ -1,10 +1,7 @@
#pragma once #pragma once
#include "macro.hpp" #include "macro.hpp"
#include <QWidget>
#include <QComboBox> #include <QComboBox>
#include <QPushButton>
#include <QPlainTextEdit>
#include <QCheckBox>
enum class SourceCondition { enum class SourceCondition {
ACTIVE, ACTIVE,
@@ -17,7 +14,6 @@ public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
@@ -56,8 +52,6 @@ private slots:
void GetSettingsClicked(); void GetSettingsClicked();
void SettingsChanged(); void SettingsChanged();
void RegexChanged(int); void RegexChanged(int);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_sources; QComboBox *_sources;

View File

@@ -19,7 +19,6 @@ public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
QImage GetMatchImage() { return _matchImage; }; QImage GetMatchImage() { return _matchImage; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
@@ -66,8 +65,6 @@ private slots:
void ConditionChanged(int cond); void ConditionChanged(int cond);
void FilePathChanged(); void FilePathChanged();
void BrowseButtonClicked(); void BrowseButtonClicked();
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_videoSelection; QComboBox *_videoSelection;

View File

@@ -3,13 +3,7 @@
#include <QWidget> #include <QWidget>
#include <QComboBox> #include <QComboBox>
enum class ReplayBufferState { class MacroConditionVirtDesktop : public MacroCondition {
STOP,
START,
SAVE,
};
class MacroConditionReplayBuffer : public MacroCondition {
public: public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
@@ -17,39 +11,40 @@ public:
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
return std::make_shared<MacroConditionReplayBuffer>(); return std::make_shared<MacroConditionVirtDesktop>();
} }
long _desktop = 0;
ReplayBufferState _state;
private: private:
static bool _registered; static bool _registered;
static const std::string id; static const std::string id;
}; };
class MacroConditionReplayBufferEdit : public QWidget { class MacroConditionVirtDesktopEdit : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
MacroConditionReplayBufferEdit( MacroConditionVirtDesktopEdit(
QWidget *parent, QWidget *parent,
std::shared_ptr<MacroConditionReplayBuffer> cond = nullptr); std::shared_ptr<MacroConditionVirtDesktop> cond = nullptr);
void UpdateEntryData(); void UpdateEntryData();
static QWidget *Create(QWidget *parent, static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroCondition> cond) std::shared_ptr<MacroCondition> cond)
{ {
return new MacroConditionReplayBufferEdit( return new MacroConditionVirtDesktopEdit(
parent, parent,
std::dynamic_pointer_cast<MacroConditionReplayBuffer>( std::dynamic_pointer_cast<MacroConditionVirtDesktop>(
cond)); cond));
} }
private slots: private slots:
void StateChanged(int value); void DesktopChanged(int value);
void UpdateCurrentDesktop();
protected: protected:
QComboBox *_state; QComboBox *_virtDesktops;
std::shared_ptr<MacroConditionReplayBuffer> _entryData; QLabel *_currentDesktop;
std::shared_ptr<MacroConditionVirtDesktop> _entryData;
private: private:
bool _loading = true; bool _loading = true;

View File

@@ -1,54 +0,0 @@
#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;
};

View File

@@ -1,15 +1,13 @@
#pragma once #pragma once
#include "macro.hpp" #include "macro.hpp"
#include <QWidget>
#include <QComboBox> #include <QComboBox>
#include <QCheckBox>
class MacroConditionWindow : public MacroCondition { class MacroConditionWindow : public MacroCondition {
public: public:
bool CheckCondition(); bool CheckCondition();
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
std::string GetShortDesc();
std::string GetId() { return id; }; std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create() static std::shared_ptr<MacroCondition> Create()
{ {
@@ -26,7 +24,6 @@ public:
bool _fullscreen = false; bool _fullscreen = false;
bool _maximized = false; bool _maximized = false;
bool _focus = true; bool _focus = true;
bool _windowFocusChanged = false;
private: private:
static bool _registered; static bool _registered;
@@ -53,17 +50,13 @@ private slots:
void WindowChanged(const QString &text); void WindowChanged(const QString &text);
void FullscreenChanged(int state); void FullscreenChanged(int state);
void MaximizedChanged(int state); void MaximizedChanged(int state);
void FocusedChanged(int state); void FocusChanged(int state);
void WindowFocusChanged(int state);
signals:
void HeaderInfoChanged(const QString &);
protected: protected:
QComboBox *_windowSelection; QComboBox *_windowSelection;
QCheckBox *_fullscreen; QCheckBox *_fullscreen;
QCheckBox *_maximized; QCheckBox *_maximized;
QCheckBox *_focused; QCheckBox *_focused;
QCheckBox *_windowFocusChanged;
std::shared_ptr<MacroConditionWindow> _entryData; std::shared_ptr<MacroConditionWindow> _entryData;
private: private:

View File

@@ -1,31 +0,0 @@
#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;
};

View File

@@ -1,71 +0,0 @@
#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;
};

View File

@@ -1,5 +1,4 @@
#pragma once #pragma once
#include "macro-segment.hpp"
#include "duration-control.hpp" #include "duration-control.hpp"
#include <string> #include <string>
@@ -37,11 +36,13 @@ struct LogicTypeInfo {
std::string _name; std::string _name;
}; };
class MacroCondition : public MacroSegment { class MacroCondition {
public: public:
virtual bool CheckCondition() = 0; virtual bool CheckCondition() = 0;
virtual bool Save(obs_data_t *obj) = 0; virtual bool Save(obs_data_t *obj) = 0;
virtual bool Load(obs_data_t *obj) = 0; virtual bool Load(obs_data_t *obj) = 0;
virtual std::string GetId() = 0;
LogicType GetLogicType() { return _logic; } LogicType GetLogicType() { return _logic; }
void SetLogicType(LogicType logic) { _logic = logic; } void SetLogicType(LogicType logic) { _logic = logic; }
static const std::map<LogicType, LogicTypeInfo> logicTypes; static const std::map<LogicType, LogicTypeInfo> logicTypes;
@@ -59,11 +60,12 @@ private:
DurationConstraint _duration; DurationConstraint _duration;
}; };
class MacroAction : public MacroSegment { class MacroAction {
public: public:
virtual bool PerformAction() = 0; virtual bool PerformAction() = 0;
virtual bool Save(obs_data_t *obj) = 0; virtual bool Save(obs_data_t *obj) = 0;
virtual bool Load(obs_data_t *obj) = 0; virtual bool Load(obs_data_t *obj) = 0;
virtual std::string GetId() = 0;
virtual void LogAction(); virtual void LogAction();
}; };
@@ -85,8 +87,6 @@ public:
{ {
return _conditions; return _conditions;
} }
void UpdateActionIndices();
void UpdateConditionIndices();
std::deque<std::shared_ptr<MacroAction>> &Actions() { return _actions; } std::deque<std::shared_ptr<MacroAction>> &Actions() { return _actions; }
bool Save(obs_data_t *obj); bool Save(obs_data_t *obj);

View File

@@ -16,7 +16,7 @@ public:
static bool AskForName(QWidget *parent, const QString &title, static bool AskForName(QWidget *parent, const QString &title,
const QString &text, std::string &userTextInput, const QString &text, std::string &userTextInput,
const QString &placeHolder = QString(""), const QString &placeHolder = QString(""),
int maxSize = 170, bool clean = true); int maxSize = 170);
private: private:
QLabel *label; QLabel *label;

View File

@@ -1,5 +1,4 @@
#pragma once #pragma once
#include "hotkey.hpp"
void GetWindowList(std::vector<std::string> &windows); void GetWindowList(std::vector<std::string> &windows);
void GetWindowList(QStringList &windows); void GetWindowList(QStringList &windows);
@@ -10,6 +9,5 @@ std::pair<int, int> getCursorPos();
int secondsSinceLastInput(); int secondsSinceLastInput();
void GetProcessList(QStringList &processes); void GetProcessList(QStringList &processes);
bool isInFocus(const QString &executable); bool isInFocus(const QString &executable);
void PressKeys(const std::vector<HotkeyType> keys); bool GetCurrentVirtualDesktop(long &desktop);
void PlatformInit(); bool GetVirtualDesktopCount(long &ndesktops);
void PlatformCleanup();

View File

@@ -82,6 +82,3 @@ private:
SceneGroup *sceneGroup = nullptr; SceneGroup *sceneGroup = nullptr;
}; };
SceneGroup *GetSceneGroupByName(const char *name);
SceneGroup *GetSceneGroupByQString(const QString &name);

View File

@@ -1,51 +0,0 @@
#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);
};

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"
@@ -34,9 +27,6 @@ enum class sceneTriggerAction {
START_SWITCHER, START_SWITCHER,
STOP_SWITCHER, STOP_SWITCHER,
START_VCAM,
STOP_VCAM,
}; };
struct SceneTrigger : SceneSwitcherEntry { struct SceneTrigger : SceneSwitcherEntry {

View File

@@ -23,8 +23,6 @@ protected:
private slots: private slots:
void AnimationFinished(); void AnimationFinished();
void Collapse(bool collapse); void Collapse(bool collapse);
signals:
void Collapsed(bool);
private: private:
void SetupAnimations(); void SetupAnimations();

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include <QSpinBox> #include <QSpinBox>
#include <limits> #include <limits>

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include <QCheckBox> #include <QCheckBox>
#include "switch-generic.hpp" #include "switch-generic.hpp"

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"
#include <QPlainTextEdit> #include <QPlainTextEdit>

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include <QSpinBox> #include <QSpinBox>
#include "switch-generic.hpp" #include "switch-generic.hpp"

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include <QVBoxLayout> #include <QVBoxLayout>
@@ -35,9 +28,11 @@ struct SceneSequenceSwitch : SceneSwitcherEntry {
bool reduce(); bool reduce();
SceneSequenceSwitch *extend(); SceneSequenceSwitch *extend();
bool checkMatch(int &linger, SceneSequenceSwitch *root = nullptr); bool checkMatch(OBSWeakSource currentScene, int &linger,
SceneSequenceSwitch *root = nullptr);
bool checkDurationMatchInterruptible(); bool checkDurationMatchInterruptible();
void prepareUninterruptibleMatch(int &linger); void prepareUninterruptibleMatch(OBSWeakSource currentScene,
int &linger);
void advanceActiveSequence(); void advanceActiveSequence();
void logAdvanceSequence(); void logAdvanceSequence();
void logSequenceCanceled(); void logSequenceCanceled();

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include <QTimeEdit> #include <QTimeEdit>

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include <QSpinBox> #include <QSpinBox>

View File

@@ -1,10 +1,3 @@
/******************************************************************************
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 #pragma once
#include "switch-generic.hpp" #include "switch-generic.hpp"

View File

@@ -67,6 +67,7 @@ struct SwitcherData {
std::mutex m; std::mutex m;
bool transitionActive = false; bool transitionActive = false;
bool waitForTransition = false; bool waitForTransition = false;
std::condition_variable transitionCv;
bool stop = false; bool stop = false;
bool verbose = false; bool verbose = false;
bool disableHints = false; bool disableHints = false;
@@ -77,8 +78,8 @@ struct SwitcherData {
int interval = default_interval; int interval = default_interval;
obs_source_t *waitScene = nullptr; obs_source_t *waitScene = nullptr;
OBSWeakSource currentScene = nullptr;
OBSWeakSource previousScene = nullptr; OBSWeakSource previousScene = nullptr;
OBSWeakSource previousSceneHelper = nullptr;
OBSWeakSource lastRandomScene; OBSWeakSource lastRandomScene;
SceneGroup *lastRandomSceneGroup; SceneGroup *lastRandomSceneGroup;
OBSWeakSource nonMatchingScene; OBSWeakSource nonMatchingScene;
@@ -91,19 +92,15 @@ struct SwitcherData {
std::chrono::high_resolution_clock::time_point lastMatchTime; std::chrono::high_resolution_clock::time_point lastMatchTime;
std::deque<Macro> macros; std::deque<Macro> macros;
std::condition_variable macroWaitCv; // Allow only one macro scene change per scene switcher interval
std::atomic_bool abortMacroWait = {false}; // with the top macro having the highest priority
bool macroSceneSwitched = false; bool macroSceneSwitched = false;
bool replayBufferSaved = false;
std::deque<WindowSwitch> windowSwitches; std::deque<WindowSwitch> windowSwitches;
std::vector<std::string> ignoreIdleWindows; std::vector<std::string> ignoreIdleWindows;
std::string lastTitle; std::string lastTitle;
std::string currentTitle;
std::deque<ScreenRegionSwitch> screenRegionSwitches; std::deque<ScreenRegionSwitch> screenRegionSwitches;
std::pair<int, int> lastCursorPos = {0, 0};
bool cursorPosChanged = false;
std::vector<std::string> ignoreWindowsSwitches; std::vector<std::string> ignoreWindowsSwitches;
@@ -181,9 +178,9 @@ struct SwitcherData {
std::vector<int> tabOrder = std::vector<int>(tab_count); std::vector<int> tabOrder = std::vector<int>(tab_count);
bool hotkeysRegistered = false; bool hotkeysRegistered = false;
obs_hotkey_id startHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id startHotkey = 0;
obs_hotkey_id stopHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id stopHotkey = 0;
obs_hotkey_id toggleHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id toggleHotkey = 0;
bool saveWindowGeo = false; bool saveWindowGeo = false;
QPoint windowPos = {}; QPoint windowPos = {};
@@ -206,7 +203,6 @@ struct SwitcherData {
void writeSceneInfoToFile(); void writeSceneInfoToFile();
void writeToStatusFile(const QString &msg); void writeToStatusFile(const QString &msg);
void setPreconditions();
bool checkForMatch(OBSWeakSource &scene, OBSWeakSource &transition, bool checkForMatch(OBSWeakSource &scene, OBSWeakSource &transition,
int &linger, bool &setPreviousSceneAsMatch, int &linger, bool &setPreviousSceneAsMatch,
bool &macroMatch); bool &macroMatch);

View File

@@ -12,8 +12,6 @@
#include <unordered_map> #include <unordered_map>
#include "scene-group.hpp" #include "scene-group.hpp"
class SceneSelection;
bool WeakSourceValid(obs_weak_source_t *ws); bool WeakSourceValid(obs_weak_source_t *ws);
std::string GetWeakSourceName(obs_weak_source_t *weak_source); std::string GetWeakSourceName(obs_weak_source_t *weak_source);
OBSWeakSource GetWeakSourceByName(const char *name); OBSWeakSource GetWeakSourceByName(const char *name);
@@ -24,14 +22,7 @@ OBSWeakSource GetWeakFilterByName(OBSWeakSource source, const char *name);
OBSWeakSource GetWeakFilterByQString(OBSWeakSource source, const QString &name); OBSWeakSource GetWeakFilterByQString(OBSWeakSource source, const QString &name);
bool compareIgnoringLineEnding(QString &s1, QString &s2); bool compareIgnoringLineEnding(QString &s1, QString &s2);
std::string getSourceSettings(OBSWeakSource ws); 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); 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 * Populate layout with labels and widgets based on provided text
@@ -44,7 +35,6 @@ QString formatJsonString(const char *);
void placeWidgets(std::string text, QBoxLayout *layout, void placeWidgets(std::string text, QBoxLayout *layout,
std::unordered_map<std::string, QWidget *> placeholders, std::unordered_map<std::string, QWidget *> placeholders,
bool addStretch = true); bool addStretch = true);
void deleteLayoutItem(QLayoutItem *item);
void clearLayout(QLayout *layout); void clearLayout(QLayout *layout);
QMetaObject::Connection PulseWidget(QWidget *widget, QColor endColor, QMetaObject::Connection PulseWidget(QWidget *widget, QColor endColor,
QColor = QColor(0, 0, 0, 0), QColor = QColor(0, 0, 0, 0),
@@ -67,14 +57,7 @@ void populateMediaSelection(QComboBox *sel, bool addSelect = true);
void populateProcessSelection(QComboBox *sel, bool addSelect = true); void populateProcessSelection(QComboBox *sel, bool addSelect = true);
void populateSourceSelection(QComboBox *list, bool addSelect = true); void populateSourceSelection(QComboBox *list, bool addSelect = true);
void populateSceneSelection(QComboBox *sel, bool addPrevious = false, void populateSceneSelection(QComboBox *sel, bool addPrevious = false,
bool addCurrent = false, bool addAny = false,
bool addSceneGroup = false, bool addSceneGroup = false,
std::deque<SceneGroup> *sceneGroups = nullptr, std::deque<SceneGroup> *sceneGroups = nullptr,
bool addSelect = true, std::string selectText = "", bool addSelect = true, std::string selectText = "",
bool selectable = false); 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);

View File

@@ -1,8 +1,7 @@
#include "headers/hotkey.hpp"
#include "headers/advanced-scene-switcher.hpp"
#include <obs-module.h> #include <obs-module.h>
#include <fstream> #include <fstream>
#include <regex> #include <regex>
#include "headers/advanced-scene-switcher.hpp"
void startHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey, void startHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
bool pressed) bool pressed)

View File

@@ -1,11 +1,7 @@
#include "../headers/hotkey.hpp"
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/scrnsaver.h> #include <X11/extensions/scrnsaver.h>
#include <X11/extensions/XTest.h>
#undef Bool #undef Bool
#undef CursorShape #undef CursorShape
#undef Expose #undef Expose
@@ -19,19 +15,11 @@
#undef Unsorted #undef Unsorted
#include <util/platform.h> #include <util/platform.h>
#include <vector> #include <vector>
#include <thread>
#include <unordered_map>
#include <QStringList> #include <QStringList>
#include <QRegularExpression> #include <QRegularExpression>
#include <QLibrary>
static Display *xdisplay = 0; 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() Display *disp()
{ {
if (!xdisplay) if (!xdisplay)
@@ -223,7 +211,7 @@ void GetCurrentWindowTitle(std::string &title)
int status = 0; int status = 0;
XTextProperty text; XTextProperty text;
if (xstatus == Success && data[0]) { if (xstatus == Success) {
status = XGetTextProperty(disp(), data[0], &text, status = XGetTextProperty(disp(), data[0], &text,
XInternAtom(disp(), "_NET_WM_NAME", XInternAtom(disp(), "_NET_WM_NAME",
true)); true));
@@ -254,13 +242,14 @@ std::pair<int, int> getCursorPos()
int win_y; int win_y;
unsigned int mask; unsigned int mask;
dpy = disp(); dpy = XOpenDisplay(NULL);
root = XDefaultRootWindow(dpy); root = XDefaultRootWindow(dpy);
if (XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y, if (XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y,
&win_x, &win_y, &mask)) { &win_x, &win_y, &mask)) {
pos = std::pair<int, int>(root_x, root_y); pos = std::pair<int, int>(root_x, root_y);
} }
XCloseDisplay(dpy);
return pos; return pos;
} }
@@ -393,186 +382,78 @@ int secondsSinceLastInput()
mit_info = XScreenSaverAllocInfo(); mit_info = XScreenSaverAllocInfo();
if ((display = disp()) == NULL) { if ((display = XOpenDisplay(NULL)) == NULL) {
return -1; return (-1);
} }
screen = DefaultScreen(display); screen = DefaultScreen(display);
XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info); XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info);
idle_time = (mit_info->idle) / 1000; idle_time = (mit_info->idle) / 1000;
XFree(mit_info); XFree(mit_info);
XCloseDisplay(display);
return idle_time; return idle_time;
} }
static std::unordered_map<HotkeyType, long> keyTable = { bool GetCurrentVirtualDesktop(long &desktop)
// 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)
{ {
if (!canSimulateKeyPresses) { Atom type;
return; long unsigned nitems;
} long unsigned int bytes = 0;
int format = 0;
unsigned char *data;
Window root;
Atom request;
Display *display = disp(); Display *display = disp();
if (display == NULL)
return;
// Press keys //TODO check for _NET_CURRENT_DESKTOP
for (auto &key : keys) { if (!ewmhIsSupported()) {
auto it = keyTable.find(key); return false;
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);
} }
XFlush(display); 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;
} }
void PlatformInit() bool GetVirtualDesktopCount(long &ndesktops)
{ {
libXtstHandle = new QLibrary("libXtst.so", nullptr); Atom type;
pressFunc = (keyPressFunc)libXtstHandle->resolve("XTestFakeKeyEvent"); long unsigned nitems;
int _; long unsigned int bytes = 0;
canSimulateKeyPresses = pressFunc && int format = 0;
!XQueryExtension(disp(), "XTEST", &_, &_, &_); unsigned char *data;
} Window root;
Atom request;
Display *display = disp();
void PlatformCleanup() //TODO check for _NET_NUMBER_OF_DESKTOPS
{ if (!ewmhIsSupported()) {
delete libXtstHandle; return false;
libXtstHandle = nullptr; }
cleanupDisplay(); 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;
} }

View File

@@ -75,14 +75,6 @@ bool MacroActionAudio::Load(obs_data_t *obj)
return true; return true;
} }
std::string MacroActionAudio::GetShortDesc()
{
if (_audioSource) {
return GetWeakSourceName(_audioSource);
}
return "";
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (auto entry : actionTypes) {
@@ -175,8 +167,6 @@ void MacroActionAudioEdit::SourceChanged(const QString &text)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_audioSource = GetWeakSourceByQString(text); _entryData->_audioSource = GetWeakSourceByQString(text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
} }
void MacroActionAudioEdit::ActionChanged(int value) void MacroActionAudioEdit::ActionChanged(int value)

View File

@@ -1,9 +1,7 @@
#include "headers/advanced-scene-switcher.hpp"
#include "headers/macro-action-edit.hpp" #include "headers/macro-action-edit.hpp"
#include "headers/macro-action-scene-switch.hpp" #include "headers/macro-action-scene-switch.hpp"
#include "headers/section.hpp"
#include "headers/macro-controls.hpp"
#include "headers/utility.hpp" #include "headers/utility.hpp"
#include "headers/advanced-scene-switcher.hpp"
std::map<std::string, MacroActionInfo> MacroActionFactory::_methods; std::map<std::string, MacroActionInfo> MacroActionFactory::_methods;
@@ -61,10 +59,11 @@ static inline void populateActionSelection(QComboBox *list)
MacroActionEdit::MacroActionEdit(QWidget *parent, MacroActionEdit::MacroActionEdit(QWidget *parent,
std::shared_ptr<MacroAction> *entryData, std::shared_ptr<MacroAction> *entryData,
const std::string &id) const std::string &id, bool startCollapsed)
: MacroSegmentEdit(parent), _entryData(entryData) : QWidget(parent)
{ {
_actionSelection = new QComboBox(); _actionSelection = new QComboBox();
_section = new Section(300);
QWidget::connect(_actionSelection, QWidget::connect(_actionSelection,
SIGNAL(currentTextChanged(const QString &)), this, SIGNAL(currentTextChanged(const QString &)), this,
@@ -73,15 +72,13 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
populateActionSelection(_actionSelection); populateActionSelection(_actionSelection);
_section->AddHeaderWidget(_actionSelection); _section->AddHeaderWidget(_actionSelection);
_section->AddHeaderWidget(_headerInfo);
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(_section); mainLayout->addWidget(_section);
mainLayout->addWidget(_controls);
setLayout(mainLayout); setLayout(mainLayout);
_entryData = entryData; _entryData = entryData;
UpdateEntryData(id); UpdateEntryData(id, startCollapsed);
_loading = false; _loading = false;
} }
@@ -93,61 +90,22 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
} }
std::string id = MacroActionFactory::GetIdByName(text); std::string id = MacroActionFactory::GetIdByName(text);
HeaderInfoChanged("");
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->reset(); _entryData->reset();
*_entryData = MacroActionFactory::Create(id); *_entryData = MacroActionFactory::Create(id);
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData); auto widget =
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)), MacroActionFactory::CreateWidget(id, window(), *_entryData);
this, SLOT(HeaderInfoChanged(const QString &)));
_section->SetContent(widget, false); _section->SetContent(widget, false);
SetFocusPolicyOfWidgets();
} }
void MacroActionEdit::UpdateEntryData(const std::string &id) void MacroActionEdit::UpdateEntryData(const std::string &id, bool collapse)
{ {
_actionSelection->setCurrentText( _actionSelection->setCurrentText(
obs_module_text(MacroActionFactory::GetActionName(id).c_str())); obs_module_text(MacroActionFactory::GetActionName(id).c_str()));
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData); auto widget =
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)), MacroActionFactory::CreateWidget(id, window(), *_entryData);
this, SLOT(HeaderInfoChanged(const QString &))); _section->SetContent(widget, collapse);
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() void AdvSceneSwitcher::on_actionAdd_clicked()
@@ -157,33 +115,15 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
return; return;
} }
AddMacroAction((int)macro->Actions().size()); MacroActionSwitchScene temp;
ui->macroEditActionHelp->setVisible(false); std::string id = temp.GetId();
}
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); std::lock_guard<std::mutex> lock(switcher->m);
macro->Actions().erase(macro->Actions().begin() + idx); macro->Actions().emplace_back(MacroActionFactory::Create(id));
switcher->abortMacroWait = true; auto newEntry =
switcher->macroWaitCv.notify_one(); new MacroActionEdit(this, &macro->Actions().back(), id, false);
macro->UpdateActionIndices(); ui->macroEditActionLayout->addWidget(newEntry);
ui->macroEditActionHelp->setVisible(false);
// 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() void AdvSceneSwitcher::on_actionRemove_clicked()
@@ -192,61 +132,24 @@ void AdvSceneSwitcher::on_actionRemove_clicked()
if (!macro) { if (!macro) {
return; return;
} }
RemoveMacroAction((int)macro->Actions().size() - 1);
}
void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
{
if (pos1 == pos2) {
return;
}
if (pos1 > pos2) {
std::swap(pos1, pos2);
}
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(m->Actions().begin() + pos1, m->Actions().begin() + pos2); if (macro->Actions().empty()) {
m->UpdateActionIndices(); return;
}
macro->Actions().pop_back();
auto a1 = m->Actions().begin() + pos1; int count = ui->macroEditActionLayout->count();
auto a2 = m->Actions().begin() + pos2; auto item = ui->macroEditActionLayout->takeAt(count - 1);
auto item1 = ui->macroEditActionLayout->takeAt(pos1); if (item) {
auto item2 = ui->macroEditActionLayout->takeAt(pos2 - 1); auto widget = item->widget();
deleteLayoutItem(item1); if (widget) {
deleteLayoutItem(item2); widget->setVisible(false);
auto widget1 = new MacroActionEdit(this, &(*a1), (*a1)->GetId()); }
auto widget2 = new MacroActionEdit(this, &(*a2), (*a2)->GetId()); delete item;
ConnectControlSignals(widget1); }
ConnectControlSignals(widget2);
ui->macroEditActionLayout->insertWidget(pos1, widget1); if (count == 1) {
ui->macroEditActionLayout->insertWidget(pos2, widget2); ui->macroEditActionHelp->setVisible(true);
} }
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);
} }

View File

@@ -1,187 +0,0 @@
#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);
}

View File

@@ -12,8 +12,6 @@ bool MacroActionFilter::_registered = MacroActionFactory::Register(
const static std::map<FilterAction, std::string> actionTypes = { const static std::map<FilterAction, std::string> actionTypes = {
{FilterAction::ENABLE, "AdvSceneSwitcher.action.filter.type.enable"}, {FilterAction::ENABLE, "AdvSceneSwitcher.action.filter.type.enable"},
{FilterAction::DISABLE, "AdvSceneSwitcher.action.filter.type.disable"}, {FilterAction::DISABLE, "AdvSceneSwitcher.action.filter.type.disable"},
{FilterAction::SETTINGS,
"AdvSceneSwitcher.action.filter.type.settings"},
}; };
bool MacroActionFilter::PerformAction() bool MacroActionFilter::PerformAction()
@@ -26,9 +24,6 @@ bool MacroActionFilter::PerformAction()
case FilterAction::DISABLE: case FilterAction::DISABLE:
obs_source_set_enabled(s, false); obs_source_set_enabled(s, false);
break; break;
case FilterAction::SETTINGS:
setSourceSettings(s, _settings);
break;
default: default:
break; break;
} }
@@ -56,7 +51,6 @@ bool MacroActionFilter::Save(obs_data_t *obj)
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str()); obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
obs_data_set_string(obj, "filter", GetWeakSourceName(_filter).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_int(obj, "action", static_cast<int>(_action));
obs_data_set_string(obj, "settings", _settings.c_str());
return true; return true;
} }
@@ -68,19 +62,9 @@ bool MacroActionFilter::Load(obs_data_t *obj)
const char *filterName = obs_data_get_string(obj, "filter"); const char *filterName = obs_data_get_string(obj, "filter");
_filter = GetWeakFilterByQString(_source, filterName); _filter = GetWeakFilterByQString(_source, filterName);
_action = static_cast<FilterAction>(obs_data_get_int(obj, "action")); _action = static_cast<FilterAction>(obs_data_get_int(obj, "action"));
_settings = obs_data_get_string(obj, "settings");
return true; return true;
} }
std::string MacroActionFilter::GetShortDesc()
{
if (_filter && _source) {
return GetWeakSourceName(_source) + " - " +
GetWeakSourceName(_filter);
}
return "";
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (auto entry : actionTypes) {
@@ -88,6 +72,56 @@ 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( MacroActionFilterEdit::MacroActionFilterEdit(
QWidget *parent, std::shared_ptr<MacroActionFilter> entryData) QWidget *parent, std::shared_ptr<MacroActionFilter> entryData)
: QWidget(parent) : QWidget(parent)
@@ -95,12 +129,9 @@ MacroActionFilterEdit::MacroActionFilterEdit(
_sources = new QComboBox(); _sources = new QComboBox();
_filters = new QComboBox(); _filters = new QComboBox();
_actions = new QComboBox(); _actions = new QComboBox();
_getSettings = new QPushButton(
obs_module_text("AdvSceneSwitcher.action.filter.getSettings"));
_settings = new QPlainTextEdit();
populateActionSelection(_actions); populateActionSelection(_actions);
populateSourcesWithFilterSelection(_sources); populateSourcesWithFilter(_sources);
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int))); SLOT(ActionChanged(int)));
@@ -108,29 +139,15 @@ MacroActionFilterEdit::MacroActionFilterEdit(
this, SLOT(SourceChanged(const QString &))); this, SLOT(SourceChanged(const QString &)));
QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)), QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(FilterChanged(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 = { std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{sources}}", _sources}, {"{{filters}}", _filters}, {"{{sources}}", _sources},
{"{{actions}}", _actions}, {"{{settings}}", _settings}, {"{{filters}}", _filters},
{"{{getSettings}}", _getSettings}, {"{{actions}}", _actions},
}; };
placeWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"),
entryLayout, widgetPlaceholders); mainLayout, 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); setLayout(mainLayout);
_entryData = entryData; _entryData = entryData;
@@ -147,11 +164,9 @@ void MacroActionFilterEdit::UpdateEntryData()
_actions->setCurrentIndex(static_cast<int>(_entryData->_action)); _actions->setCurrentIndex(static_cast<int>(_entryData->_action));
_sources->setCurrentText( _sources->setCurrentText(
GetWeakSourceName(_entryData->_source).c_str()); GetWeakSourceName(_entryData->_source).c_str());
populateFilterSelection(_filters, _entryData->_source); populateFilters(_filters, _entryData->_source);
_filters->setCurrentText( _filters->setCurrentText(
GetWeakSourceName(_entryData->_filter).c_str()); GetWeakSourceName(_entryData->_filter).c_str());
_settings->setPlainText(QString::fromStdString(_entryData->_settings));
SetWidgetVisibility(_entryData->_action == FilterAction::SETTINGS);
} }
void MacroActionFilterEdit::SourceChanged(const QString &text) void MacroActionFilterEdit::SourceChanged(const QString &text)
@@ -164,7 +179,7 @@ void MacroActionFilterEdit::SourceChanged(const QString &text)
_entryData->_source = GetWeakSourceByQString(text); _entryData->_source = GetWeakSourceByQString(text);
} }
_filters->clear(); _filters->clear();
populateFilterSelection(_filters, _entryData->_source); populateFilters(_filters, _entryData->_source);
} }
void MacroActionFilterEdit::FilterChanged(const QString &text) void MacroActionFilterEdit::FilterChanged(const QString &text)
@@ -175,8 +190,6 @@ void MacroActionFilterEdit::FilterChanged(const QString &text)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_filter = GetWeakFilterByQString(_entryData->_source, text); _entryData->_filter = GetWeakFilterByQString(_entryData->_source, text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
} }
void MacroActionFilterEdit::ActionChanged(int value) void MacroActionFilterEdit::ActionChanged(int value)
@@ -187,33 +200,4 @@ void MacroActionFilterEdit::ActionChanged(int value)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_action = static_cast<FilterAction>(value); _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();
} }

View File

@@ -1,377 +0,0 @@
#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);
}

View File

@@ -77,14 +77,6 @@ bool MacroActionMacro::Load(obs_data_t *obj)
return true; return true;
} }
std::string MacroActionMacro::GetShortDesc()
{
if (_macro.get()) {
return _macro->Name();
}
return "";
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (auto entry : actionTypes) {
@@ -139,8 +131,6 @@ void MacroActionMacroEdit::MacroChanged(const QString &text)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_macro.UpdateRef(text); _entryData->_macro.UpdateRef(text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
} }
void MacroActionMacroEdit::ActionChanged(int value) void MacroActionMacroEdit::ActionChanged(int value)

View File

@@ -84,14 +84,6 @@ bool MacroActionMedia::Load(obs_data_t *obj)
return true; return true;
} }
std::string MacroActionMedia::GetShortDesc()
{
if (_mediaSource) {
return GetWeakSourceName(_mediaSource);
}
return "";
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (auto entry : actionTypes) {
@@ -148,8 +140,6 @@ void MacroActionMediaEdit::SourceChanged(const QString &text)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_mediaSource = GetWeakSourceByQString(text); _entryData->_mediaSource = GetWeakSourceByQString(text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
} }
void MacroActionMediaEdit::ActionChanged(int value) void MacroActionMediaEdit::ActionChanged(int value)

View File

@@ -14,17 +14,6 @@ bool MacroActionPluginState::_registered = MacroActionFactory::Register(
const static std::map<PluginStateAction, std::string> actionTypes = { const static std::map<PluginStateAction, std::string> actionTypes = {
{PluginStateAction::STOP, {PluginStateAction::STOP,
"AdvSceneSwitcher.action.pluginState.type.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() void stopPlugin()
@@ -33,23 +22,12 @@ void stopPlugin()
t.detach(); t.detach();
} }
void setNoMatchBehaviour(int value, OBSWeakSource &scene)
{
switcher->switchIfNotMatching = static_cast<NoMatch>(value);
if (switcher->switchIfNotMatching == SWITCH) {
switcher->nonMatchingScene = scene;
}
}
bool MacroActionPluginState::PerformAction() bool MacroActionPluginState::PerformAction()
{ {
switch (_action) { switch (_action) {
case PluginStateAction::STOP: case PluginStateAction::STOP:
stopPlugin(); stopPlugin();
break; break;
case PluginStateAction::NO_MATCH_BEHAVIOUR:
setNoMatchBehaviour(_value, _scene);
break;
default: default:
break; break;
} }
@@ -58,9 +36,10 @@ bool MacroActionPluginState::PerformAction()
void MacroActionPluginState::LogAction() void MacroActionPluginState::LogAction()
{ {
auto it = actionTypes.find(_action);
switch (_action) { switch (_action) {
case PluginStateAction::STOP: case PluginStateAction::STOP:
blog(LOG_INFO, "stop() called by macro"); blog(LOG_INFO, "stop() called by macro", it->second.c_str());
break; break;
default: default:
blog(LOG_WARNING, "ignored unknown pluginState action %d", blog(LOG_WARNING, "ignored unknown pluginState action %d",
@@ -73,8 +52,6 @@ bool MacroActionPluginState::Save(obs_data_t *obj)
{ {
MacroAction::Save(obj); MacroAction::Save(obj);
obs_data_set_int(obj, "action", static_cast<int>(_action)); 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; return true;
} }
@@ -83,9 +60,6 @@ bool MacroActionPluginState::Load(obs_data_t *obj)
MacroAction::Load(obj); MacroAction::Load(obj);
_action = _action =
static_cast<PluginStateAction>(obs_data_get_int(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; return true;
} }
@@ -96,39 +70,20 @@ 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( MacroActionPluginStateEdit::MacroActionPluginStateEdit(
QWidget *parent, std::shared_ptr<MacroActionPluginState> entryData) QWidget *parent, std::shared_ptr<MacroActionPluginState> entryData)
: QWidget(parent) : QWidget(parent)
{ {
_actions = new QComboBox(); _actions = new QComboBox();
_values = new QComboBox();
_scenes = new QComboBox();
populateActionSelection(_actions); populateActionSelection(_actions);
populateSceneSelection(_scenes);
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int))); 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; QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = { std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{actions}}", _actions}, {"{{actions}}", _actions},
{"{{values}}", _values},
{"{{scenes}}", _scenes},
}; };
placeWidgets( placeWidgets(
obs_module_text("AdvSceneSwitcher.action.pluginState.entry"), obs_module_text("AdvSceneSwitcher.action.pluginState.entry"),
@@ -146,10 +101,6 @@ void MacroActionPluginStateEdit::UpdateEntryData()
return; return;
} }
_actions->setCurrentIndex(static_cast<int>(_entryData->_action)); _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) void MacroActionPluginStateEdit::ActionChanged(int value)
@@ -158,46 +109,6 @@ void MacroActionPluginStateEdit::ActionChanged(int value)
return; return;
} }
{
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); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_value = value; _entryData->_action = static_cast<PluginStateAction>(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();
}
}
} }

View File

@@ -1,6 +1,5 @@
#include "headers/macro-action-run.hpp" #include "headers/macro-action-run.hpp"
#include "headers/advanced-scene-switcher.hpp" #include "headers/advanced-scene-switcher.hpp"
#include "headers/name-dialog.hpp"
#include "headers/utility.hpp" #include "headers/utility.hpp"
#include <QProcess> #include <QProcess>
@@ -14,7 +13,7 @@ bool MacroActionRun::_registered = MacroActionFactory::Register(
bool MacroActionRun::PerformAction() bool MacroActionRun::PerformAction()
{ {
QProcess::startDetached(QString::fromStdString(_path), _args); QProcess::startDetached(QString::fromStdString(_path), QStringList());
return true; return true;
} }
@@ -27,16 +26,6 @@ bool MacroActionRun::Save(obs_data_t *obj)
{ {
MacroAction::Save(obj); MacroAction::Save(obj);
obs_data_set_string(obj, "path", _path.c_str()); 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; return true;
} }
@@ -44,23 +33,9 @@ bool MacroActionRun::Load(obs_data_t *obj)
{ {
MacroAction::Load(obj); MacroAction::Load(obj);
_path = obs_data_get_string(obj, "path"); _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; return true;
} }
std::string MacroActionRun::GetShortDesc()
{
return _path;
}
MacroActionRunEdit::MacroActionRunEdit( MacroActionRunEdit::MacroActionRunEdit(
QWidget *parent, std::shared_ptr<MacroActionRun> entryData) QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
: QWidget(parent) : QWidget(parent)
@@ -68,63 +43,20 @@ MacroActionRunEdit::MacroActionRunEdit(
_filePath = new QLineEdit(); _filePath = new QLineEdit();
_browseButton = _browseButton =
new QPushButton(obs_module_text("AdvSceneSwitcher.browse")); new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
_argList = new QListWidget(); _browseButton->setStyleSheet("border:1px solid gray;");
_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, QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
SLOT(FilePathChanged())); SLOT(FilePathChanged()));
QWidget::connect(_browseButton, SIGNAL(clicked()), this, QWidget::connect(_browseButton, SIGNAL(clicked()), this,
SLOT(BrowseButtonClicked())); 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()));
auto *entryLayout = new QHBoxLayout; QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = { std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{filePath}}", _filePath}, {"{{filePath}}", _filePath},
{"{{browseButton}}", _browseButton}, {"{{browseButton}}", _browseButton},
}; };
placeWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry"), placeWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry"),
entryLayout, widgetPlaceholders); mainLayout, 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); setLayout(mainLayout);
_entryData = entryData; _entryData = entryData;
@@ -138,10 +70,6 @@ void MacroActionRunEdit::UpdateEntryData()
return; return;
} }
_filePath->setText(QString::fromStdString(_entryData->_path)); _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() void MacroActionRunEdit::FilePathChanged()
@@ -152,8 +80,6 @@ void MacroActionRunEdit::FilePathChanged()
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_path = _filePath->text().toUtf8().constData(); _entryData->_path = _filePath->text().toUtf8().constData();
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
} }
void MacroActionRunEdit::BrowseButtonClicked() void MacroActionRunEdit::BrowseButtonClicked()
@@ -170,77 +96,3 @@ void MacroActionRunEdit::BrowseButtonClicked()
_filePath->setText(path); _filePath->setText(path);
FilePathChanged(); 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);
}
}

View File

@@ -1,208 +0,0 @@
#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;
}

View File

@@ -39,17 +39,6 @@ bool MacroActionSwitchScene::Load(obs_data_t *obj)
return true; 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( MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
QWidget *parent, std::shared_ptr<MacroActionSwitchScene> entryData) QWidget *parent, std::shared_ptr<MacroActionSwitchScene> entryData)
: SwitchWidget(parent, entryData.get(), true, true) : SwitchWidget(parent, entryData.get(), true, true)
@@ -57,8 +46,6 @@ MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
_duration = new DurationSelection(parent, false); _duration = new DurationSelection(parent, false);
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this, QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
SLOT(DurationChanged(double))); SLOT(DurationChanged(double)));
QWidget::connect(scenes, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(ChangeHeaderInfo(const QString &)));
QHBoxLayout *mainLayout = new QHBoxLayout; QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = { std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
@@ -84,9 +71,3 @@ void MacroActionSwitchSceneEdit::DurationChanged(double seconds)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_duration.seconds = seconds; _entryData->_duration.seconds = seconds;
} }
void MacroActionSwitchSceneEdit::ChangeHeaderInfo(const QString &)
{
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
}

View File

@@ -1,271 +0,0 @@
#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);
}

View File

@@ -40,7 +40,7 @@ static bool visibilityEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
bool MacroActionSceneVisibility::PerformAction() bool MacroActionSceneVisibility::PerformAction()
{ {
auto s = obs_weak_source_get_source(_scene.GetScene()); auto s = obs_weak_source_get_source(_scene);
auto scene = obs_scene_from_source(s); auto scene = obs_scene_from_source(s);
auto sourceName = GetWeakSourceName(_source); auto sourceName = GetWeakSourceName(_source);
VisInfo vInfo = {sourceName, _action == SceneVisibilityAction::SHOW}; VisInfo vInfo = {sourceName, _action == SceneVisibilityAction::SHOW};
@@ -64,9 +64,9 @@ void MacroActionSceneVisibility::LogAction()
auto it = actionTypes.find(_action); auto it = actionTypes.find(_action);
if (it != actionTypes.end()) { if (it != actionTypes.end()) {
vblog(LOG_INFO, vblog(LOG_INFO,
"performed visibility action \"%s\" for source \"%s\" on scene \"%s\"", "performed action \"%s\" for source \"%s\" on scene \"%s\"",
it->second.c_str(), GetWeakSourceName(_source).c_str(), it->second.c_str(), GetWeakSourceName(_scene).c_str(),
_scene.ToString().c_str()); GetWeakSourceName(_scene).c_str());
} else { } else {
blog(LOG_WARNING, "ignored unknown SceneVisibility action %d", blog(LOG_WARNING, "ignored unknown SceneVisibility action %d",
static_cast<int>(_action)); static_cast<int>(_action));
@@ -76,7 +76,7 @@ void MacroActionSceneVisibility::LogAction()
bool MacroActionSceneVisibility::Save(obs_data_t *obj) bool MacroActionSceneVisibility::Save(obs_data_t *obj)
{ {
MacroAction::Save(obj); MacroAction::Save(obj);
_scene.Save(obj); obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str()); 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, "action", static_cast<int>(_action));
return true; return true;
@@ -85,7 +85,8 @@ bool MacroActionSceneVisibility::Save(obs_data_t *obj)
bool MacroActionSceneVisibility::Load(obs_data_t *obj) bool MacroActionSceneVisibility::Load(obs_data_t *obj)
{ {
MacroAction::Load(obj); MacroAction::Load(obj);
_scene.Load(obj); const char *sceneName = obs_data_get_string(obj, "scene");
_scene = GetWeakSourceByName(sceneName);
const char *sourceName = obs_data_get_string(obj, "source"); const char *sourceName = obs_data_get_string(obj, "source");
_source = GetWeakSourceByName(sourceName); _source = GetWeakSourceByName(sourceName);
_action = static_cast<SceneVisibilityAction>( _action = static_cast<SceneVisibilityAction>(
@@ -93,14 +94,6 @@ bool MacroActionSceneVisibility::Load(obs_data_t *obj)
return true; return true;
} }
std::string MacroActionSceneVisibility::GetShortDesc()
{
if (_source) {
return _scene.ToString() + " - " + GetWeakSourceName(_source);
}
return "";
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (auto entry : actionTypes) {
@@ -108,20 +101,51 @@ 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( MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit(
QWidget *parent, std::shared_ptr<MacroActionSceneVisibility> entryData) QWidget *parent, std::shared_ptr<MacroActionSceneVisibility> entryData)
: QWidget(parent) : QWidget(parent)
{ {
_scenes = new SceneSelectionWidget(window(), false, false, true); _scenes = new QComboBox();
_sources = new QComboBox(); _sources = new QComboBox();
_actions = new QComboBox(); _actions = new QComboBox();
populateActionSelection(_actions); populateActionSelection(_actions);
populateSceneSelection(_scenes);
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int))); SLOT(ActionChanged(int)));
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), QWidget::connect(_scenes, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(SceneChanged(const SceneSelection &))); this, SLOT(SceneChanged(const QString &)));
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)), QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(SourceChanged(const QString &))); this, SLOT(SourceChanged(const QString &)));
@@ -148,23 +172,23 @@ void MacroActionSceneVisibilityEdit::UpdateEntryData()
} }
_actions->setCurrentIndex(static_cast<int>(_entryData->_action)); _actions->setCurrentIndex(static_cast<int>(_entryData->_action));
_scenes->SetScene(_entryData->_scene); _scenes->setCurrentText(GetWeakSourceName(_entryData->_scene).c_str());
populateSceneItemSelection(_sources, _entryData->_scene); populateSceneItems(_sources, _entryData->_scene);
_sources->setCurrentText( _sources->setCurrentText(
GetWeakSourceName(_entryData->_source).c_str()); GetWeakSourceName(_entryData->_source).c_str());
} }
void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s) void MacroActionSceneVisibilityEdit::SceneChanged(const QString &text)
{ {
if (_loading || !_entryData) { if (_loading || !_entryData) {
return; return;
} }
{ {
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_scene = s; _entryData->_scene = GetWeakSourceByQString(text);
} }
_sources->clear(); _sources->clear();
populateSceneItemSelection(_sources, _entryData->_scene); populateSceneItems(_sources, _entryData->_scene);
} }
void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text) void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text)
@@ -175,8 +199,6 @@ void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_source = GetWeakSourceByQString(text); _entryData->_source = GetWeakSourceByQString(text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
} }
void MacroActionSceneVisibilityEdit::ActionChanged(int value) void MacroActionSceneVisibilityEdit::ActionChanged(int value)

View File

@@ -16,6 +16,22 @@ const static std::map<SourceAction, std::string> actionTypes = {
"AdvSceneSwitcher.action.source.type.settings"}, "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() bool MacroActionSource::PerformAction()
{ {
auto s = obs_weak_source_get_source(_source); auto s = obs_weak_source_get_source(_source);
@@ -67,14 +83,6 @@ bool MacroActionSource::Load(obs_data_t *obj)
return true; return true;
} }
std::string MacroActionSource::GetShortDesc()
{
if (_source) {
return GetWeakSourceName(_source);
}
return "";
}
static inline void populateActionSelection(QComboBox *list) static inline void populateActionSelection(QComboBox *list)
{ {
for (auto entry : actionTypes) { for (auto entry : actionTypes) {
@@ -151,8 +159,6 @@ void MacroActionSourceEdit::SourceChanged(const QString &text)
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_source = GetWeakSourceByQString(text); _entryData->_source = GetWeakSourceByQString(text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
} }
void MacroActionSourceEdit::ActionChanged(int value) void MacroActionSourceEdit::ActionChanged(int value)
@@ -173,7 +179,7 @@ void MacroActionSourceEdit::GetSettingsClicked()
} }
_settings->setPlainText( _settings->setPlainText(
formatJsonString(getSourceSettings(_entryData->_source))); QString::fromStdString(getSourceSettings(_entryData->_source)));
} }
void MacroActionSourceEdit::SettingsChanged() void MacroActionSourceEdit::SettingsChanged()

View File

@@ -1,109 +0,0 @@
#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);
}

View File

@@ -38,12 +38,9 @@ bool MacroActionWait::PerformAction()
sleep_duration); sleep_duration);
std::unique_lock<std::mutex> lock(switcher->m); std::unique_lock<std::mutex> lock(switcher->m);
switcher->abortMacroWait = false; switcher->cv.wait_for(lock, std::chrono::milliseconds((
switcher->macroWaitCv.wait_for( long long)(sleep_duration * 1000)));
lock, return !switcher->stop;
std::chrono::milliseconds((long long)(sleep_duration * 1000)),
[] { return switcher->abortMacroWait.load(); });
return !switcher->abortMacroWait;
} }
bool MacroActionWait::Save(obs_data_t *obj) bool MacroActionWait::Save(obs_data_t *obj)

View File

@@ -77,14 +77,6 @@ bool MacroConditionAudio::Load(obs_data_t *obj)
return true; return true;
} }
std::string MacroConditionAudio::GetShortDesc()
{
if (_audioSource) {
return GetWeakSourceName(_audioSource);
}
return "";
}
void MacroConditionAudio::SetVolumeLevel( void MacroConditionAudio::SetVolumeLevel(
void *data, const float magnitude[MAX_AUDIO_CHANNELS], void *data, const float magnitude[MAX_AUDIO_CHANNELS],
const float peak[MAX_AUDIO_CHANNELS], const float peak[MAX_AUDIO_CHANNELS],
@@ -189,8 +181,6 @@ void MacroConditionAudioEdit::SourceChanged(const QString &text)
_entryData->_audioSource = GetWeakSourceByQString(text); _entryData->_audioSource = GetWeakSourceByQString(text);
_entryData->ResetVolmeter(); _entryData->ResetVolmeter();
UpdateVolmeterSource(); UpdateVolmeterSource();
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
} }
void MacroConditionAudioEdit::VolumeThresholdChanged(int vol) void MacroConditionAudioEdit::VolumeThresholdChanged(int vol)

View File

@@ -0,0 +1,194 @@
#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);
}

View File

@@ -1,261 +0,0 @@
#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);
}

View File

@@ -1,279 +0,0 @@
#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();
}

View File

@@ -1,9 +1,5 @@
#include "headers/advanced-scene-switcher.hpp"
#include "headers/macro-condition-edit.hpp" #include "headers/macro-condition-edit.hpp"
#include "headers/macro-condition-scene.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; std::map<std::string, MacroConditionInfo> MacroConditionFactory::_methods;
@@ -91,11 +87,12 @@ static inline void populateConditionSelection(QComboBox *list)
MacroConditionEdit::MacroConditionEdit( MacroConditionEdit::MacroConditionEdit(
QWidget *parent, std::shared_ptr<MacroCondition> *entryData, QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
const std::string &id, bool root) const std::string &id, bool root, bool startCollapsed)
: MacroSegmentEdit(parent), _entryData(entryData), _isRoot(root) : QWidget(parent)
{ {
_logicSelection = new QComboBox(); _logicSelection = new QComboBox();
_conditionSelection = new QComboBox(); _conditionSelection = new QComboBox();
_section = new Section(300);
_dur = new DurationConstraintEdit(); _dur = new DurationConstraintEdit();
QWidget::connect(_logicSelection, SIGNAL(currentIndexChanged(int)), QWidget::connect(_logicSelection, SIGNAL(currentIndexChanged(int)),
@@ -116,15 +113,15 @@ MacroConditionEdit::MacroConditionEdit(
_section->AddHeaderWidget(_logicSelection); _section->AddHeaderWidget(_logicSelection);
_section->AddHeaderWidget(_conditionSelection); _section->AddHeaderWidget(_conditionSelection);
_section->AddHeaderWidget(_headerInfo);
_section->AddHeaderWidget(_dur); _section->AddHeaderWidget(_dur);
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(_section); mainLayout->addWidget(_section);
mainLayout->addWidget(_controls);
setLayout(mainLayout); setLayout(mainLayout);
UpdateEntryData(id); _entryData = entryData;
_isRoot = root;
UpdateEntryData(id, startCollapsed);
_loading = false; _loading = false;
} }
@@ -150,23 +147,12 @@ bool MacroConditionEdit::IsRootNode()
return _isRoot; return _isRoot;
} }
void MacroConditionEdit::SetRootNode(bool root) void MacroConditionEdit::UpdateEntryData(const std::string &id, bool collapse)
{
const QSignalBlocker blocker(_logicSelection);
_logicSelection->clear();
populateLogicSelection(_logicSelection, root);
}
void MacroConditionEdit::UpdateEntryData(const std::string &id)
{ {
_conditionSelection->setCurrentText(obs_module_text( _conditionSelection->setCurrentText(obs_module_text(
MacroConditionFactory::GetConditionName(id).c_str())); MacroConditionFactory::GetConditionName(id).c_str()));
auto widget = auto widget =
MacroConditionFactory::CreateWidget(id, this, *_entryData); MacroConditionFactory::CreateWidget(id, window(), *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
HeaderInfoChanged(
QString::fromStdString((*_entryData)->GetShortDesc()));
auto logic = (*_entryData)->GetLogicType(); auto logic = (*_entryData)->GetLogicType();
if (IsRootNode()) { if (IsRootNode()) {
_logicSelection->setCurrentIndex(static_cast<int>(logic)); _logicSelection->setCurrentIndex(static_cast<int>(logic));
@@ -174,12 +160,11 @@ void MacroConditionEdit::UpdateEntryData(const std::string &id)
_logicSelection->setCurrentIndex(static_cast<int>(logic) - _logicSelection->setCurrentIndex(static_cast<int>(logic) -
logic_root_offset); logic_root_offset);
} }
_section->SetContent(widget, (*_entryData)->GetCollapsed()); _section->SetContent(widget, collapse);
_dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id)); _dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id));
auto constraint = (*_entryData)->GetDurationConstraint(); auto constraint = (*_entryData)->GetDurationConstraint();
_dur->SetValue(constraint); _dur->SetValue(constraint);
SetFocusPolicyOfWidgets();
} }
void MacroConditionEdit::ConditionSelectionChanged(const QString &text) void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
@@ -192,7 +177,6 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
auto temp = DurationConstraint(); auto temp = DurationConstraint();
_dur->SetValue(temp); _dur->SetValue(temp);
HeaderInfoChanged("");
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
auto logic = (*_entryData)->GetLogicType(); auto logic = (*_entryData)->GetLogicType();
@@ -200,12 +184,9 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
*_entryData = MacroConditionFactory::Create(id); *_entryData = MacroConditionFactory::Create(id);
(*_entryData)->SetLogicType(logic); (*_entryData)->SetLogicType(logic);
auto widget = auto widget =
MacroConditionFactory::CreateWidget(id, this, *_entryData); MacroConditionFactory::CreateWidget(id, window(), *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
_section->SetContent(widget, false); _section->SetContent(widget, false);
_dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id)); _dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id));
SetFocusPolicyOfWidgets();
} }
void MacroConditionEdit::DurationChanged(double seconds) void MacroConditionEdit::DurationChanged(double seconds)
@@ -238,83 +219,24 @@ void MacroConditionEdit::DurationUnitChanged(DurationUnit unit)
(*_entryData)->SetDurationUnit(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() void AdvSceneSwitcher::on_conditionAdd_clicked()
{ {
auto macro = getSelectedMacro(); auto macro = getSelectedMacro();
if (!macro) { if (!macro) {
return; return;
} }
MacroConditionScene temp;
AddMacroCondition((int)macro->Conditions().size()); std::string id = temp.GetId();
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); std::lock_guard<std::mutex> lock(switcher->m);
macro->Conditions().erase(macro->Conditions().begin() + idx); bool root = macro->Conditions().size() == 0;
macro->UpdateConditionIndices(); macro->Conditions().emplace_back(MacroConditionFactory::Create(id));
auto logic = root ? LogicType::ROOT_NONE : LogicType::NONE;
if (macro->Conditions().size() == 0) { macro->Conditions().back()->SetLogicType(logic);
ui->macroEditConditionHelp->setVisible(true); auto newEntry = new MacroConditionEdit(
} this, &macro->Conditions().back(), id, root, false);
ui->macroEditConditionLayout->addWidget(newEntry);
if (idx == 0 && macro->Conditions().size() > 0) { ui->macroEditConditionHelp->setVisible(false);
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() void AdvSceneSwitcher::on_conditionRemove_clicked()
@@ -323,71 +245,24 @@ void AdvSceneSwitcher::on_conditionRemove_clicked()
if (!macro) { if (!macro) {
return; return;
} }
RemoveMacroCondition((int)macro->Conditions().size() - 1);
}
void AdvSceneSwitcher::SwapConditions(Macro *m, int pos1, int pos2)
{
if (pos1 == pos2) {
return;
}
if (pos1 > pos2) {
std::swap(pos1, pos2);
}
bool root = pos1 == 0;
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(m->Conditions().begin() + pos1, if (macro->Conditions().empty()) {
m->Conditions().begin() + pos2); return;
m->UpdateConditionIndices(); }
macro->Conditions().pop_back();
auto c1 = m->Conditions().begin() + pos1; int count = ui->macroEditConditionLayout->count();
auto c2 = m->Conditions().begin() + pos2; auto item = ui->macroEditConditionLayout->takeAt(count - 1);
if (root) {
auto logic1 = (*c1)->GetLogicType(); if (item) {
auto logic2 = (*c2)->GetLogicType(); auto widget = item->widget();
(*c1)->SetLogicType(logic2); if (widget) {
(*c2)->SetLogicType(logic1); widget->setVisible(false);
}
delete item;
} }
auto item1 = ui->macroEditConditionLayout->takeAt(pos1); if (count == 1) {
auto item2 = ui->macroEditConditionLayout->takeAt(pos2 - 1); ui->macroEditConditionHelp->setVisible(true);
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);
} }

View File

@@ -32,14 +32,6 @@ static std::string getRemoteData(std::string &url)
f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION, f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION,
WriteCallback); WriteCallback);
f_curl_setopt(switcher->curl, CURLOPT_WRITEDATA, &readBuffer); 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); f_curl_perform(switcher->curl);
} }
return readBuffer; return readBuffer;
@@ -75,7 +67,7 @@ bool MacroConditionFile::checkLocalFileContent()
{ {
QString t = QString::fromStdString(_text); QString t = QString::fromStdString(_text);
QFile file(QString::fromStdString(_file)); QFile file(QString::fromStdString(_file));
if (!file.open(QIODevice::ReadOnly)) { if (_file.empty() || !file.open(QIODevice::ReadOnly)) {
return false; return false;
} }
@@ -127,11 +119,6 @@ bool MacroConditionFile::Load(obs_data_t *obj)
return true; return true;
} }
std::string MacroConditionFile::GetShortDesc()
{
return _file;
}
MacroConditionFileEdit::MacroConditionFileEdit( MacroConditionFileEdit::MacroConditionFileEdit(
QWidget *parent, std::shared_ptr<MacroConditionFile> entryData) QWidget *parent, std::shared_ptr<MacroConditionFile> entryData)
: QWidget(parent) : QWidget(parent)
@@ -244,8 +231,6 @@ void MacroConditionFileEdit::FilePathChanged()
std::lock_guard<std::mutex> lock(switcher->m); std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_file = _filePath->text().toUtf8().constData(); _entryData->_file = _filePath->text().toUtf8().constData();
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
} }
void MacroConditionFileEdit::BrowseButtonClicked() void MacroConditionFileEdit::BrowseButtonClicked()

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