mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 04:36:21 -05:00
Compare commits
346 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dfed8ac2a | ||
|
|
d7102d395e | ||
|
|
82a41694a1 | ||
|
|
a1cae263c1 | ||
|
|
cce6e240c2 | ||
|
|
9d04b4d1a0 | ||
|
|
fd7e48eff9 | ||
|
|
0350a46004 | ||
|
|
00fec4b573 | ||
|
|
c40a3af8ca | ||
|
|
e452d8cc8c | ||
|
|
fbc9818764 | ||
|
|
5ef09f661f | ||
|
|
2155a942f3 | ||
|
|
5af206da60 | ||
|
|
924f68df64 | ||
|
|
2f3c4a6dae | ||
|
|
f955c07bda | ||
|
|
6f1cd3cbcc | ||
|
|
95537f39e4 | ||
|
|
0490c97ad9 | ||
|
|
4b17314c66 | ||
|
|
7459793fe3 | ||
|
|
8a39a859be | ||
|
|
f8a592f17a | ||
|
|
f824ac8f4e | ||
|
|
8e9323173a | ||
|
|
9bc59c1082 | ||
|
|
8b9f03a349 | ||
|
|
093b0f9ec0 | ||
|
|
254eabfa8d | ||
|
|
b2da8faf37 | ||
|
|
3eba20e2d8 | ||
|
|
08841aa88e | ||
|
|
2e96c226b5 | ||
|
|
c34308f743 | ||
|
|
4af07d9d55 | ||
|
|
d743260ca8 | ||
|
|
8ff50056f0 | ||
|
|
b786831f3b | ||
|
|
32e2a5f44c | ||
|
|
e3f277c32a | ||
|
|
5a7d76061c | ||
|
|
39a8c34fa6 | ||
|
|
ead51e2f13 | ||
|
|
3b465e1fdc | ||
|
|
26fd26051b | ||
|
|
08933a3683 | ||
|
|
9be00ba3ca | ||
|
|
cce15529fe | ||
|
|
588f90f0b1 | ||
|
|
d3220c40dc | ||
|
|
79c659b4fa | ||
|
|
292adb990d | ||
|
|
b7a0f6c5d0 | ||
|
|
b3f1aff03c | ||
|
|
aea9d1b319 | ||
|
|
1fd724e4f4 | ||
|
|
3d1c613f1c | ||
|
|
9ca2f4470b | ||
|
|
34527b08a9 | ||
|
|
3ae1050488 | ||
|
|
d7ec7c6e40 | ||
|
|
e98ee64974 | ||
|
|
7c6428b27e | ||
|
|
aca9b84fc6 | ||
|
|
d397f5e406 | ||
|
|
97cbcd7e61 | ||
|
|
64fd8dd50d | ||
|
|
a0dd1cf3ef | ||
|
|
25cf51abea | ||
|
|
3c8f5088d3 | ||
|
|
66f3c74cf3 | ||
|
|
6c23110fb9 | ||
|
|
c9001df97c | ||
|
|
76fa1f8942 | ||
|
|
55ca146a82 | ||
|
|
a3625242de | ||
|
|
db4214c918 | ||
|
|
f024199e2d | ||
|
|
299e7bc868 | ||
|
|
0262e066bf | ||
|
|
bee75336d0 | ||
|
|
96b472776a | ||
|
|
fb457f723a | ||
|
|
eee3e05c10 | ||
|
|
ccc147a1b3 | ||
|
|
45a149f6df | ||
|
|
076be21d40 | ||
|
|
ab5bdb32f5 | ||
|
|
8cfed048cc | ||
|
|
c842595214 | ||
|
|
8fa3e8b038 | ||
|
|
174c17edea | ||
|
|
9d8fadda80 | ||
|
|
58028d3c3d | ||
|
|
3dcabe543f | ||
|
|
1a7ebc5569 | ||
|
|
522ab2963e | ||
|
|
d9bd98ce9c | ||
|
|
2af0735a2f | ||
|
|
556943c293 | ||
|
|
e3004184c4 | ||
|
|
7b2c2e91db | ||
|
|
06ea7bf1d9 | ||
|
|
1474509cb9 | ||
|
|
87aa8d3b40 | ||
|
|
d3e8b76fa6 | ||
|
|
99c9b1a4a2 | ||
|
|
8c0aad4c96 | ||
|
|
c964ed04d3 | ||
|
|
810235e0b7 | ||
|
|
e2b3563810 | ||
|
|
76c5ec480b | ||
|
|
84e4b740a8 | ||
|
|
95409dfa26 | ||
|
|
058af0d3bb | ||
|
|
fd789b476b | ||
|
|
3fc82df278 | ||
|
|
d541356fd3 | ||
|
|
5c2adacca1 | ||
|
|
7200668158 | ||
|
|
7cf7fd6112 | ||
|
|
41821cbeb2 | ||
|
|
9537579235 | ||
|
|
40a701a934 | ||
|
|
6c8556c66c | ||
|
|
a467dffd05 | ||
|
|
497dbd89d4 | ||
|
|
0fdbce25a1 | ||
|
|
7e3e621ae5 | ||
|
|
9dfbd266fc | ||
|
|
8d02f63c36 | ||
|
|
f31c54fd72 | ||
|
|
7719087065 | ||
|
|
0b175a41d1 | ||
|
|
0824abc4f5 | ||
|
|
efef29603b | ||
|
|
034a1b0c93 | ||
|
|
86fefe1e9e | ||
|
|
0bc15b4c2d | ||
|
|
7cfa956b80 | ||
|
|
9670a01e1a | ||
|
|
371f6daf5a | ||
|
|
1c141abd06 | ||
|
|
13788c2dfa | ||
|
|
daf36365a8 | ||
|
|
cea4df90b1 | ||
|
|
80b824e0a7 | ||
|
|
0bfdc3890b | ||
|
|
cc067de021 | ||
|
|
57c0734ba6 | ||
|
|
913682e128 | ||
|
|
92711c5798 | ||
|
|
80334088d0 | ||
|
|
bdd9d12257 | ||
|
|
decee4647b | ||
|
|
4991e74a72 | ||
|
|
baa158bb33 | ||
|
|
0975ffabfa | ||
|
|
beec7d5939 | ||
|
|
1bf2a154e2 | ||
|
|
aa691cf51c | ||
|
|
8fc12bee99 | ||
|
|
5e8a0f92ee | ||
|
|
86029e8e0e | ||
|
|
a86d6f1f76 | ||
|
|
8ef798c70c | ||
|
|
efc8726054 | ||
|
|
7b72abb100 | ||
|
|
311ee5d0a0 | ||
|
|
5e4258968a | ||
|
|
ae4e861f7f | ||
|
|
d692444687 | ||
|
|
6976c98fd8 | ||
|
|
75f8d0cb07 | ||
|
|
a7e03245bd | ||
|
|
056e7ef737 | ||
|
|
675c23d7cc | ||
|
|
c4b66ef7f6 | ||
|
|
5cae1bca41 | ||
|
|
407d338b8b | ||
|
|
edd9f18de0 | ||
|
|
c9769a799d | ||
|
|
047ca93486 | ||
|
|
bd00a3f97e | ||
|
|
72f67705ed | ||
|
|
38161f63a3 | ||
|
|
b9f6e47a49 | ||
|
|
c82c56dbb7 | ||
|
|
326cc0c46f | ||
|
|
d9997d374d | ||
|
|
c18d799f4a | ||
|
|
fdb72629db | ||
|
|
7fda5e3820 | ||
|
|
78966e456a | ||
|
|
49a042039e | ||
|
|
adb266927f | ||
|
|
703f24b8fc | ||
|
|
de6120c401 | ||
|
|
b1f7a255d5 | ||
|
|
d112e92d33 | ||
|
|
5c4dd6dae1 | ||
|
|
546a83ee07 | ||
|
|
09ab29b4ba | ||
|
|
86d4e59dc2 | ||
|
|
bf03edd391 | ||
|
|
aa7714210a | ||
|
|
2454ea8fa5 | ||
|
|
a5edbc8b88 | ||
|
|
ec6cffcd6a | ||
|
|
89849a0792 | ||
|
|
48e6bcbb7a | ||
|
|
6893d9539e | ||
|
|
4a84bede37 | ||
|
|
77642c54d8 | ||
|
|
069b0f89d0 | ||
|
|
e517fa7b39 | ||
|
|
9301713c49 | ||
|
|
66285a0d3d | ||
|
|
e83a9e8d94 | ||
|
|
881e197cb2 | ||
|
|
e7f031641f | ||
|
|
198a5dc1ec | ||
|
|
5496c256c0 | ||
|
|
a93cec2bb9 | ||
|
|
32101627a6 | ||
|
|
c2d2a27d44 | ||
|
|
5eb8378612 | ||
|
|
961ea655fd | ||
|
|
c1704f2164 | ||
|
|
e4b060976b | ||
|
|
186198bfd4 | ||
|
|
283025f1a8 | ||
|
|
5b4ddfa669 | ||
|
|
572b974b82 | ||
|
|
ae71b24c60 | ||
|
|
e803ba75f9 | ||
|
|
72bd905e7c | ||
|
|
51680adc20 | ||
|
|
4b84850f00 | ||
|
|
6a998934d0 | ||
|
|
b80c16a446 | ||
|
|
f4d11dd6e6 | ||
|
|
4248b86705 | ||
|
|
305ce96ad0 | ||
|
|
74dfd9af30 | ||
|
|
c911862d8c | ||
|
|
2a73583793 | ||
|
|
8f16d05a28 | ||
|
|
2ce0b35921 | ||
|
|
33d2def126 | ||
|
|
c44b0a2ac2 | ||
|
|
3abeb936b3 | ||
|
|
cef513f775 | ||
|
|
a66961eac1 | ||
|
|
92c8767e1a | ||
|
|
5b12468a46 | ||
|
|
675021c284 | ||
|
|
6bf122d0e8 | ||
|
|
8b8e479098 | ||
|
|
717d41a527 | ||
|
|
ad5587e084 | ||
|
|
f37f384b5a | ||
|
|
dad36689c4 | ||
|
|
0bd7d004ad | ||
|
|
f8c589c7a2 | ||
|
|
e714df7ad0 | ||
|
|
6277da1bbd | ||
|
|
1bef309264 | ||
|
|
2e1d660e17 | ||
|
|
3f492f468a | ||
|
|
c86bba84b3 | ||
|
|
c468b0698b | ||
|
|
2af82fe22a | ||
|
|
5d720219bf | ||
|
|
484e1aa191 | ||
|
|
0fdfe757b4 | ||
|
|
bc5a04651f | ||
|
|
d9dfc1913d | ||
|
|
1310d0b3f3 | ||
|
|
139df8a641 | ||
|
|
acf1ae63aa | ||
|
|
041a9e7f19 | ||
|
|
427ed34a1b | ||
|
|
45fa4dac8f | ||
|
|
e4bf5fa749 | ||
|
|
eb346da6f4 | ||
|
|
866480cde6 | ||
|
|
10e1c7b3a3 | ||
|
|
beb482bd5a | ||
|
|
e561d378dd | ||
|
|
73ce88e2f0 | ||
|
|
dfccc4b16d | ||
|
|
b0ef1fee71 | ||
|
|
1ef8ce4b4a | ||
|
|
1bf4bff014 | ||
|
|
4b6e00b2b2 | ||
|
|
c99cbb0c0f | ||
|
|
2a87334d38 | ||
|
|
1a4724ff21 | ||
|
|
59d8fb5d28 | ||
|
|
8823c05aeb | ||
|
|
2d0a52f8d1 | ||
|
|
1273446ce5 | ||
|
|
177ca4aea2 | ||
|
|
7526cbe1a3 | ||
|
|
e4bb034303 | ||
|
|
78e14df620 | ||
|
|
34f07bfb07 | ||
|
|
ee74d39424 | ||
|
|
33667a1f23 | ||
|
|
7947ad2608 | ||
|
|
920c188213 | ||
|
|
28fbff1adc | ||
|
|
326617aad7 | ||
|
|
499ba7dd21 | ||
|
|
f4902933ab | ||
|
|
9aa0b31bff | ||
|
|
6d5086b971 | ||
|
|
f32f47db4b | ||
|
|
74c0cd1736 | ||
|
|
a74a952b1d | ||
|
|
5bbfef81e0 | ||
|
|
c31d1cd975 | ||
|
|
81d91a9139 | ||
|
|
a354daa71d | ||
|
|
a84a205608 | ||
|
|
a5f0eb8da8 | ||
|
|
35151ea134 | ||
|
|
1510a2c2fa | ||
|
|
8e8cb4bf3e | ||
|
|
a480be3ea0 | ||
|
|
27ae5107cd | ||
|
|
69d452f978 | ||
|
|
fe9457427f | ||
|
|
d989c2b570 | ||
|
|
1f4679433e | ||
|
|
b42de8d5c8 | ||
|
|
0950d93828 | ||
|
|
5156c66b26 | ||
|
|
346240473a | ||
|
|
17c4fefb37 | ||
|
|
2b90493ae9 | ||
|
|
bf97975fa8 | ||
|
|
4e971f59a9 |
49
.github/workflows/build-debian.yml
vendored
Normal file
49
.github/workflows/build-debian.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
name: debian-build
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: check_libobs_revision
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install libobs-dev
|
||||
mkdir source
|
||||
cd source
|
||||
dpkg -l libobs-dev | tr -s " "| grep libobs | cut -d" " -f3 > libobs.rev
|
||||
- name: install_frontend_header
|
||||
run: |
|
||||
[ -e /usr/include/obs/obs-frontend-api.h ] && { echo "ERROR: obs-frontend-api.h already in system. Maybe the package libobs-dev is installing it."; exit 1; }
|
||||
cd source
|
||||
LIBOBSREV=$(cat libobs.rev)
|
||||
sudo apt update
|
||||
sudo apt install devscripts
|
||||
dget -u http://archive.ubuntu.com/ubuntu/pool/universe/o/obs-studio/obs-studio_$LIBOBSREV.dsc
|
||||
cd ..
|
||||
sudo find -name obs-frontend-api.h -exec cp {} /usr/include/obs/ \;
|
||||
egrep '#include <obs.h>' /usr/include/obs/obs-frontend-api.h || { echo "ERROR: check if the sed commands are needed from now."; exit 1; }
|
||||
sudo sed -i 's/#include <obs.h>/#include <obs\/obs.h>/' /usr/include/obs/obs-frontend-api.h
|
||||
sudo sed -i 's/#include <util\/darray.h>/#include <obs\/util\/darray.h>/' /usr/include/obs/obs-frontend-api.h
|
||||
- name: create_tarball
|
||||
run: |
|
||||
cd ..
|
||||
tar --exclude=.git -cvzf obs-scene-switcher_0.1+testonly.orig.tar.gz SceneSwitcher
|
||||
- name: create_debian_dir
|
||||
run: |
|
||||
cp -a CI/linux/debian .
|
||||
- name: install_dependencies
|
||||
run: |
|
||||
# devscripts and libobs-dev are needed but they were already installed
|
||||
# from check_libobs_revision and install_frontend_header sections.
|
||||
sudo apt update
|
||||
sudo apt install cmake debhelper libcurl4-openssl-dev libxss-dev libxtst-dev qtbase5-dev libopencv-dev libprocps-dev
|
||||
- name: build
|
||||
run: |
|
||||
debuild --no-lintian --no-sign
|
||||
136
.github/workflows/build.yml
vendored
136
.github/workflows/build.yml
vendored
@@ -1,14 +1,11 @@
|
||||
name: build obs plugin
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
env:
|
||||
PLUGIN_NAME: SceneSwitcher
|
||||
LIB_NAME: advanced-scene-switcher
|
||||
OBS_TAG: 27.1.3
|
||||
|
||||
jobs:
|
||||
macos64:
|
||||
@@ -23,10 +20,12 @@ jobs:
|
||||
with:
|
||||
repository: obsproject/obs-studio
|
||||
submodules: 'recursive'
|
||||
ref: 'refs/tags/${{ env.OBS_TAG }}'
|
||||
- name: "Checkout plugin"
|
||||
uses: actions/checkout@v2.3.4
|
||||
with:
|
||||
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
|
||||
submodules: 'recursive'
|
||||
- name: Fetch Git Tags
|
||||
run: |
|
||||
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}
|
||||
@@ -56,13 +55,22 @@ jobs:
|
||||
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz
|
||||
tar -xf ./macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz -C "/tmp"
|
||||
xattr -r -d com.apple.quarantine /tmp/obsdeps
|
||||
- name: 'Build prerequisite: OpenCV'
|
||||
shell: bash
|
||||
run: |
|
||||
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}/deps/opencv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DBUILD_LIST="core,imgproc,objdetect" ..
|
||||
make -j4
|
||||
make install
|
||||
- name: Configure
|
||||
shell: bash
|
||||
run: |
|
||||
echo "add_subdirectory(${{ env.PLUGIN_NAME }})" >> UI/frontend-plugins/CMakeLists.txt
|
||||
mkdir ./build
|
||||
cd ./build
|
||||
cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DDISABLE_PYTHON=ON -DDepsPath="/tmp/obsdeps" -DQTDIR="/tmp/obsdeps" ..
|
||||
cmake -DBUILD_BROWSER=OFF -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DDISABLE_PYTHON=ON -DDepsPath="/tmp/obsdeps" -DQTDIR="/tmp/obsdeps" ..
|
||||
cd -
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -75,8 +83,9 @@ jobs:
|
||||
if: success()
|
||||
shell: bash
|
||||
run: |
|
||||
curl -L -O https://s3-us-west-2.amazonaws.com/obs-nightly/Packages.pkg
|
||||
sudo installer -pkg ./Packages.pkg -target /
|
||||
curl -L -O http://s.sudre.free.fr/Software/files/Packages.dmg
|
||||
sudo hdiutil attach ./Packages.dmg
|
||||
sudo installer -pkg /Volumes/Packages\ 1.2.9/Install\ Packages.pkg -target /
|
||||
- name: Package
|
||||
if: success()
|
||||
shell: bash
|
||||
@@ -109,10 +118,12 @@ jobs:
|
||||
with:
|
||||
repository: obsproject/obs-studio
|
||||
submodules: 'recursive'
|
||||
ref: 'refs/tags/${{ env.OBS_TAG }}'
|
||||
- name: "Checkout plugin"
|
||||
uses: actions/checkout@v2.3.4
|
||||
with:
|
||||
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
|
||||
submodules: 'recursive'
|
||||
- name: Add plugin to obs cmake
|
||||
shell: bash
|
||||
run: echo "add_subdirectory(${{ env.PLUGIN_NAME }})" >> UI/frontend-plugins/CMakeLists.txt
|
||||
@@ -157,19 +168,25 @@ jobs:
|
||||
libxcb-xinerama0-dev \
|
||||
libxcomposite-dev \
|
||||
libxinerama-dev \
|
||||
libxtst-dev \
|
||||
libmbedtls-dev \
|
||||
pkg-config \
|
||||
python3-dev \
|
||||
qtbase5-dev \
|
||||
qtbase5-private-dev \
|
||||
libqt5svg5-dev \
|
||||
swig \
|
||||
libxss-dev
|
||||
libxss-dev \
|
||||
libx11-xcb-dev \
|
||||
libxcb-xfixes0-dev \
|
||||
libopencv-dev \
|
||||
libprocps-dev
|
||||
- name: 'Configure'
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir ./build
|
||||
cd ./build
|
||||
cmake -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DWITH_RTMPS=OFF -DBUILD_BROWSER=OFF ..
|
||||
cmake -DENABLE_PIPEWIRE=OFF -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DWITH_RTMPS=OFF -DBUILD_BROWSER=OFF ..
|
||||
- name: 'Build'
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/build
|
||||
@@ -181,6 +198,7 @@ jobs:
|
||||
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-linux64.tar.gz
|
||||
echo "FILE_NAME=${FILE_NAME}" >> $GITHUB_ENV
|
||||
mkdir -p ./${{ env.LIB_NAME }}/bin/64bit/
|
||||
strip -d ./build/UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.LIB_NAME }}.so
|
||||
mv ./build/UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.LIB_NAME }}.so ./${{ env.LIB_NAME }}/bin/64bit/${{ env.LIB_NAME }}.so
|
||||
mv ./UI/frontend-plugins/${{ env.PLUGIN_NAME }}/data ./${{ env.LIB_NAME }}/data
|
||||
tar -cvzf "${FILE_NAME}" ${{ env.LIB_NAME }}
|
||||
@@ -192,11 +210,14 @@ jobs:
|
||||
windows:
|
||||
name: Windows
|
||||
runs-on: [windows-latest]
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [32, 64]
|
||||
env:
|
||||
QT_VERSION: 5.10.1
|
||||
CMAKE_GENERATOR: "Visual Studio 16 2019"
|
||||
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
|
||||
WINDOWS_DEPS_VERSION: '2017'
|
||||
WINDOWS_DEPS_VERSION: '2019'
|
||||
steps:
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
@@ -205,10 +226,12 @@ jobs:
|
||||
with:
|
||||
repository: obsproject/obs-studio
|
||||
submodules: 'recursive'
|
||||
ref: 'refs/tags/${{ env.OBS_TAG }}'
|
||||
- name: Checkout plugin
|
||||
uses: actions/checkout@v2.3.4
|
||||
with:
|
||||
path: UI/frontend-plugins/${{ env.PLUGIN_NAME}}
|
||||
submodules: 'recursive'
|
||||
- name: Add plugin to obs cmake
|
||||
shell: cmd
|
||||
run: echo add_subdirectory(${{ env.PLUGIN_NAME }}) >> UI/frontend-plugins/CMakeLists.txt
|
||||
@@ -222,55 +245,99 @@ jobs:
|
||||
run: |
|
||||
curl -kLO https://cdn-fastly.obsproject.com/downloads/dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -f --retry 5 -C -
|
||||
7z x dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -o"${{ github.workspace }}/cmbuild/deps"
|
||||
- name: 'Build prerequisite: OpenCV'
|
||||
run: |
|
||||
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}/deps/opencv
|
||||
mkdir build
|
||||
cd build
|
||||
if ( ${{ matrix.arch }} -eq 32 )
|
||||
{
|
||||
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DBUILD_LIST="core,imgproc,objdetect" ..
|
||||
}
|
||||
else
|
||||
{
|
||||
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DBUILD_LIST="core,imgproc,objdetect" ..
|
||||
}
|
||||
msbuild /m /p:Configuration=Release OpenCV.sln
|
||||
msbuild INSTALL.vcxproj
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir ./package
|
||||
mkdir ./build32
|
||||
cd ./build32
|
||||
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win32" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
|
||||
cd ..
|
||||
mkdir ./build64
|
||||
cd ./build64
|
||||
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win64" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017_64" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
|
||||
mkdir ./build${{ matrix.arch }}
|
||||
cd ./build${{ matrix.arch }}
|
||||
Get-Location
|
||||
if ( ${{ matrix.arch }} -eq 32 )
|
||||
{
|
||||
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DOpenCV_DIR="${{ github.workspace }}/UI/frontend-plugins/SceneSwitcher/deps/opencv/build/" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win32" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
|
||||
}
|
||||
else
|
||||
{
|
||||
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DOpenCV_DIR="${{ github.workspace }}/UI/frontend-plugins/SceneSwitcher/deps/opencv/build/" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win64" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017_64" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
|
||||
}
|
||||
- name: Build
|
||||
run: |
|
||||
msbuild /m /p:Configuration=RelWithDebInfo .\build32\obs-studio.sln
|
||||
msbuild /m /p:Configuration=RelWithDebInfo .\build64\obs-studio.sln
|
||||
msbuild /m /p:Configuration=RelWithDebInfo .\build${{ matrix.arch }}\obs-studio.sln
|
||||
- name: Package
|
||||
if: success()
|
||||
run: |
|
||||
$env:FILE_DATE=(Get-Date -UFormat "%F")
|
||||
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-windows"
|
||||
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
|
||||
robocopy .\build32\rundir\RelWithDebInfo\obs-plugins\32bit\ .\package\obs-plugins\32bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
||||
robocopy .\build64\rundir\RelWithDebInfo\obs-plugins\64bit\ .\package\obs-plugins\64bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
||||
robocopy .\build64\rundir\RelWithDebInfo\data\obs-plugins\${{ env.LIB_NAME }}\ .\package\data\obs-plugins\${{ env.LIB_NAME }}\ /E /XF .gitignore
|
||||
robocopy .\build${{ matrix.arch }}\rundir\RelWithDebInfo\obs-plugins\${{ matrix.arch }}bit\ .\package\obs-plugins\${{ matrix.arch }}bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
||||
robocopy .\build${{ matrix.arch }}\rundir\RelWithDebInfo\data\obs-plugins\${{ env.LIB_NAME }}\ .\package\data\obs-plugins\${{ env.LIB_NAME }}\ /E /XF .gitignore
|
||||
cp UI/frontend-plugins/${{ env.PLUGIN_NAME }}/deps/opencv/build/bin/Release/*dll package/obs-plugins/${{ matrix.arch }}bit
|
||||
exit 0
|
||||
- name: Publish zip
|
||||
if: success()
|
||||
uses: actions/upload-artifact@v2.2.1
|
||||
with:
|
||||
name: '${{ env.FILE_NAME }}'
|
||||
name: '${{ env.FILE_NAME }}-${{ matrix.arch }}bit'
|
||||
path: package/*
|
||||
- name: "Package Installer (Prereqs)"
|
||||
windows-installer:
|
||||
needs: [windows]
|
||||
name: 'Create Windows Installer'
|
||||
runs-on: [windows-latest]
|
||||
steps:
|
||||
- name: "Checkout plugin"
|
||||
uses: actions/checkout@v2.3.4
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
- name: "Prepare innosetup"
|
||||
run: |
|
||||
curl "-kL" "https://files.jrsoftware.org/is/6/innosetup-6.0.3.exe" "-f" "--retry" "5" "-o" "inno.exe"
|
||||
.\inno.exe /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
continue-on-error: true
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: artifacts
|
||||
- name: "Prepare package dir"
|
||||
run: |
|
||||
curl "-kL" "https://github.com/Xaymar/msvc-redist-helper/releases/download/0.1/msvc-redist-helper-64.exe" "-f" "--retry" "5" "-o" "msvc-redist-helper-64.exe"
|
||||
curl "-kL" "https://github.com/Xaymar/msvc-redist-helper/releases/download/0.1/msvc-redist-helper-32.exe" "-f" "--retry" "5" "-o" "msvc-redist-helper-32.exe"
|
||||
curl "-kL" "https://files.jrsoftware.org/is/6/innosetup-6.0.3.exe" "-f" "--retry" "5" "-o" "inno.exe"
|
||||
.\inno.exe /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART
|
||||
- name: "Package Installer (Compile)"
|
||||
$env:FILE_DATE=(Get-Date -UFormat "%F")
|
||||
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-windows"
|
||||
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
|
||||
mkdir package
|
||||
cd package
|
||||
cp -r ../artifacts/${env:FILE_NAME}-32bit/* .
|
||||
cp -r ../artifacts/${env:FILE_NAME}-64bit/obs-plugins/* obs-plugins
|
||||
- name: "Compile"
|
||||
run: |
|
||||
& 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' /Qp ".\build64\UI\frontend-plugins\${{ env.PLUGIN_NAME }}\CI\windows\setup.iss"
|
||||
- name: Publish installer
|
||||
& 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' /Qp ".\build\CI\windows\setup.iss"
|
||||
- name: "Publish"
|
||||
if: success()
|
||||
uses: actions/upload-artifact@v2.2.0
|
||||
with:
|
||||
name: '${{ env.FILE_NAME }}-installer'
|
||||
path: build64/UI/frontend-plugins/SceneSwitcher/CI/windows/Output/*.exe
|
||||
path: build/CI/windows/Output/*.exe
|
||||
release:
|
||||
needs: [macos64, ubuntu64, windows]
|
||||
needs: [macos64, ubuntu64, windows, windows-installer]
|
||||
name: 'Create Release'
|
||||
runs-on: [ubuntu-latest]
|
||||
runs-on: [ubuntu-18.04]
|
||||
steps:
|
||||
- name: "Checkout plugin"
|
||||
uses: actions/checkout@v2.3.4
|
||||
@@ -286,7 +353,8 @@ jobs:
|
||||
mkdir -p ${{ env.PLUGIN_NAME }}/Linux ${{ env.PLUGIN_NAME }}/MacOs ${{ env.PLUGIN_NAME }}/Windows
|
||||
tar xf artifacts/${{ env.PLUGIN_NAME }}*-linux64.tar.gz/${{ env.PLUGIN_NAME }}*-linux64.tar.gz -C ${{ env.PLUGIN_NAME }}/Linux/
|
||||
mv artifacts/${{ env.PLUGIN_NAME }}*-macos.pkg/${{ env.PLUGIN_NAME }}*-macos.pkg ${{ env.PLUGIN_NAME }}/MacOs/${{ env.PLUGIN_NAME }}.pkg
|
||||
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows/* ${{ env.PLUGIN_NAME }}/Windows/
|
||||
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows-32bit/* ${{ env.PLUGIN_NAME }}/Windows/
|
||||
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows-64bit/obs-plugins/* ${{ env.PLUGIN_NAME }}/Windows/obs-plugins
|
||||
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows-installer/*.exe ${{ env.PLUGIN_NAME }}/Windows/
|
||||
rm ${{ env.PLUGIN_NAME }}/Windows/obs-plugins/32bit/advanced-scene-switcher.pdb
|
||||
rm ${{ env.PLUGIN_NAME }}/Windows/obs-plugins/64bit/advanced-scene-switcher.pdb
|
||||
|
||||
15
.github/workflows/clang-format.yml
vendored
15
.github/workflows/clang-format.yml
vendored
@@ -8,23 +8,10 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Install clang format
|
||||
run: |
|
||||
# gets us newer clang
|
||||
sudo bash -c "cat >> /etc/apt/sources.list" << LLVMAPT
|
||||
# 3.8
|
||||
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
|
||||
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
|
||||
LLVMAPT
|
||||
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
|
||||
|
||||
sudo apt-get -qq update
|
||||
|
||||
sudo apt-get install -y clang-format-8
|
||||
sudo apt-get install -y clang-format-10
|
||||
|
||||
- name: Check the Formatting
|
||||
run: |
|
||||
|
||||
9
.gitmodules
vendored
Normal file
9
.gitmodules
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
[submodule "deps/asio"]
|
||||
path = deps/asio
|
||||
url = https://github.com/chriskohlhoff/asio.git
|
||||
[submodule "deps/websocketpp"]
|
||||
path = deps/websocketpp
|
||||
url = https://github.com/zaphoyd/websocketpp.git
|
||||
[submodule "deps/opencv"]
|
||||
path = deps/opencv
|
||||
url = https://github.com/opencv/opencv.git
|
||||
152
BUILDING.md
Normal file
152
BUILDING.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# 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)
|
||||
```
|
||||
|
||||
Now follow the [build instructions for obs-studio](https://obsproject.com/wiki/install-instructions) for your particular platform.
|
||||
|
||||
Note that on Linux systems it might be necessary to additionally install the following packages to fulfill the dependencies to `XTest`, `XScreensaver` and `OpenCV` - exact command may differ:
|
||||
```
|
||||
sudo apt-get install \
|
||||
libxtst-dev \
|
||||
libxss-dev \
|
||||
libopencv-dev
|
||||
```
|
||||
|
||||
|
||||
## 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_LIBRARY** (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
|
||||
Install dependencies `XTest`, `XScreensaver` and `OpenCV` - exact command may differ:
|
||||
```
|
||||
sudo apt-get install \
|
||||
libxtst-dev \
|
||||
libxss-dev \
|
||||
libopencv-dev
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
@@ -6,6 +6,8 @@ set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
|
||||
|
||||
# Runs the Clang Formatter in parallel on the code base.
|
||||
# Return codes:
|
||||
# - 1 there are files to be formatted
|
||||
@@ -19,13 +21,15 @@ if [[ $OS = "Linux" || $OS = "Darwin" ]] ; then
|
||||
fi
|
||||
|
||||
# Discover clang-format
|
||||
if type clang-format-8 2> /dev/null ; then
|
||||
if type clang-format-10 2> /dev/null ; then
|
||||
CLANG_FORMAT=clang-format-10
|
||||
elif type clang-format-8 2> /dev/null ; then
|
||||
CLANG_FORMAT=clang-format-8
|
||||
else
|
||||
CLANG_FORMAT=clang-format
|
||||
fi
|
||||
|
||||
find .. -type d \( -path ./deps \
|
||||
-o -path ./cmake \
|
||||
-o -path ./build \) -prune -type f -o -name '*.h' -or -name '*.hpp' -or -name '*.m' -or -name '*.mm' -or -name '*.c' -or -name '*.cpp' \
|
||||
find $SCRIPTPATH/.. -type d \( -path $SCRIPTPATH/../deps \
|
||||
-o -path $SCRIPTPATH/../cmake \
|
||||
-o -path $SCRIPTPATH/../build \) -prune -type f -o -name '*.h' -or -name '*.hpp' -or -name '*.m' -or -name '*.mm' -or -name '*.c' -or -name '*.cpp' \
|
||||
| xargs -L100 -P${NPROC} ${CLANG_FORMAT} -i -style=file -fallback-style=none
|
||||
|
||||
5
CI/linux/debian/changelog
Normal file
5
CI/linux/debian/changelog
Normal file
@@ -0,0 +1,5 @@
|
||||
obs-scene-switcher (0.1+testonly) focal; urgency=medium
|
||||
|
||||
* Initial release (Closes: #123456)
|
||||
|
||||
-- Joao Eriberto Mota Filho <eriberto@debian.org> Fri, 03 Sep 2021 11:39:52 -0300
|
||||
22
CI/linux/debian/control
Normal file
22
CI/linux/debian/control
Normal file
@@ -0,0 +1,22 @@
|
||||
Source: obs-scene-switcher
|
||||
Section: video
|
||||
Priority: optional
|
||||
Maintainer: Joao Eriberto Mota Filho <eriberto@debian.org>
|
||||
Build-Depends: cmake,
|
||||
debhelper-compat (= 12),
|
||||
libcurl4-openssl-dev,
|
||||
libobs-dev,
|
||||
libxtst-dev,
|
||||
qtbase5-dev,
|
||||
libxss-dev,
|
||||
libopencv-dev
|
||||
Standards-Version: 4.6.0
|
||||
Homepage: https://obsproject.com/forum/resources/advanced-scene-switcher.395/
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: obs-scene-switcher
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: automated scene switcher for OBS Studio (plugin)
|
||||
Advanced Scene Switcher is based on the built in scene switcher. It extends
|
||||
its functionality by adding several features.
|
||||
60
CI/linux/debian/copyright
Normal file
60
CI/linux/debian/copyright
Normal file
@@ -0,0 +1,60 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: SceneSwitcher
|
||||
Upstream-Contact: https://github.com/WarmUpTill/SceneSwitcher/issues
|
||||
Source: https://github.com/WarmUpTill/SceneSwitcher
|
||||
|
||||
Files: *
|
||||
Copyright: 2016-2021 WarmUpTill <WarmUpTill@web.de>
|
||||
License: GPL-2
|
||||
|
||||
Files: cmake/GetGitRevisionDescription.cmake
|
||||
cmake/GetGitRevisionDescription.cmake.in
|
||||
Copyright: 2009-2013 Iowa State University
|
||||
2013-2020 Contributors
|
||||
2013-2020 Ryan Pavlik
|
||||
License: BSL-1.0
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2021 Joao Eriberto Mota Filho <eriberto@debian.org>
|
||||
License: BSL-1.0
|
||||
|
||||
License: GPL-2
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2.
|
||||
.
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||
|
||||
License: BSL-1.0
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
.
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
.
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
16
CI/linux/debian/rules
Normal file
16
CI/linux/debian/rules
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/make -f
|
||||
#export DH_VERBOSE = 1
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
export QT_SELECT = qt5
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
|
||||
dh_auto_configure -- -DBUILD_OUT_OF_TREE=1 \
|
||||
-DLIBOBS_INCLUDE_DIR=/usr/include/obs \
|
||||
-DLIBOBS_LIB=/usr/lib/${DEB_TARGET_MULTIARCH}/libobs.so \
|
||||
-DLIBOBS_FRONTEND_INCLUDE_DIR=/usr/include/obs \
|
||||
-DLIBOBS_FRONTEND_API_LIB=/usr/lib/${DEB_TARGET_MULTIARCH}/libobs-frontend-api.so
|
||||
1
CI/linux/debian/source/format
Normal file
1
CI/linux/debian/source/format
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (native)
|
||||
@@ -46,6 +46,294 @@
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_objdetect.4.5.3.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_features2d.4.5.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_core.4.5.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_calib3d.4.5.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_calib3d.4.5.3.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_imgproc.4.5.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_features2d.4.5.3.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_core.4.5.3.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_flann.4.5.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_calib3d.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_objdetect.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_imgproc.4.5.3.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_flann.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_imgproc.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_flann.4.5.3.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_features2d.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_core.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>../../deps/opencv/build/lib/libopencv_objdetect.4.5.dylib</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
|
||||
@@ -1,31 +1,42 @@
|
||||
Note that you will have to use OBS version 25 or newer!
|
||||
Note that you will have to use OBS version 27 or newer!
|
||||
|
||||
--- WINDOWS ---
|
||||
--- Windows ---
|
||||
Recommended: Run the provided installer. (You might have to click 'More info' and select 'Run anyway' if it is blocked by Windows)
|
||||
|
||||
Alternatively manually copy the 'obs-plugins' and 'data' folders in the respective OBS Studio installation directory.
|
||||
It is usually located at 'C:\Program Files (x86)\obs-studio\'.
|
||||
Remember to install the Visual C++ Redistributable for Visual Studio 2019, if you have not done so already. (See plugin overview page)
|
||||
|
||||
--- MAC OS ---
|
||||
Recommended: Run the provided installer. (You might have to right click and select 'open' if it is blocked)
|
||||
|
||||
Alternatively extract the *so file and data folder and either ...
|
||||
|
||||
... right click the OBS app inside your Applications folder and choose 'Show Package Contents'.
|
||||
Copy the advanced-scene-switcher.so file to 'Contents/Plugins' and the 'data' folder to 'Contents/Resources'.
|
||||
|
||||
... or 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/'.
|
||||
--- macOS ---
|
||||
Run the provided installer. (You might have to right-click or control-click and select 'open' if it is blocked)
|
||||
|
||||
--- Linux ---
|
||||
Copy the advanced-scene-switcher.so file and data folder into the OBS Studio plugin folder.
|
||||
The location of this folder can vary so you might have to look around a bit.
|
||||
Note that the plugin has dependencies to:
|
||||
* libXss
|
||||
* libopencv-imgproc
|
||||
* libopencv-objdetect
|
||||
Optional:
|
||||
* libXtst
|
||||
* libcurl
|
||||
|
||||
Copy the advanced-scene-switcher.so file and into the OBS Studio plugin folder.
|
||||
The location of this folder can vary, so you might have to look around a bit.
|
||||
|
||||
Examples are ...
|
||||
/usr/lib/obs-plugins/
|
||||
/usr/lib/x86_64-linux-gnu/obs-plugins/
|
||||
/usr/share/obs/obs-plugins/
|
||||
~/.config/obs-studio/plugins/advanced-scene-switcher/bin/64bit/
|
||||
~/.local/share/flatpak/app/com.obsproject.Studio/x86_64/stable/active/files/lib/obs-plugins/
|
||||
/var/lib/flatpak/app/com.obsproject.Studio/x86_64/stable/active/files/lib/obs-plugins/
|
||||
|
||||
Unfortunately the expected location of the locale, which can be found in the data folder, can vary also.
|
||||
The data folder usually should be copied to:
|
||||
~/.config/obs-studio/plugins/advanced-scene-switcher/
|
||||
|
||||
If this does not work you can try to copy the "locale" folder found inside the data folder to:
|
||||
/usr/share/obs/obs-plugins/advanced-scene-switcher/locale
|
||||
~/.local/share/flatpak/app/com.obsproject.Studio/x86_64/stable/active/files/share/obs/obs-plugins/advanced-scene-switcher/locale
|
||||
/var/lib/flatpak/app/com.obsproject.Studio/x86_64/stable/active/files/share/obs/obs-plugins/advanced-scene-switcher/locale
|
||||
|
||||
In doubt please check where other "en-US.ini" files are located on your system.
|
||||
|
||||
563
CMakeLists.txt
563
CMakeLists.txt
@@ -1,194 +1,433 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(advanced-scene-switcher)
|
||||
|
||||
# generate version info
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
||||
endif()
|
||||
|
||||
# Compiler settings
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC
|
||||
OR CMAKE_COMPILER_IS_GNUCXX
|
||||
OR CMAKE_COMPILER_IS_CLANG)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"-Wall -Wextra -Wvla -Wno-unused-function -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS} -fno-strict-aliasing"
|
||||
)
|
||||
set(CMAKE_C_FLAGS
|
||||
"-Wall -Wextra -Wvla -Wno-unused-function -Werror-implicit-function-declaration -Wno-missing-braces -Wno-missing-field-initializers ${CMAKE_C_FLAGS} -std=gnu99 -fno-strict-aliasing"
|
||||
)
|
||||
|
||||
option(USE_LIBC++ "Use libc++ instead of libstdc++" ${APPLE})
|
||||
if(USE_LIBC++)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
elseif(MSVC)
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
|
||||
# Disable pointless constant condition warnings
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} /wd4127 /wd4201 /wd4456 /wd4457 /wd4458 /wd4459 /wd4595"
|
||||
)
|
||||
add_definitions(-DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS
|
||||
-D_CRT_NONSTDC_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
# Generate version info
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
|
||||
git_describe(GIT_TAG)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
|
||||
|
||||
# Windows installer
|
||||
if(WIN32)
|
||||
get_filename_component(ISS_PLUGIN_FILES_DIR "${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
|
||||
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}" ISS_MSVC_REDIST_HELPER_DIR)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
|
||||
get_filename_component(ISS_PLUGIN_FILES_DIR
|
||||
"${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
|
||||
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_BINARY_DIR}\\.."
|
||||
ABSOLUTE)
|
||||
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}"
|
||||
ISS_MSVC_REDIST_HELPER_DIR)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
|
||||
endif()
|
||||
|
||||
# Out of tree specific settings
|
||||
if(BUILD_OUT_OF_TREE)
|
||||
set(CMAKE_PREFIX_PATH "${QTDIR}")
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/external")
|
||||
set(CMAKE_PREFIX_PATH "${QTDIR}")
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(LibObs)
|
||||
find_package(LibObs-frontend-api)
|
||||
if(LibObs_FOUND)
|
||||
set(LIBOBS_LIB ${LIBOBS_LIBRARIES})
|
||||
set(LIBOBS_INCLUDE_DIR ${LIBOBS_INCLUDE_DIRS})
|
||||
endif()
|
||||
if(LibObs-frontend-api_FOUND)
|
||||
set(LIBOBS_FRONTEND_API_LIB ${LIBOBS-FRONTEND-API_LIBRARIES})
|
||||
set(LIBOBS_FRONTEND_INCLUDE_DIR ${LIBOBS-FRONTEND-API_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
include(external/FindLibObs.cmake)
|
||||
find_package(LibObs REQUIRED)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Libcurl REQUIRED)
|
||||
find_path(LIBOBS_FRONTEND_INCLUDE_DIR HINTS ${LIBOBS_INCLUDE_DIRS})
|
||||
find_file(LIBOBS_FRONTEND_API_LIB NAMES libobs-frontend-api.* HINTS ${LIBOBS_LIB} )
|
||||
if(NOT LIBOBS_LIB)
|
||||
message(FATAL_ERROR "obs library not found - please set LIBOBS_LIB")
|
||||
endif()
|
||||
if(NOT LIBOBS_FRONTEND_API_LIB)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"libobs frontend-api library not found - please set LIBOBS_FRONTEND_API_LIB"
|
||||
)
|
||||
endif()
|
||||
if(NOT LIBOBS_INCLUDE_DIR)
|
||||
message(
|
||||
FATAL_ERROR "obs.hpp header not found - please set LIBOBS_INCLUDE_DIR")
|
||||
endif()
|
||||
if(NOT LIBOBS_FRONTEND_INCLUDE_DIR)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
" obs-frontend-api.h not found - please set LIBOBS_FRONTEND_INCLUDE_DIR"
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories("${LIBOBS_INCLUDE_DIR}" "${LIBOBS_FRONTEND_INCLUDE_DIR}"
|
||||
${Qt5Core_INCLUDES} ${Qt5Widgets_INCLUDES})
|
||||
|
||||
find_package(CURL REQUIRED)
|
||||
include_directories("${CURL_INCLUDE_DIRS}")
|
||||
|
||||
# Backwards compatability with older OBS versions
|
||||
if(LibObs_VERSION_MAJOR GREATER_EQUAL 27)
|
||||
add_definitions(-DVCAM_SUPPORTED)
|
||||
else()
|
||||
message(
|
||||
WARNING
|
||||
"OBS version ${LibObs_VERSION_MAJOR} found - disabling virtual camera functionality"
|
||||
)
|
||||
endif()
|
||||
if(LibObs_VERSION_MAJOR GREATER_EQUAL 26)
|
||||
add_definitions(-DREPLAYBUFFER_SUPPORTED)
|
||||
else()
|
||||
message(
|
||||
WARNING
|
||||
"OBS version ${LibObs_VERSION_MAJOR} found - disabling replay buffer functionality"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
find_package(Libcurl REQUIRED)
|
||||
include_directories("${LIBCURL_INCLUDE_DIRS}")
|
||||
add_definitions(-DVCAM_SUPPORTED)
|
||||
add_definitions(-DREPLAYBUFFER_SUPPORTED)
|
||||
endif()
|
||||
|
||||
# Platform specific settings
|
||||
if(APPLE)
|
||||
find_library(COCOA Cocoa)
|
||||
if(BUILD_OUT_OF_TREE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif()
|
||||
include_directories(${COCOA})
|
||||
find_library(COCOA Cocoa)
|
||||
if(BUILD_OUT_OF_TREE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif()
|
||||
include_directories(${COCOA})
|
||||
endif()
|
||||
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(X11 REQUIRED)
|
||||
link_libraries(${X11_LIBRARIES})
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
find_package(X11 REQUIRED COMPONENTS Xtst Xss)
|
||||
find_path(PROCPS_INCLUDE_DIR NAMES proc/procps.h)
|
||||
if(NOT PROCPS_INCLUDE_DIR)
|
||||
message(
|
||||
FATAL_ERROR "procps include dir not found - please set PROCPS_INCLUDE_DIR"
|
||||
)
|
||||
endif()
|
||||
find_library(PROCPS_LIBRARY NAMES procps)
|
||||
if(NOT PROCPS_LIBRARY)
|
||||
message(FATAL_ERROR "procps lib not found - please set PROCPS_LIBRARY")
|
||||
endif()
|
||||
link_libraries(${X11_LIBRARIES} ${procps_LIBRARIES})
|
||||
include_directories("${X11_INCLUDE_DIR}" "${X11_Xtst_INCLUDE_PATH}"
|
||||
"${X11_Xss_INCLUDE_PATH}" "${PROCPS_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
set(advanced-scene-switcher_HEADERS
|
||||
${advanced-scene-switcher_HEADERS}
|
||||
src/headers/advanced-scene-switcher.hpp
|
||||
src/headers/switcher-data-structs.hpp
|
||||
src/headers/utility.hpp
|
||||
src/headers/curl-helper.hpp
|
||||
src/headers/volume-control.hpp
|
||||
src/headers/switch-audio.hpp
|
||||
src/headers/switch-executable.hpp
|
||||
src/headers/switch-file.hpp
|
||||
src/headers/switch-idle.hpp
|
||||
src/headers/switch-media.hpp
|
||||
src/headers/switch-pause.hpp
|
||||
src/headers/switch-random.hpp
|
||||
src/headers/switch-screen-region.hpp
|
||||
src/headers/switch-time.hpp
|
||||
src/headers/switch-transitions.hpp
|
||||
src/headers/switch-window.hpp
|
||||
src/headers/switch-sequence.hpp
|
||||
src/headers/switch-generic.hpp
|
||||
src/headers/version.h
|
||||
)
|
||||
|
||||
set(advanced-scene-switcher_SOURCES
|
||||
${advanced-scene-switcher_SOURCES}
|
||||
src/advanced-scene-switcher.cpp
|
||||
src/advanced-scene-switcher-module.c
|
||||
src/switcher-data-structs.cpp
|
||||
src/switch-transitions.cpp
|
||||
src/switch-screen-region.cpp
|
||||
src/switch-priority.cpp
|
||||
src/switch-executable.cpp
|
||||
src/switch-idle.cpp
|
||||
src/switch-sequence.cpp
|
||||
src/switch-file.cpp
|
||||
src/switch-window.cpp
|
||||
src/switch-media.cpp
|
||||
src/hotkey.cpp
|
||||
src/general.cpp
|
||||
src/switch-pause.cpp
|
||||
src/switch-random.cpp
|
||||
src/switch-time.cpp
|
||||
src/switch-audio.cpp
|
||||
src/switch-generic.cpp
|
||||
src/curl-helper.cpp
|
||||
src/volume-control.cpp
|
||||
src/version.cpp
|
||||
)
|
||||
|
||||
set(advanced-scene-switcher_UI
|
||||
${advanced-scene-switcher_UI}
|
||||
forms/advanced-scene-switcher.ui
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/win/advanced-scene-switcher-win.cpp)
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/win/advanced-scene-switcher-win.cpp)
|
||||
elseif(APPLE)
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/osx/advanced-scene-switcher-osx.mm)
|
||||
set_source_files_properties(advanced-scene-switcher-osx.mm
|
||||
PROPERTIES COMPILE_FLAGS "-fobjc-arc")
|
||||
set(advanced-scene-switcher_PLATFORM_LIBS
|
||||
${COCOA})
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/osx/advanced-scene-switcher-osx.mm)
|
||||
set_source_files_properties(advanced-scene-switcher-osx.mm
|
||||
PROPERTIES COMPILE_FLAGS "-fobjc-arc")
|
||||
set(advanced-scene-switcher_PLATFORM_LIBS ${COCOA})
|
||||
else()
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/linux/advanced-scene-switcher-nix.cpp)
|
||||
set(advanced-scene-switcher_PLATFORM_LIBS
|
||||
Xss)
|
||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||
src/linux/advanced-scene-switcher-nix.cpp)
|
||||
set(advanced-scene-switcher_PLATFORM_LIBS Xss ${PROCPS_LIBRARY})
|
||||
endif()
|
||||
|
||||
qt5_wrap_ui(advanced-scene-switcher_UI_HEADERS
|
||||
${advanced-scene-switcher_UI}
|
||||
${advanced-scene-switcher_PLATFORM_UI})
|
||||
# asio and websocketpp
|
||||
add_definitions(-DASIO_STANDALONE)
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp")
|
||||
if(WIN32)
|
||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||
endif()
|
||||
|
||||
add_library(advanced-scene-switcher MODULE
|
||||
${advanced-scene-switcher_HEADERS}
|
||||
${advanced-scene-switcher_SOURCES}
|
||||
${advanced-scene-switcher_UI_HEADERS}
|
||||
${advanced-scene-switcher_PLATFORM_SOURCES}
|
||||
${advanced-scene-switcher_PLATFORM_HEADERS}
|
||||
)
|
||||
# Setup QT tools
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/forms")
|
||||
set(advanced-scene-switcher_UI ${advanced-scene-switcher_UI}
|
||||
forms/advanced-scene-switcher.ui)
|
||||
qt5_wrap_ui(advanced-scene-switcher_UI_HEADERS ${advanced-scene-switcher_UI}
|
||||
${advanced-scene-switcher_PLATFORM_UI})
|
||||
|
||||
# The plugin sources
|
||||
set(advanced-scene-switcher_HEADERS
|
||||
${advanced-scene-switcher_HEADERS}
|
||||
src/headers/advanced-scene-switcher.hpp
|
||||
src/headers/switcher-data-structs.hpp
|
||||
src/headers/scene-group.hpp
|
||||
src/headers/scene-trigger.hpp
|
||||
src/headers/switch-audio.hpp
|
||||
src/headers/switch-executable.hpp
|
||||
src/headers/switch-file.hpp
|
||||
src/headers/switch-idle.hpp
|
||||
src/headers/switch-media.hpp
|
||||
src/headers/switch-network.hpp
|
||||
src/headers/switch-pause.hpp
|
||||
src/headers/switch-random.hpp
|
||||
src/headers/switch-screen-region.hpp
|
||||
src/headers/switch-time.hpp
|
||||
src/headers/switch-transitions.hpp
|
||||
src/headers/switch-window.hpp
|
||||
src/headers/switch-sequence.hpp
|
||||
src/headers/switch-video.hpp
|
||||
src/headers/switch-generic.hpp
|
||||
src/headers/macro-action-edit.hpp
|
||||
src/headers/macro-action-audio.hpp
|
||||
src/headers/macro-action-file.hpp
|
||||
src/headers/macro-action-filter.hpp
|
||||
src/headers/macro-action-hotkey.hpp
|
||||
src/headers/macro-action-macro.hpp
|
||||
src/headers/macro-action-media.hpp
|
||||
src/headers/macro-action-plugin-state.hpp
|
||||
src/headers/macro-action-preview-scene.hpp
|
||||
src/headers/macro-action-random.hpp
|
||||
src/headers/macro-action-recording.hpp
|
||||
src/headers/macro-action-replay-buffer.hpp
|
||||
src/headers/macro-action-run.hpp
|
||||
src/headers/macro-action-scene-order.hpp
|
||||
src/headers/macro-action-scene-swap.hpp
|
||||
src/headers/macro-action-scene-switch.hpp
|
||||
src/headers/macro-action-scene-transform.hpp
|
||||
src/headers/macro-action-scene-visibility.hpp
|
||||
src/headers/macro-action-source.hpp
|
||||
src/headers/macro-action-streaming.hpp
|
||||
src/headers/macro-action-timer.hpp
|
||||
src/headers/macro-action-transition.hpp
|
||||
src/headers/macro-action-virtual-cam.hpp
|
||||
src/headers/macro-action-wait.hpp
|
||||
src/headers/macro-condition-edit.hpp
|
||||
src/headers/macro-condition-audio.hpp
|
||||
src/headers/macro-condition-cursor.hpp
|
||||
src/headers/macro-condition-date.hpp
|
||||
src/headers/macro-condition-file.hpp
|
||||
src/headers/macro-condition-filter.hpp
|
||||
src/headers/macro-condition-hotkey.hpp
|
||||
src/headers/macro-condition-idle.hpp
|
||||
src/headers/macro-condition-macro.hpp
|
||||
src/headers/macro-condition-media.hpp
|
||||
src/headers/macro-condition-plugin-state.hpp
|
||||
src/headers/macro-condition-process.hpp
|
||||
src/headers/macro-condition-recording.hpp
|
||||
src/headers/macro-condition-replay-buffer.hpp
|
||||
src/headers/macro-condition-scene-order.hpp
|
||||
src/headers/macro-condition-scene-transform.hpp
|
||||
src/headers/macro-condition-scene-visibility.hpp
|
||||
src/headers/macro-condition-scene.hpp
|
||||
src/headers/macro-condition-source.hpp
|
||||
src/headers/macro-condition-streaming.hpp
|
||||
src/headers/macro-condition-timer.hpp
|
||||
src/headers/macro-condition-transition.hpp
|
||||
src/headers/macro-condition-video.hpp
|
||||
src/headers/macro-condition-virtual-cam.hpp
|
||||
src/headers/macro-condition-window.hpp
|
||||
src/headers/macro.hpp
|
||||
src/headers/macro-controls.hpp
|
||||
src/headers/macro-segment.hpp
|
||||
src/headers/macro-selection.hpp
|
||||
src/headers/curl-helper.hpp
|
||||
src/headers/hotkey.hpp
|
||||
src/headers/scene-selection.hpp
|
||||
src/headers/screenshot-helper.hpp
|
||||
src/headers/transition-selection.hpp
|
||||
src/headers/name-dialog.hpp
|
||||
src/headers/duration-control.hpp
|
||||
src/headers/file-selection.hpp
|
||||
src/headers/section.hpp
|
||||
src/headers/platform-funcs.hpp
|
||||
src/headers/utility.hpp
|
||||
src/headers/volume-control.hpp
|
||||
src/headers/version.h)
|
||||
|
||||
set(advanced-scene-switcher_SOURCES
|
||||
${advanced-scene-switcher_SOURCES}
|
||||
src/advanced-scene-switcher.cpp
|
||||
src/advanced-scene-switcher-module.c
|
||||
src/switcher-data-structs.cpp
|
||||
src/scene-group.cpp
|
||||
src/scene-trigger.cpp
|
||||
src/switch-transitions.cpp
|
||||
src/switch-screen-region.cpp
|
||||
src/switch-priority.cpp
|
||||
src/switch-executable.cpp
|
||||
src/switch-idle.cpp
|
||||
src/switch-sequence.cpp
|
||||
src/switch-file.cpp
|
||||
src/switch-window.cpp
|
||||
src/switch-media.cpp
|
||||
src/switch-network.cpp
|
||||
src/file-selection.cpp
|
||||
src/hotkey.cpp
|
||||
src/general.cpp
|
||||
src/switch-pause.cpp
|
||||
src/switch-random.cpp
|
||||
src/switch-time.cpp
|
||||
src/switch-audio.cpp
|
||||
src/switch-video.cpp
|
||||
src/switch-generic.cpp
|
||||
src/macro-action-edit.cpp
|
||||
src/macro-action-audio.cpp
|
||||
src/macro-action-file.cpp
|
||||
src/macro-action-filter.cpp
|
||||
src/macro-action-hotkey.cpp
|
||||
src/macro-action-macro.cpp
|
||||
src/macro-action-media.cpp
|
||||
src/macro-action-plugin-state.cpp
|
||||
src/macro-action-preview-scene.cpp
|
||||
src/macro-action-random.cpp
|
||||
src/macro-action-recording.cpp
|
||||
src/macro-action-replay-buffer.cpp
|
||||
src/macro-action-run.cpp
|
||||
src/macro-action-scene-order.cpp
|
||||
src/macro-action-scene-swap.cpp
|
||||
src/macro-action-scene-switch.cpp
|
||||
src/macro-action-scene-transform.cpp
|
||||
src/macro-action-scene-visibility.cpp
|
||||
src/macro-action-source.cpp
|
||||
src/macro-action-streaming.cpp
|
||||
src/macro-action-timer.cpp
|
||||
src/macro-action-transition.cpp
|
||||
src/macro-action-virtual-cam.cpp
|
||||
src/macro-action-wait.cpp
|
||||
src/macro-condition-edit.cpp
|
||||
src/macro-condition-audio.cpp
|
||||
src/macro-condition-cursor.cpp
|
||||
src/macro-condition-date.cpp
|
||||
src/macro-condition-file.cpp
|
||||
src/macro-condition-filter.cpp
|
||||
src/macro-condition-hotkey.cpp
|
||||
src/macro-condition-idle.cpp
|
||||
src/macro-condition-macro.cpp
|
||||
src/macro-condition-media.cpp
|
||||
src/macro-condition-plugin-state.cpp
|
||||
src/macro-condition-process.cpp
|
||||
src/macro-condition-recording.cpp
|
||||
src/macro-condition-replay-buffer.cpp
|
||||
src/macro-condition-scene-order.cpp
|
||||
src/macro-condition-scene-transform.cpp
|
||||
src/macro-condition-scene-visibility.cpp
|
||||
src/macro-condition-scene.cpp
|
||||
src/macro-condition-source.cpp
|
||||
src/macro-condition-streaming.cpp
|
||||
src/macro-condition-timer.cpp
|
||||
src/macro-condition-transition.cpp
|
||||
src/macro-condition-video.cpp
|
||||
src/macro-condition-virtual-cam.cpp
|
||||
src/macro-condition-window.cpp
|
||||
src/macro.cpp
|
||||
src/macro-controls.cpp
|
||||
src/macro-segment.cpp
|
||||
src/macro-selection.cpp
|
||||
src/macro-tab.cpp
|
||||
src/curl-helper.cpp
|
||||
src/scene-selection.cpp
|
||||
src/screenshot-helper.cpp
|
||||
src/transition-selection.cpp
|
||||
src/name-dialog.cpp
|
||||
src/duration-control.cpp
|
||||
src/section.cpp
|
||||
src/utility.cpp
|
||||
src/volume-control.cpp
|
||||
src/version.cpp)
|
||||
|
||||
# opencv
|
||||
find_package(OpenCV)
|
||||
if(OpenCV_FOUND)
|
||||
include_directories("${OpenCV_INCLUDE_DIRS}")
|
||||
else()
|
||||
set(OpenCV_LIBRARIES "")
|
||||
message(
|
||||
WARNING
|
||||
"OpenCV not found! Functionality relying on OpenCV will be disabled!\nOpenCV sources are available under: ${CMAKE_CURRENT_SOURCE_DIR}/deps/opencv"
|
||||
)
|
||||
list(REMOVE_ITEM advanced-scene-switcher_SOURCES
|
||||
src/macro-condition-video.cpp)
|
||||
list(REMOVE_ITEM advanced-scene-switcher_HEADERS
|
||||
src/headers/macro-condition-video.hpp)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
advanced-scene-switcher MODULE
|
||||
${advanced-scene-switcher_HEADERS}
|
||||
${advanced-scene-switcher_SOURCES}
|
||||
${advanced-scene-switcher_UI_HEADERS}
|
||||
${advanced-scene-switcher_PLATFORM_SOURCES}
|
||||
${advanced-scene-switcher_PLATFORM_HEADERS})
|
||||
|
||||
# Out of tree build
|
||||
if(BUILD_OUT_OF_TREE)
|
||||
include_directories(
|
||||
"${LIBOBS_INCLUDE_DIRS}"
|
||||
"${LIBOBS_FRONTEND_INCLUDE_DIR}"
|
||||
${Qt5Core_INCLUDES}
|
||||
${Qt5Widgets_INCLUDES}
|
||||
${LIBCURL_INCLUDE_DIRS})
|
||||
target_link_libraries(
|
||||
advanced-scene-switcher
|
||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
${OpenCV_LIBRARIES}
|
||||
${LIBOBS_LIB}
|
||||
${LIBOBS_FRONTEND_API_LIB}
|
||||
Qt5::Core
|
||||
Qt5::Widgets)
|
||||
|
||||
target_link_libraries(advanced-scene-switcher
|
||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
${LIBOBS_LIB}
|
||||
${LIBOBS_FRONTEND_API_LIB}
|
||||
Qt5::Core
|
||||
Qt5::Widgets)
|
||||
# Additional commands to install the module in the correct place. Find all the
|
||||
# translation files so we can copy them to the correct place later on.
|
||||
file(GLOB ASS_TRANSLATION_FILES "data/locale/*.ini")
|
||||
|
||||
# Additional commands to install the module in the correct place.
|
||||
# Find all the translation files so we can copy them to the correct
|
||||
# place later on.
|
||||
file(GLOB ASS_TRANSLATION_FILES
|
||||
"data/locale/*.ini"
|
||||
)
|
||||
# OSX
|
||||
if(APPLE)
|
||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||
endif()
|
||||
|
||||
# Windows
|
||||
if(WIN32)
|
||||
string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
message("${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
||||
find_package(w32-pthreads REQUIRED)
|
||||
|
||||
target_link_libraries(advanced-scene-switcher
|
||||
w32-pthreads)
|
||||
endif()
|
||||
|
||||
# OSX
|
||||
if(APPLE)
|
||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||
endif()
|
||||
|
||||
# Linux
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(CMAKE_C_FLAGS "-Wall -Wextra -Wvla -Wno-unused-function -Werror-implicit-function-declaration -Wno-missing-braces -Wno-missing-field-initializers ${CMAKE_C_FLAGS} -std=c99 -fno-strict-aliasing")
|
||||
|
||||
if(ARCH EQUAL 64)
|
||||
set(ARCH_NAME "x86_64")
|
||||
else()
|
||||
set(ARCH_NAME "i686")
|
||||
endif()
|
||||
|
||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||
|
||||
install(TARGETS advanced-scene-switcher
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/obs-plugins)
|
||||
install(FILES ${ASS_TRANSLATION_FILES}
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/obs/obs-plugins/advanced-scene-switcher/locale")
|
||||
endif()
|
||||
# Linux
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(NOT LIB_OUT_DIR)
|
||||
set(LIB_OUT_DIR "/lib/obs-plugins")
|
||||
endif()
|
||||
if(NOT DATA_OUT_DIR)
|
||||
set(DATA_OUT_DIR "/share/obs/obs-plugins/advanced-scene-switcher")
|
||||
endif()
|
||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||
install(TARGETS advanced-scene-switcher
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_OUT_DIR})
|
||||
install(DIRECTORY data/locale
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/${DATA_OUT_DIR})
|
||||
install(DIRECTORY data/res
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/${DATA_OUT_DIR})
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(advanced-scene-switcher
|
||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
obs-frontend-api
|
||||
Qt5::Widgets
|
||||
libobs)
|
||||
|
||||
install_obs_plugin_with_data(advanced-scene-switcher data)
|
||||
# In tree build
|
||||
target_link_libraries(
|
||||
advanced-scene-switcher ${advanced-scene-switcher_PLATFORM_LIBS}
|
||||
${OpenCV_LIBRARIES} obs-frontend-api Qt5::Widgets libobs)
|
||||
install_obs_plugin_with_data(advanced-scene-switcher data)
|
||||
endif()
|
||||
|
||||
128
README.md
128
README.md
@@ -1,119 +1,27 @@
|
||||
# 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/.
|
||||
|
||||
## Compiling in tree (recommended)
|
||||
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
|
||||
## Downloads
|
||||
|
||||
Binaries for Windows, MacOS, and Linux are available in the [Releases](https://github.com/WarmUpTill/SceneSwitcher/releases) section.
|
||||
|
||||
## Installing the plugin
|
||||
|
||||
For the Windows and MacOS platforms, it is recommended to run the provided installers.
|
||||
|
||||
For Linux the Snap package manager offers an OBS Studio installation which is bundled with the plugin:
|
||||
```
|
||||
cd obs-studio/UI/frontend-plugins/
|
||||
git clone https://github.com/WarmUpTill/SceneSwitcher.git
|
||||
sudo snap install obs-studio
|
||||
```
|
||||
|
||||
Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt file and add an entry for the scene switcher:
|
||||
add_subdirectory(SceneSwitcher)
|
||||
If that is not an option you will have to ...
|
||||
1. Copy the library to the plugins folder of you obs installation.
|
||||
2. Copy the contents of the data directory to its respective folders of your obs installation.
|
||||
|
||||
## Compiling out of tree
|
||||
### Prerequisites
|
||||
You'll need CMake and a working development environment for OBS Studio installed
|
||||
on your computer. Once you've done that, do the following:
|
||||
```
|
||||
git clone https://github.com/WarmUpTill/SceneSwitcher.git
|
||||
cd SceneSwitcher
|
||||
mkdir build && cd build
|
||||
```
|
||||
Unfortunately the exact location of these folders may vary from system to system.
|
||||
|
||||
### Windows
|
||||
In cmake-gui, you'll have to set these CMake variables :
|
||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||
code of OBS Studio, located at [source_directory]/libobs/.
|
||||
- **LIBOBS_LIB** (filepath) : location of the obs.dll file (usually set to
|
||||
C:\Program Files\obs-studio\bin\64bit\obs.dll)
|
||||
## Compiling the plugin
|
||||
|
||||
Assuming that you installed Qt via the regular Qt App way:
|
||||
- **Qt5Core_DIR** (path) : C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Core
|
||||
- **Qt5Gui_DIR** (path): C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Gui
|
||||
- **Qt5Widgets_DIR** (path) : C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Widgets
|
||||
|
||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.dll
|
||||
file, usually C:/Program Files/obs-studio/bin/64bit/obs-frontend-api.dll
|
||||
(usually in the same place as LIBOBS_LIB)
|
||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
||||
subfolder in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
||||
|
||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||
|
||||
### Linux
|
||||
Most versions of Linux you can use cmake-gui or the command line.
|
||||
|
||||
**For the command line:**
|
||||
```
|
||||
cmake -DBUILD_OUT_OF_TREE=1 -DLIBOBS_INCLUDE_DIR="<path to the libobs/ sub-folder in obs-studio's source code>" \
|
||||
-DLIBOBS_FRONTEND_INCLUDE_DIR="<path to the UI/obs-frontend-api/ sub-folder in obs-studio's source code>" \
|
||||
-DLIBOBS_LIB="<path to the libobs.so file>" \
|
||||
-DLIBOBS_FRONTEND_API_LIB="<path to the libobs-frontend-api.so file (usually in the same place as LIBOBS_LIB)>" \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
|
||||
For cmake-gui you'll have to set the following variables:
|
||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||
code of OBS Studio, located at [source_directory]/libobs/.
|
||||
- **LIBOBS_LIB** (filepath) : location of the libobs.so file (usually CMake finds
|
||||
this, but if not it'll usually be in /usr/lib/libobs.so)
|
||||
|
||||
Assuming that you installed Qt via your system package manager, it should be
|
||||
found automatically. If not, then usually you'll find it in something like:
|
||||
- **Qt5Core_DIR** (path) : /usr/lib64/cmake/Qt5Core
|
||||
- **Qt5Gui_DIR** (path): /usr/lib64/cmake/Qt5Gui
|
||||
- **Qt5Widgets_DIR** (path) : /usr/lib64/cmake/Qt5Widgets
|
||||
|
||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.so
|
||||
file (usually in the same place as LIBOBS_LIB)
|
||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
||||
subfolder in the source code of OBS Studio, located at
|
||||
[source_directory]/UI/obs-frontend-api.
|
||||
|
||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||
|
||||
Then open a terminal in the build folder and type:
|
||||
```
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
NOTE: The Linux version of this plugin is dependent on libXScrnSaver.
|
||||
|
||||
### OS X
|
||||
In cmake-gui, you'll have to set these CMake variables :
|
||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||
code of OBS Studio, located at [source_directory]/libobs/.
|
||||
- **LIBOBS_LIB** (filepath) : location of the libobs.0.dylib file (usually
|
||||
in /Applications/OBS.app/Contents/Resources/bin/libobs.0.dylib)
|
||||
|
||||
Assuming that you installed Qt via the regular Qt App way:
|
||||
- **Qt5Core_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Core
|
||||
- **Qt5Widgets_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Widgets
|
||||
- **Qt5MacExtras_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5MacExtras
|
||||
|
||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.0.dylib
|
||||
file (usually in usually in /Applications/OBS.app/Contents/Resources/bin/libobs-frontend-api.0.dylib)
|
||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api subfolder
|
||||
in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
||||
|
||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||
|
||||
Open xcode (or a terminal, depending on the build type you chose), build and copy
|
||||
the advanced-scene-switcher.so file to /Applications/OBS.app/Contents/PlugIns
|
||||
|
||||
Note that you might have to adjust the library search paths using the install_name_tool if you want the plugin to run on machines other than your build machine:
|
||||
```
|
||||
install_name_tool -change @rpath/libobs-frontend-api.dylib @executable_path/../Frameworks/libobs-frontend-api.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change /usr/local/opt/qt5/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change /usr/local/opt/qt5/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
install_name_tool -change /usr/local/opt/qt5/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||
```
|
||||
See the [build instructions](BUILDING.md).
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include "src/headers/version.h"
|
||||
#define GIT_SHA1 "@GIT_SHA1@"
|
||||
const char g_GIT_SHA1[] = GIT_SHA1;
|
||||
#define GIT_TAG "@GIT_TAG@"
|
||||
const char g_GIT_SHA1[] = GIT_SHA1;
|
||||
const char g_GIT_TAG[] = GIT_TAG;
|
||||
@@ -6,26 +6,28 @@ AdvSceneSwitcher.generalTab.title="Allgemein"
|
||||
AdvSceneSwitcher.generalTab.status="Status"
|
||||
AdvSceneSwitcher.generalTab.status.hotkeytips="Hotkeys können in den OBS Einstellungen konfiguriert werden"
|
||||
AdvSceneSwitcher.generalTab.status.currentStatus="Erweiterter Automatischer Szenenwechsler ist:"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup="Beim Start:"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup="Beim Start von OBS:"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="Aktiviere den Szenenwechsler wenn er aktiv war"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Aktiviere den Szenenwechsler"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Aktiviere den Szenenwechsler nicht"
|
||||
AdvSceneSwitcher.generalTab.status.start="Start"
|
||||
AdvSceneSwitcher.generalTab.status.stop="Stop"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart="Starte auotmatischen den Szenenwechsler beim:"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Niemals"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Aufnehmen"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streamen"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Aufnehmen oder Streamen"
|
||||
AdvSceneSwitcher.generalTab.status.checkInterval="Teste Bedingungen alle"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior="Allgemeines Verhalten"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.recording="Aufnehmen"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.streaming="Streamen"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.recordingAndStreaming="Aufnehmen und Streamen"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart1="Starte"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart2=" auf Szene"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="Wenn keine Bedingung erfüllt ist für "
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Kann nur so genau sein wie das eingestellte Interval zum Testen der Bedingungen."
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Nicht wechseln"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Wechsle zu einer Szene auf dem Zufall-Tab"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Wechsle zu:"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="Nach einem automatisierten Szenenwechsel wechsle nicht mehr für"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="In diesem Zeitraum werden potentielle erfüllte Bedingungen ignoriert!"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Ausführliches Logging"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStop="Stoppe Streamen/Aufnehmen auf Szene"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Fensterposition und -größe speichern"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Deaktiviere UI Tipps"
|
||||
AdvSceneSwitcher.generalTab.priority="Priorität"
|
||||
AdvSceneSwitcher.generalTab.priority.description="Szenenwechselmethoden sortiert nach Priorität"
|
||||
@@ -43,20 +45,27 @@ AdvSceneSwitcher.generalTab.priority.fileContent="Datei Inhalt"
|
||||
AdvSceneSwitcher.generalTab.priority.sceneSequence="Szenenfolge"
|
||||
AdvSceneSwitcher.generalTab.priority.idleDetection="Inaktivitätserkennung"
|
||||
AdvSceneSwitcher.generalTab.priority.executable="Prozess"
|
||||
AdvSceneSwitcher.generalTab.priority.screenRegion="Bildschrimbereich"
|
||||
AdvSceneSwitcher.generalTab.priority.screenRegion="Bildschirmbereich"
|
||||
AdvSceneSwitcher.generalTab.priority.windowTitle="Fenstername"
|
||||
AdvSceneSwitcher.generalTab.priority.media="Medien"
|
||||
AdvSceneSwitcher.generalTab.priority.time="Zeit"
|
||||
AdvSceneSwitcher.generalTab.priority.audio="Audio"
|
||||
AdvSceneSwitcher.generalTab.priority.video="Video"
|
||||
|
||||
; Transition Tab
|
||||
AdvSceneSwitcher.transitionTab.title="Szenenübergänge"
|
||||
AdvSceneSwitcher.transitionTab.transitionOverride="Szenenübergänge, die im Szenenwechsler konfiguriert werden, haben Vorrang vor Übergangsüberschreibung"
|
||||
AdvSceneSwitcher.transitionTab.setTransitionBy="Beim Ändern des Szenenübergangs:"
|
||||
AdvSceneSwitcher.transitionTab.transitionOverride="Verwende Übergangsüberschreibungen"
|
||||
AdvSceneSwitcher.transitionTab.adjustActiveTransitionType="Wechsle den aktiven Szenenübergangtyp"
|
||||
AdvSceneSwitcher.transitionTab.transitionBehaviorSelectionError="Mindestens eine Option muss aktiv sein:\n\n - Verwende Übergangsüberschreibungen\n\n - Wechsle den aktiven Szenenübergangtyp"
|
||||
AdvSceneSwitcher.transitionTab.transitionForAToB="Szenenübergänge für automatisierte Szenenwechsel von Szene A zu Szene B"
|
||||
AdvSceneSwitcher.transitionTab.transitionForAToB.description="<html><head/><body><p>Diese Einstellungen beeinflussen <span style=\"font-style:italic;\">nur</span> vom Szenenwechsler ausgelöste Szenenübergänge - Siehe <a href=\"https://obsproject.com/forum/resources/obs-transition-matrix.751/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Matrix</span></a> um alle zu konfigurieren.<br/>Einstellungen auf diesem Tab haben Vorrang vor denen welche auf den übrigen Tabs konfiguriert wurden.</p></body></html>"
|
||||
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>Diese Einstellungen beeinflussen <span style=\"font-style:italic;\">nur</span> vom Szenenwechsler ausgelöste Szenenübergänge - Siehe <a href=\"https://obsproject.com/forum/resources/transition-table.1174/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Table</span></a> um auch manuelle Szenenübergänge zu konfigurieren.<br/>Einstellungen auf diesem Tab haben Vorrang, vor denen welche auf den übrigen Tabs konfiguriert wurden.<br/><br/>Klicke auf das Plus Symbol, um einen neuen Eintrag hinzuzufügen.</p></body></html>"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition="Ändere den Szenenübergang wenn eine Szene aktiv ist"
|
||||
AdvSceneSwitcher.transitionTab.entry="Wechsle von {{scenes}} zu {{scenes2}} mit {{transitions}}"
|
||||
AdvSceneSwitcher.transitionTab.entry="Wechsle von {{scenes}} zu {{scenes2}} mit {{transitions}} mit einer Dauer von {{duration}}"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransitionEntry="Wenn {{scenes}} aktiv ist ändere den Szenenübergang zu {{transitions}}"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransitionsHelp="Klicke auf das Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition.delay="Wechsle Szenenübergang {{defTransitionDelay}} nach Szenenwechsel."
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition.delay.help="Diese Verzögerung dient dazu Szenenwechsel zu unterbrechen.\nDies kann passieren, wenn der Szenenübergangtyp gewechselt wird während ein Szenenübergang grade noch im Gang ist."
|
||||
|
||||
; Pause Scenes Tab
|
||||
AdvSceneSwitcher.pauseTab.title="Pause"
|
||||
@@ -67,6 +76,7 @@ AdvSceneSwitcher.pauseTab.pauseTypeScene="Szene aktiv ist"
|
||||
AdvSceneSwitcher.pauseTab.pauseTypeWindow="Fenster im Fokus ist"
|
||||
AdvSceneSwitcher.pauseTab.pauseTargetAll="alle"
|
||||
AdvSceneSwitcher.pauseTab.pauseEntry="Pausiere {{pauseTargets}} Überprüfungen wenn {{scenes}} {{windows}} {{pauseTypes}}"
|
||||
AdvSceneSwitcher.pauseTab.help="Auf diesem Tab können einzelne Szenenwechselmethoden pausiert werden, wenn eine Szene aktiv oder ein Fenster im Fokus ist.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
|
||||
; Window Title Tab
|
||||
AdvSceneSwitcher.windowTitleTab.title="Fenstername"
|
||||
@@ -77,19 +87,24 @@ AdvSceneSwitcher.windowTitleTab.fullscreen="wenn Vollbild"
|
||||
AdvSceneSwitcher.windowTitleTab.maximized="wenn maximiert"
|
||||
AdvSceneSwitcher.windowTitleTab.focused="wenn fokussiert"
|
||||
AdvSceneSwitcher.windowTitleTab.entry="{{windows}} {{scenes}} {{transitions}} {{fullscreen}} {{maximized}} {{focused}}"
|
||||
AdvSceneSwitcher.windowTitleTab.windowsHelp="Wechsle Szenen basiert auf dem Fensternamen eines laufenden Prozesses.\nFolgende zusätzliche Bedingungen können ausgewählt werden:\nDas Fenster ist im Vollbildmodus\nDas Fenster ist maximiert\nDas Fenster ist fokussiert\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
AdvSceneSwitcher.windowTitleTab.ignoreWindowsHelp="Ist ein Fenstername ignoriert so verhält sich der Szenenwechsler als ob das vorhergehende Fenster immer noch fokussiert ist.\nDies kann in Situationen nützlich sein, in den oft zwischen Fenster gewechselt wird, dies aber nicht immer einen Szenenwechsel auslösen soll.\n\nWähle oben ein Fenster aus oder gib einen Fensternamen ein und klicke auf das Plus Symbol um es zur Liste hinzuzufügen."
|
||||
|
||||
; Executable Tab
|
||||
AdvSceneSwitcher.executableTab.title="Prozess"
|
||||
AdvSceneSwitcher.executableTab.implemented="Implementiert von dasOven"
|
||||
AdvSceneSwitcher.executableTab.requiresFocus="nur wenn dieser fokussiert ist"
|
||||
AdvSceneSwitcher.executableTab.entry="Wenn {{processes}} läuft wechsle zu {{scenes}} mit {{transitions}} {{requiresFocus}}"
|
||||
AdvSceneSwitcher.executableTab.help="Dieser Tab erlaubt es Szenen zu wechseln, wenn bestimmte Prozesse laufen.\nDas kann nützlich sein, wenn sich der Name eines Fensters ändern kann oder dieser nicht bekannt ist.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
|
||||
; Screen Region Tab
|
||||
AdvSceneSwitcher.screenRegionTab.title="Bildschrimbereich"
|
||||
AdvSceneSwitcher.screenRegionTab.title="Bildschirmbereich"
|
||||
AdvSceneSwitcher.screenRegionTab.currentPosition="Mauszeiger ist bei:"
|
||||
AdvSceneSwitcher.screenRegionTab.showGuideFrames="Hilfsrahmen einblenden"
|
||||
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="Hilfsrahmen ausblenden"
|
||||
AdvSceneSwitcher.screenRegionTab.entry="Wenn der Mauszeiger in {{minX}} {{minY}} x {{maxX}} {{maxY}} ist wechsle zu {{scenes}} mit {{transitions}}"
|
||||
AdvSceneSwitcher.screenRegionTab.excludeScenes.None="Keine Auswahl"
|
||||
AdvSceneSwitcher.screenRegionTab.entry="Wenn der Mauszeiger in {{minX}} {{minY}} x {{maxX}} {{maxY}} ist wechsle zu {{scenes}} mit {{transitions}} außer wenn auf {{excludeScenes}}"
|
||||
AdvSceneSwitcher.screenRegionTab.help="Dieser Tab ermöglicht es basierend auf der Position des Mauszeigers Szenen zu wechseln.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
|
||||
; Media Tab
|
||||
AdvSceneSwitcher.mediaTab.title="Medien"
|
||||
@@ -110,6 +125,7 @@ AdvSceneSwitcher.mediaTab.timeRestriction.longer="Dauer länger"
|
||||
AdvSceneSwitcher.mediaTab.timeRestriction.remainShorter="übrige Zeit kürzer"
|
||||
AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger="übrige Zeit länger"
|
||||
AdvSceneSwitcher.mediaTab.entry="Wenn {{mediaSources}} im Status {{states}} ist und{{timeRestrictions}} {{time}} ist wechsle zu {{scenes}} mit {{transitions}}"
|
||||
AdvSceneSwitcher.mediaTab.help="Dieser Tab ermöglicht es basieren auf dem Status von Medienquellen Szenen zu wechseln.\nZum Beispiel kann automatisch zur vorhergehenden Szene gewechselt werden, sobald sich eine Medienquelle im Status Beendet befindet.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
|
||||
; File Tab
|
||||
AdvSceneSwitcher.fileTab.title="Datei Inhalt"
|
||||
@@ -134,11 +150,13 @@ AdvSceneSwitcher.fileTab.checkfileContent="nur wenn sich der Inhalt geänder hat
|
||||
AdvSceneSwitcher.fileTab.entry="Wechsle zu {{scenes}} mit {{transitions}} wenn der Inhalt von {{fileType}} {{filePath}} {{browseButton}} passt zu:"
|
||||
AdvSceneSwitcher.fileTab.entry2="{{matchText}}"
|
||||
AdvSceneSwitcher.fileTab.entry3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.fileTab.help="Dieser Tab erlaubt es Szenen zu wechseln basierend auf dem Inhalt von lokalen oder remote Dateien.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
|
||||
; Random Tab
|
||||
AdvSceneSwitcher.randomTab.title="Zufall"
|
||||
AdvSceneSwitcher.randomTab.randomDisabledWarning="Funktionalität deaktiviert - Um diese zu aktivieren wähle \"Wenn keine Bedingung erfüllt ist wechsle zu einer Szene auf dem Zufall-Tab\" auf dem Allgemein-Tab aus"
|
||||
AdvSceneSwitcher.randomTab.entry="Wenn keine Bedingung erfüllt ist wechsle zu {{scenes}} mit {{transitions}} für {{delay}}"
|
||||
AdvSceneSwitcher.randomTab.help="Der Szenenwechsler wählt zufällig einen Eintrag auf diesem Tab aus, zu dem er für die angegebene Zeit wechseln wird.\nDer gleiche Eintrag wird nicht zweimal nacheinander ausgewählt werden.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
|
||||
; Time Tab
|
||||
AdvSceneSwitcher.timeTab.title="Zeit"
|
||||
@@ -153,15 +171,12 @@ AdvSceneSwitcher.timeTab.sundays="Sonntags"
|
||||
AdvSceneSwitcher.timeTab.afterstart="Nach Streamen-/Aufnehmenstart"
|
||||
AdvSceneSwitcher.timeTab.afterstart.tip="Hier wird die Zeit relativ zum Starten des Streamen/Aufnehmen gemessen"
|
||||
AdvSceneSwitcher.timeTab.entry="{{triggers}} um {{time}} wechsle zu {{scenes}} mit {{transitions}}"
|
||||
AdvSceneSwitcher.timeTab.help="Dieser Tab ermöglicht es Szenen basierend auf der aktuellen Uhrzeit zu wechseln.\n\nDer Szenenwechsler versucht den Szenenwechsel nur zur eingestellten Uhrzeit auszulösen.\nBeachte, dass die Prioritätseinstellungen auf dem Allgemein Tab entsprechend konfiguriert sind, sodass keine andere Szenenwechselmethode hier konfiguriert Einstellungen zur gegebenen Uhrzeit übertrifft.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
|
||||
; Idle Tab
|
||||
AdvSceneSwitcher.idleTab.title="Inaktivitätserkennung"
|
||||
AdvSceneSwitcher.idleTab.enable="Aktiviere Inaktivitätserkennung"
|
||||
AdvSceneSwitcher.idleTab.condition1="Nach "
|
||||
AdvSceneSwitcher.idleTab.condition2="ohne Keyboard- oder Mauseingaben"
|
||||
AdvSceneSwitcher.idleTab.switchToScene="wechsle zu Szene"
|
||||
AdvSceneSwitcher.idleTab.usingTransition1="mit"
|
||||
AdvSceneSwitcher.idleTab.usingTransition2=" "
|
||||
AdvSceneSwitcher.idleTab.idleswitch="After {{duration}} ohne Keyboard- oder Mauseingaben wechsle zu {{scenes}} mit {{transitions}}"
|
||||
AdvSceneSwitcher.idleTab.dontSwitchIfFocus1="Wechsle nicht wenn"
|
||||
AdvSceneSwitcher.idleTab.dontSwitchIfFocus2="im Fokus ist"
|
||||
|
||||
@@ -175,27 +190,123 @@ AdvSceneSwitcher.sceneSequenceTab.loadTitle="Wähle eine Datei aus von der Szene
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadFail="Laden der Einstellungen ist fehlgeschlagen!"
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Laden der Einstellungen war erfolgreich!"
|
||||
AdvSceneSwitcher.sceneSequenceTab.fileType="Text Dateien (*.txt)"
|
||||
AdvSceneSwitcher.sceneSequenceTab.entry="Wenn {{startScenes}} aktiv ist wechsle zu {{scenes}} nach {{delay}} {{delayUnits}} mit {{transitions}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.interruptible="kann unterbrochen werden"
|
||||
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Andere Szenenwechselmethoden können diese Sequenz unterbrechen"
|
||||
AdvSceneSwitcher.sceneSequenceTab.extendEdit="Szenenfolge erweitern"
|
||||
AdvSceneSwitcher.sceneSequenceTab.extendEntry="Nach {{delay}} wechsle zu {{scenes}} mit {{transitions}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.entry="Wenn {{startScenes}} aktiv ist wechsle zu {{scenes}} nach {{delay}} mit {{transitions}} {{interruptible}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.help="Dieser Tab ermöglicht es automatisiert zu einer anderen Szene zu wechseln, nachdem eine Szene für die konfigurierte Zeit aktiv war.\nZum Beispiel kann so automatisch zwischen zwei Szenen hin und her gewechselt werden.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
|
||||
; Audio Tab
|
||||
AdvSceneSwitcher.audioTab.title="Audio"
|
||||
AdvSceneSwitcher.audioTab.condition.above="über"
|
||||
AdvSceneSwitcher.audioTab.condition.below="unter"
|
||||
AdvSceneSwitcher.audioTab.entry="Wenn die Lautstärke von {{audioSources}} {{condition}} {{volumeWidget}} ist für {{duration}} wechsle zu {{scenes}} mit {{transitions}}"
|
||||
AdvSceneSwitcher.audioTab.ignoreInactiveSource="außer Audio Quelle ist inaktiv"
|
||||
AdvSceneSwitcher.audioTab.entry="Wenn die Lautstärke von {{audioSources}} {{condition}} {{volumeWidget}} ist für {{duration}} Sekunden wechsle zu {{scenes}} mit {{transitions}} {{ignoreInactiveSource}}"
|
||||
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="Wenn mehrere Einträge zutreffen ..."
|
||||
AdvSceneSwitcher.audioTab.multiMatchfallback="... für {{duration}} Sekunden wechsle zu {{scenes}} mit {{transitions}}"
|
||||
AdvSceneSwitcher.audioTab.help="Dieser Tab ermöglicht es basierend auf der Lautstärke von Audioquellen Szenen zu wechseln.\nSo kann zum Beispiel automatisch zu einer Szene gewechselt werden, wenn die Lautstärke eines Mikrofons eine konfigurierte Schwelle überschreitet.\n\nKlicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen."
|
||||
|
||||
; Video Tab
|
||||
AdvSceneSwitcher.videoTab.title="Video"
|
||||
AdvSceneSwitcher.videoTab.getScreenshot="Screenshot für ausgewählten Eintrag erstellen"
|
||||
AdvSceneSwitcher.videoTab.getScreenshotHelp="Erstellt einen Screenshot für die Video Quelle des ausgewählten Eintrag und setzt diesen als Ziel Bild"
|
||||
AdvSceneSwitcher.videoTab.condition.match="genau übereinstimmt mit"
|
||||
AdvSceneSwitcher.videoTab.condition.match.tooltip="Eine genaue Übereinstimmung setzt voraus, dass sowohl Zielquelle als auch das Bild die gleiche Auflösung besitzen.\nZusätzlich muss jeder einzelne Pixel zwischen beiden Bildquellen übereinstimmen weshalb Bildformate, welche das Bild komprimieren (z. B. .JPG) nicht zu empfehlen sind."
|
||||
AdvSceneSwitcher.videoTab.condition.differ="nicht übereinstimmt mit"
|
||||
AdvSceneSwitcher.videoTab.condition.hasNotChanged="sich nicht verändert"
|
||||
AdvSceneSwitcher.videoTab.condition.hasNotChanged="sich verändert"
|
||||
AdvSceneSwitcher.videoTab.ignoreInactiveSource="außer Video Quelle ist inaktiv"
|
||||
AdvSceneSwitcher.videoTab.entry="Wenn {{videoSources}} {{condition}} {{filePath}} {{browseButton}} für {{duration}} wechsle zu {{scenes}} mit {{transitions}} {{ignoreInactiveSource}}"
|
||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Dieser Tab ermöglicht es basierend auf der Videoausgabe von Quellen scenen zu wechseln.<br/>Für eine noch bessere Implementierung dieser Funktionalität siehe <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a>.<br/><br/>Klicke auf das markierte Plus Symbol, um einen neuen Eintrag hinzuzufügen..</p></body></html>"
|
||||
|
||||
; Network Tab
|
||||
AdvSceneSwitcher.networkTab.title="Netzwerk"
|
||||
AdvSceneSwitcher.networkTab.warning="Die Verwendung des Servers außerhalb eines lokalen Netzwerks kann dazu führen, dass die aktive Szene von dritten Personen ausgelesen werden kann."
|
||||
AdvSceneSwitcher.networkTab.Disabledwarning="Diese Funktionalität musste unter macOS leider aufgrund von Bibliotheksinkompatibilitäten mit dem obs-websocket plugin deaktiviert werden."
|
||||
AdvSceneSwitcher.networkTab.server="Server starten (Sendet Szenenwechselnachrichten zu allen verbundenen Clients)"
|
||||
AdvSceneSwitcher.networkTab.server.port="Port"
|
||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Nur IPv4 verwenden (deaktiviert IPv6)"
|
||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="Sende Nachrichten für Szenenwechsel"
|
||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Sende nur Szenenwechselnachrichten für automatisierte Szenenwechsel"
|
||||
AdvSceneSwitcher.networkTab.server.sendPreview="Sende Nachrichten für Vorschau Szenenwechsel im Studio-Modus"
|
||||
AdvSceneSwitcher.networkTab.startFailed.message="Der WebSocket-Server konnte nicht gestartet werden, mögliche Gründe:\n - Der TCP-Port %1 wird möglicherweise gerade von einem anderen Programm verwendet. Versuchen Sie einen anderen Port in den Websocket-Servereinstellungen zu setzen oder alle Programme zu beenden, die den Port möglicherweise verwenden.\n - Fehler: %2"
|
||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="Aktueller Status"
|
||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Nicht gestartet"
|
||||
AdvSceneSwitcher.networkTab.server.status.starting="Startet"
|
||||
AdvSceneSwitcher.networkTab.server.status.running="Server läuft"
|
||||
AdvSceneSwitcher.networkTab.server.restart="Server neu starten"
|
||||
AdvSceneSwitcher.networkTab.client="Client starten (Empfängt Szenenwechselnachrichten )"
|
||||
AdvSceneSwitcher.networkTab.client.address="Hostname oder IP-Adresse"
|
||||
AdvSceneSwitcher.networkTab.client.port="Port"
|
||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="Aktueller status"
|
||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Verbindung getrennt"
|
||||
AdvSceneSwitcher.networkTab.client.status.connecting="Verbinde"
|
||||
AdvSceneSwitcher.networkTab.client.status.connected="Verbunden"
|
||||
AdvSceneSwitcher.networkTab.client.reconnect="Erneutes Verbinden erzwingen"
|
||||
|
||||
; Scene Group Tab
|
||||
AdvSceneSwitcher.sceneGroupTab.title="Szenengruppe"
|
||||
AdvSceneSwitcher.sceneGroupTab.list="Szenengruppen"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit="Szenengruppe bearbeiten"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.name="Name:"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.type="Typ: {{type}}"
|
||||
AdvSceneSwitcher.sceneGroupTab.type.count="Anzahl"
|
||||
AdvSceneSwitcher.sceneGroupTab.type.time="Zeit"
|
||||
AdvSceneSwitcher.sceneGroupTab.type.random="Zufall"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.count="Schreite zur nächsten Szene in dieser Gruppe fort nach {{count}} Szenewechseln"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.time="Schreite zur nächsten Szene in dieser Gruppe fort nach {{time}}"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.random="Wähle eine zufällig Szene in der Liste aus"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.repeat="Beginne von vorne wenn Ende der Szenenliste erreicht ist"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.addScene="Szene hinzufügen"
|
||||
AdvSceneSwitcher.sceneGroupTab.add="Szenengruppe hinzufügen"
|
||||
AdvSceneSwitcher.sceneGroupTab.defaultname="Szenengruppe %1"
|
||||
AdvSceneSwitcher.sceneGroupTab.exists="Szenengruppen- oder Szenenname existiert bereits"
|
||||
AdvSceneSwitcher.sceneGroupTab.help="Szenengruppen können, genau wie reguläre Szenen, als Ziel eines Szenenwechsler Eintrags ausgewählt werden.\n\nSzenengruppen bestehen aus einer Liste von Szenen.\nDie aktive Szene der Szenengruppe schreitet abhängig von den konfigurierten Einstellungen durch die Liste der zugewiesenen Szenen fort.\n\nMögliche Einstellungen zum Fortschreiten der aktiven Szene sind:\nAnzahl der Szenenwechsel.\nZeit seit dem letzten Szenenwechsel in der Szenengruppe.\nOder zufällig.\n\nSo kann zum Beispiel eine Szenengruppe welche die folgenden Szenen enthält ...\nSzene 1\nSzene 2\nSzene 3 \n... beim erstem Mal zu \"Szene 1\" wechseln.\nBeim zweiten Mal zu \"Szene 2\".\nDie restlichem Male wechselt die Szenengruppe zu \"Szene 3\".\n\nKlicke auf das markierte Plus Symbol, um eine neuen Szenengruppe hinzuzufügen."
|
||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Wähle die Szenengruppe, die du bearbeiten möchtest, auf der linken Seite aus.\n\nWähle oben eine Szene aus, die du zur Szenengruppe hinzufügen möchtest, und klicke das Plus Symbol.\n\nDie gleiche Szene kann mehrfach in derselben Szenengruppe auftauchen."
|
||||
|
||||
; Scene Trigger Tab
|
||||
AdvSceneSwitcher.sceneTriggerTab.title="Szenen Trigger"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--Trigger auswählen--"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="aktiv ist"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="nicht aktiv ist"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="verlassen wird"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--Aktion auswählen--"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="Aufnahme starten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="Aufnahme pausieren"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="Aufnahme fortsetzen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="Aufnahme stoppen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="Streamen stoppen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="Streamen starten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="Replay Buffer starten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="Replay Buffer stoppen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="Audio Quelle stumm schalten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="Audio Quelle aktiv schalten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="Szenenwechsler starten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="Szenenwechsler stoppen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="Virtuelle Kamera starten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Virtuelle Kamera stoppen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.entry="Wenn {{scenes}} {{triggers}} {{actions}} {{audioSources}} nach {{duration}} "
|
||||
AdvSceneSwitcher.sceneTriggerTab.help="Dieser Tab ermöglicht es automatisiert Handlungen, wie etwa das Stoppen von einer Aufnahme oder des Streamens, bei einem Szenenwechsel auszuführen."
|
||||
|
||||
|
||||
; Hotkey
|
||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Starte den Erweiteren Szenenwechsler"
|
||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stoppe den Erweiteren Szenenwechsler"
|
||||
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Starte/Stoppe den Erweiteren Szenenwechsler"
|
||||
|
||||
AdvSceneSwitcher.askBackup="Neue Version des Erweiterten Automatischen Szenenwechslers wurde erkannt.\nSoll ein Backup der alten Einstellungen angelegt werden?"
|
||||
|
||||
AdvSceneSwitcher.close="Schließen"
|
||||
AdvSceneSwitcher.browse="Öffnen"
|
||||
|
||||
AdvSceneSwitcher.selectScene="--Szene auswählen--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Vorhergehende Szene"
|
||||
AdvSceneSwitcher.currentTransition="Aktueller Szenenübergang"
|
||||
AdvSceneSwitcher.selectTransition="--Szenenübergang auswählen--"
|
||||
AdvSceneSwitcher.selectWindow="--Fenster auswählen--"
|
||||
AdvSceneSwitcher.selectAudioSource="--Audio Quelle auswählen--"
|
||||
AdvSceneSwitcher.selectVideoSource="--Video Quelle auswählen--"
|
||||
AdvSceneSwitcher.selectMediaSource="--Medien Quelle auswählen--"
|
||||
AdvSceneSwitcher.selectProcess="--Prozess auswählen--"
|
||||
AdvSceneSwitcher.enterPath="--Pfad eingeben--"
|
||||
|
||||
@@ -6,26 +6,29 @@ AdvSceneSwitcher.generalTab.title="General"
|
||||
AdvSceneSwitcher.generalTab.status="Status"
|
||||
AdvSceneSwitcher.generalTab.status.hotkeytips="Hotkeys can be defined in the OBS settings"
|
||||
AdvSceneSwitcher.generalTab.status.currentStatus="Advanced Scene Switcher is:"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup="On startup:"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup="On startup of OBS:"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="Start the scene switcher if it was running"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Always start the scene switcher"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Do not start the scene switcher"
|
||||
AdvSceneSwitcher.generalTab.status.start="Start"
|
||||
AdvSceneSwitcher.generalTab.status.stop="Stop"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart="Automatically start the scene switcher when:"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Never"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Recording"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streaming"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Recording or Streaming"
|
||||
AdvSceneSwitcher.generalTab.status.checkInterval="Check switch conditions every"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior="General behavior"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.recording="Recording"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.streaming="Streaming"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.recordingAndStreaming="Recording and Streaming"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart1="Automatically start"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart2="on scene"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="If no switch condition is met for"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Will only ever be as accurate as the configured check interval."
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Don't switch"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Switch to any scene in Random tab"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Switch to:"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="After a match do not switch scenes for"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="During this time potential matches will be ignored!"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Enable verbose logging"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStop="Automatically stop streaming/recording on scene"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Save window position and size"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Show system tray notifications"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Disable UI hints"
|
||||
AdvSceneSwitcher.generalTab.priority="Priority"
|
||||
AdvSceneSwitcher.generalTab.priority.description="Switching methods priority (Highest priority is at the top)"
|
||||
@@ -48,15 +51,327 @@ AdvSceneSwitcher.generalTab.priority.windowTitle="Window Title"
|
||||
AdvSceneSwitcher.generalTab.priority.media="Media"
|
||||
AdvSceneSwitcher.generalTab.priority.time="Time"
|
||||
AdvSceneSwitcher.generalTab.priority.audio="Audio"
|
||||
AdvSceneSwitcher.generalTab.priority.video="Video"
|
||||
AdvSceneSwitcher.generalTab.priority.macro="Macro"
|
||||
|
||||
; Macro Tab
|
||||
AdvSceneSwitcher.macroTab.title="Macro"
|
||||
AdvSceneSwitcher.macroTab.macros="Macros"
|
||||
AdvSceneSwitcher.macroTab.help="Macros allow you to execute a string of actions depending on multiple conditions.\n\nClick on the highlighted plus symbol to add a new Macro."
|
||||
AdvSceneSwitcher.macroTab.editConditionHelp="This section allows you to define Macro conditions.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new condition."
|
||||
AdvSceneSwitcher.macroTab.editActionHelp="This section allows you to define Macro actions.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new action."
|
||||
AdvSceneSwitcher.macroTab.edit="Edit macro"
|
||||
AdvSceneSwitcher.macroTab.edit.logic="Logic type:"
|
||||
AdvSceneSwitcher.macroTab.edit.condition="Condition type:"
|
||||
AdvSceneSwitcher.macroTab.edit.action="Action type:"
|
||||
AdvSceneSwitcher.macroTab.add="Add new macro"
|
||||
AdvSceneSwitcher.macroTab.name="Name:"
|
||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||
AdvSceneSwitcher.macroTab.exists="Macro name exists already"
|
||||
AdvSceneSwitcher.macroTab.copy="Create copy"
|
||||
AdvSceneSwitcher.macroTab.expandAll="Expand all"
|
||||
AdvSceneSwitcher.macroTab.collapseAll="Collapse all"
|
||||
|
||||
; Macro Logic
|
||||
AdvSceneSwitcher.logic.none="Ignore entry"
|
||||
AdvSceneSwitcher.logic.and="And"
|
||||
AdvSceneSwitcher.logic.or="Or"
|
||||
AdvSceneSwitcher.logic.andNot="And not"
|
||||
AdvSceneSwitcher.logic.orNot="Or not"
|
||||
AdvSceneSwitcher.logic.rootNone="If"
|
||||
AdvSceneSwitcher.logic.not="If not"
|
||||
|
||||
; Macro Conditions
|
||||
AdvSceneSwitcher.condition.audio="Audio"
|
||||
AdvSceneSwitcher.condition.audio.state.below="Below"
|
||||
AdvSceneSwitcher.condition.audio.state.above="Above"
|
||||
AdvSceneSwitcher.condition.audio.entry="Volume of {{audioSources}} is {{condition}} {{volume}}"
|
||||
AdvSceneSwitcher.condition.cursor="Cursor"
|
||||
AdvSceneSwitcher.condition.cursor.type.region="is in region"
|
||||
AdvSceneSwitcher.condition.cursor.type.moving="is moving"
|
||||
AdvSceneSwitcher.condition.cursor.showFrame="Show frame"
|
||||
AdvSceneSwitcher.condition.cursor.hideFrame="Hide frame"
|
||||
AdvSceneSwitcher.condition.cursor.entry.line1="Cursor is {{conditions}} {{minX}} {{minY}} {{maxX}} {{maxY}} - {{toggleFrameButton}}"
|
||||
AdvSceneSwitcher.condition.cursor.entry.line2="Cursor is currently at {{xPos}} x {{yPos}}"
|
||||
AdvSceneSwitcher.condition.scene="Scene"
|
||||
AdvSceneSwitcher.condition.scene.type.current="Current scene is"
|
||||
AdvSceneSwitcher.condition.scene.type.previous="Previous scene is"
|
||||
AdvSceneSwitcher.condition.scene.type.changed="Scene changed"
|
||||
AdvSceneSwitcher.condition.scene.type.notChanged="Scene has not changed"
|
||||
AdvSceneSwitcher.condition.scene.waitForTransition="Wait for transition to complete"
|
||||
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} {{scenes}} {{waitForTransition}}"
|
||||
AdvSceneSwitcher.condition.window="Window"
|
||||
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.file="File"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="Content of {{fileType}} {{filePath}} matches:"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.media="Media"
|
||||
AdvSceneSwitcher.condition.media.entry="{{mediaSources}} state is {{states}} and {{timeRestrictions}} {{time}}"
|
||||
AdvSceneSwitcher.condition.video="Video"
|
||||
AdvSceneSwitcher.condition.video.condition.match="exactly matches"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="does not match"
|
||||
AdvSceneSwitcher.condition.video.condition.hasChanged="has changed"
|
||||
AdvSceneSwitcher.condition.video.condition.hasNotChanged="has not changed"
|
||||
AdvSceneSwitcher.condition.video.condition.noImage="has no output"
|
||||
AdvSceneSwitcher.condition.video.condition.pattern="matches pattern"
|
||||
AdvSceneSwitcher.condition.video.condition.object="contains object"
|
||||
AdvSceneSwitcher.condition.video.askFileAction="Do you want to use an existing file or create a screenshot of the currently selected source?"
|
||||
AdvSceneSwitcher.condition.video.askFileAction.file="Use existing file"
|
||||
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Create screenshot"
|
||||
AdvSceneSwitcher.condition.video.usePatternForChangedCheck="Use pattern matching"
|
||||
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="This will allow you to control how much the image has to change for the condition to be true."
|
||||
AdvSceneSwitcher.condition.video.patternThreshold="Threshold: "
|
||||
AdvSceneSwitcher.condition.video.patternThresholdDescription="A higher threshold value means that the pattern needs to match the video source more closely."
|
||||
AdvSceneSwitcher.condition.video.patternThresholdUseAlphaAsMask="Use alpha channel as mask for pattern."
|
||||
AdvSceneSwitcher.condition.video.objectScaleThreshold="Scale factor: "
|
||||
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="A lower scale factor will lead to more matches but higher CPU load."
|
||||
AdvSceneSwitcher.condition.video.minNeighborDescription="A higher minimum neighbors value will result in fewer but higher quality matches."
|
||||
AdvSceneSwitcher.condition.video.showMatch="Show match"
|
||||
AdvSceneSwitcher.condition.video.screenshotFail="Failed to get screenshot of source!"
|
||||
AdvSceneSwitcher.condition.video.patternMatchFail="Pattern was not found!"
|
||||
AdvSceneSwitcher.condition.video.objectMatchFail="Object was not found!"
|
||||
AdvSceneSwitcher.condition.video.modelLoadFail="Model data could not be loaded!"
|
||||
AdvSceneSwitcher.condition.video.entry="{{videoSources}} {{condition}} {{imagePath}}"
|
||||
AdvSceneSwitcher.condition.video.entry.modelPath="Model data (haar cascade classifier): {{modelDataPath}}"
|
||||
AdvSceneSwitcher.condition.video.entry.minNeighbor="Minimum neighbors: {{minNeighbors}}"
|
||||
AdvSceneSwitcher.condition.video.entry.minSize="Minimum size: {{minSizeX}} x {{minSizeY}}"
|
||||
AdvSceneSwitcher.condition.video.entry.maxSize="Maximum size: {{maxSizeX}} x {{maxSizeY}}"
|
||||
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}Reduce CPU load by performing check only every {{throttleCount}} milliseconds"
|
||||
AdvSceneSwitcher.condition.stream="Streaming"
|
||||
AdvSceneSwitcher.condition.stream.state.start="Stream running"
|
||||
AdvSceneSwitcher.condition.stream.state.stop="Stream stopped"
|
||||
AdvSceneSwitcher.condition.stream.state.starting="Stream starting"
|
||||
AdvSceneSwitcher.condition.stream.state.stopping="Stream stopping"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}}"
|
||||
AdvSceneSwitcher.condition.record="Recording"
|
||||
AdvSceneSwitcher.condition.record.state.start="Recording running"
|
||||
AdvSceneSwitcher.condition.record.state.pause="Recording paused"
|
||||
AdvSceneSwitcher.condition.record.state.stop="Recording stopped"
|
||||
AdvSceneSwitcher.condition.record.entry="{{recordState}}"
|
||||
AdvSceneSwitcher.condition.process="Process"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}} is running {{focused}} and is focused"
|
||||
AdvSceneSwitcher.condition.idle="Idle"
|
||||
AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for {{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="Plugin state"
|
||||
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene change was triggered in this interval"
|
||||
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
|
||||
AdvSceneSwitcher.condition.timer="Timer"
|
||||
AdvSceneSwitcher.condition.timer.pause="Pause"
|
||||
AdvSceneSwitcher.condition.timer.continue="Continue"
|
||||
AdvSceneSwitcher.condition.timer.entry.line1="{{duration}} have passed"
|
||||
AdvSceneSwitcher.condition.timer.entry.line2="Time remaining: {{remaining}} seconds"
|
||||
AdvSceneSwitcher.condition.timer.entry.line3="{{pauseContinue}} {{reset}} {{saveRemaining}} Save time remaining {{autoReset}} Automatically reset timer after duration was reached"
|
||||
AdvSceneSwitcher.condition.timer.reset="Reset"
|
||||
AdvSceneSwitcher.condition.macro="Macro"
|
||||
AdvSceneSwitcher.condition.macro.type.count="Count"
|
||||
AdvSceneSwitcher.condition.macro.type.state="State"
|
||||
AdvSceneSwitcher.condition.macro.type.selection="Condition type: {{types}}"
|
||||
AdvSceneSwitcher.condition.macro.count.type.below="Less than"
|
||||
AdvSceneSwitcher.condition.macro.count.type.above="More than"
|
||||
AdvSceneSwitcher.condition.macro.count.type.equal="Exactly"
|
||||
AdvSceneSwitcher.condition.macro.count.reset="Reset"
|
||||
AdvSceneSwitcher.condition.macro.pausedWarning="Selected macro is currently paused!"
|
||||
AdvSceneSwitcher.condition.macro.state.entry="Conditions of {{macros}} are true"
|
||||
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} was executed {{conditions}} {{count}} times"
|
||||
AdvSceneSwitcher.condition.macro.count.entry.line2="Current count: {{currentCount}} {{resetCount}}"
|
||||
AdvSceneSwitcher.condition.source="Source"
|
||||
AdvSceneSwitcher.condition.source.type.active="Is active"
|
||||
AdvSceneSwitcher.condition.source.type.showing="Is showing"
|
||||
AdvSceneSwitcher.condition.source.type.settings="Settings match"
|
||||
AdvSceneSwitcher.condition.source.regex="Use regular expressions"
|
||||
AdvSceneSwitcher.condition.source.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
|
||||
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.source.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.virtualCamera="Virtual camera"
|
||||
AdvSceneSwitcher.condition.virtualCamera.state.start="Virtual camera started"
|
||||
AdvSceneSwitcher.condition.virtualCamera.state.stop="Virtual camera stopped"
|
||||
AdvSceneSwitcher.condition.virtualCamera.entry="{{states}}"
|
||||
AdvSceneSwitcher.condition.filter="Filter"
|
||||
AdvSceneSwitcher.condition.filter.type.active="Is enabled"
|
||||
AdvSceneSwitcher.condition.filter.type.showing="Is disabled"
|
||||
AdvSceneSwitcher.condition.filter.type.settings="Settings match"
|
||||
AdvSceneSwitcher.condition.filter.regex="Use regular expressions"
|
||||
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.condition.filter.entry.line1="On {{sources}} {{filters}} {{conditions}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.sceneOrder="Scene item order"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.above="Is above"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.below="Is below"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.position="Is at position"
|
||||
AdvSceneSwitcher.condition.sceneOrder.positionInfo="The position value starts at the bottom with 0 and increases by one for each scene item including the ones in scene groups"
|
||||
AdvSceneSwitcher.condition.sceneOrder.entry="On {{scenes}} {{sources}} {{conditions}} {{sources2}} {{position}}"
|
||||
AdvSceneSwitcher.condition.hotkey="Hotkey"
|
||||
AdvSceneSwitcher.condition.hotkey.name="Macro trigger hotkey"
|
||||
AdvSceneSwitcher.condition.hotkey.tip="Note: You can configure the keybindings for this hotkey in the OBS settings window"
|
||||
AdvSceneSwitcher.condition.hotkey.entry="Name: {{name}}"
|
||||
AdvSceneSwitcher.condition.replay="Replay buffer"
|
||||
AdvSceneSwitcher.condition.replay.state.stopped="Replay buffer stopped"
|
||||
AdvSceneSwitcher.condition.replay.state.started="Replay buffer started"
|
||||
AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved"
|
||||
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||
AdvSceneSwitcher.condition.date="Date"
|
||||
AdvSceneSwitcher.condition.date.state.at="At"
|
||||
AdvSceneSwitcher.condition.date.state.after="After"
|
||||
AdvSceneSwitcher.condition.date.state.before="Before"
|
||||
AdvSceneSwitcher.condition.date.state.between="Between"
|
||||
AdvSceneSwitcher.condition.date.entry.line1="{{condition}} {{dateTime}} {{dateTime2}} {{ignoreDate}} Ignore date component {{ignoreTime}} Ignore time component"
|
||||
AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Repeat every {{duration}} on date match"
|
||||
AdvSceneSwitcher.condition.sceneTransform="Scene item transform"
|
||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="Get transform"
|
||||
AdvSceneSwitcher.condition.sceneTransform.regex="Use regular expressions"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="On {{scenes}} {{sources}} matches transform"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.transition="Transition"
|
||||
AdvSceneSwitcher.condition.transition.type.current="Current transition type is"
|
||||
AdvSceneSwitcher.condition.transition.type.duration="Current transition duration is"
|
||||
AdvSceneSwitcher.condition.transition.type.started="Transition active"
|
||||
AdvSceneSwitcher.condition.transition.type.ended="Transition ended"
|
||||
AdvSceneSwitcher.condition.transition.durationSuffix="seconds"
|
||||
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{duration}}{{durationSuffix}}"
|
||||
AdvSceneSwitcher.condition.sceneVisibility="Scene item visibility"
|
||||
AdvSceneSwitcher.condition.sceneVisibility.type.shown="Shown"
|
||||
AdvSceneSwitcher.condition.sceneVisibility.type.hidden="Hidden"
|
||||
AdvSceneSwitcher.condition.sceneVisibility.entry="On {{scenes}} {{sources}} is {{conditions}} "
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Switch scene"
|
||||
AdvSceneSwitcher.action.scene.entry="Switch to scene {{scenes}} using {{transitions}} with a duration of {{duration}} seconds"
|
||||
AdvSceneSwitcher.action.wait="Wait"
|
||||
AdvSceneSwitcher.action.wait.type.fixed="fixed"
|
||||
AdvSceneSwitcher.action.wait.type.random="random"
|
||||
AdvSceneSwitcher.action.wait.entry.fixed="Wait for {{waitType}} duration of {{duration}}"
|
||||
AdvSceneSwitcher.action.wait.entry.random="Wait for {{waitType}} duration from {{duration}} to {{duration2}}"
|
||||
AdvSceneSwitcher.action.audio="Audio"
|
||||
AdvSceneSwitcher.action.audio.type.mute="Mute"
|
||||
AdvSceneSwitcher.action.audio.type.unmute="Unmute"
|
||||
AdvSceneSwitcher.action.audio.type.sourceVolume="Set source volume"
|
||||
AdvSceneSwitcher.action.audio.type.masterVolume="Set master volume"
|
||||
AdvSceneSwitcher.action.audio.fade="{{fade}}Fade over {{duration}} seconds"
|
||||
AdvSceneSwitcher.action.audio.entry="{{actions}} {{audioSources}} {{volume}}"
|
||||
AdvSceneSwitcher.action.recording="Recording"
|
||||
AdvSceneSwitcher.action.recording.type.stop="Stop recording"
|
||||
AdvSceneSwitcher.action.recording.type.start="Start recording"
|
||||
AdvSceneSwitcher.action.recording.type.pause="Pause recording"
|
||||
AdvSceneSwitcher.action.recording.type.unpause="Unpause recording"
|
||||
AdvSceneSwitcher.action.recording.pause.hint="Note that depending on your recording settings you might not be able to pause recording"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}"
|
||||
AdvSceneSwitcher.action.replay="Replay buffer"
|
||||
AdvSceneSwitcher.action.replay.type.stop="Stop replay buffer"
|
||||
AdvSceneSwitcher.action.replay.type.start="Start replay buffer"
|
||||
AdvSceneSwitcher.action.replay.type.save="Save replay buffer"
|
||||
AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Streaming"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Start streaming"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="Run"
|
||||
AdvSceneSwitcher.action.run.arguments="Arguments:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Add argument"
|
||||
AdvSceneSwitcher.action.run.addArgumentDescription="Add new argument:"
|
||||
AdvSceneSwitcher.action.run.entry="Run {{filePath}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sourceTypes}} {{sources}}"
|
||||
AdvSceneSwitcher.action.filter="Filter"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Enable"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Disable"
|
||||
AdvSceneSwitcher.action.filter.type.settings="Set settings"
|
||||
AdvSceneSwitcher.action.filter.entry="On {{sources}} {{actions}} {{filters}}"
|
||||
AdvSceneSwitcher.action.filter.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.action.source="Source"
|
||||
AdvSceneSwitcher.action.source.type.enable="Enable"
|
||||
AdvSceneSwitcher.action.source.type.disable="Disable"
|
||||
AdvSceneSwitcher.action.source.type.settings="Set settings"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}} {{sources}}"
|
||||
AdvSceneSwitcher.action.source.warning="Warning: Enabling and disabling sources globally cannot be controlled by the OBS UI"
|
||||
AdvSceneSwitcher.action.source.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.action.media="Media"
|
||||
AdvSceneSwitcher.action.media.type.play="Play"
|
||||
AdvSceneSwitcher.action.media.type.pause="Pause"
|
||||
AdvSceneSwitcher.action.media.type.stop="Stop"
|
||||
AdvSceneSwitcher.action.media.type.restart="Restart"
|
||||
AdvSceneSwitcher.action.media.type.next="Next"
|
||||
AdvSceneSwitcher.action.media.type.previous="Previous"
|
||||
AdvSceneSwitcher.action.media.entry="{{actions}} {{mediaSources}}"
|
||||
AdvSceneSwitcher.action.macro="Macro"
|
||||
AdvSceneSwitcher.action.macro.type.pause="Pause"
|
||||
AdvSceneSwitcher.action.macro.type.unpause="Unpause"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Plugin state"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
|
||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}} {{values}} {{scenes}}"
|
||||
AdvSceneSwitcher.action.virtualCamera="Virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Stop virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.type.start="Start virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.hotkey="Hotkey"
|
||||
AdvSceneSwitcher.action.hotkey.leftShift="Left Shift"
|
||||
AdvSceneSwitcher.action.hotkey.rightShift="Right Shift"
|
||||
AdvSceneSwitcher.action.hotkey.leftCtrl="Left Ctrl"
|
||||
AdvSceneSwitcher.action.hotkey.rightCtrl="Right Ctrl"
|
||||
AdvSceneSwitcher.action.hotkey.leftAlt="Left Alt"
|
||||
AdvSceneSwitcher.action.hotkey.rightAlt="Right Alt"
|
||||
AdvSceneSwitcher.action.hotkey.leftMeta="Left Meta"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Right Meta"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Send keypress only to OBS"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate key presses - functionality disabled!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}} for {{duration}} milliseconds"
|
||||
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}}:"
|
||||
AdvSceneSwitcher.action.previewScene="Switch preview scene"
|
||||
AdvSceneSwitcher.action.previewScene.entry="Switch preview scene to {{scenes}}"
|
||||
AdvSceneSwitcher.action.SceneSwap="Swap scene (Studio mode)"
|
||||
AdvSceneSwitcher.action.SceneSwap.entry="Swap preview and program scene in studio mode"
|
||||
AdvSceneSwitcher.action.transition="Transition"
|
||||
AdvSceneSwitcher.action.transition.entry.line1="{{setType}}Set transition type to {{transitions}}"
|
||||
AdvSceneSwitcher.action.transition.entry.line2="{{setDuration}}Set transition duration to {{duration}}seconds"
|
||||
AdvSceneSwitcher.action.timer="Timer"
|
||||
AdvSceneSwitcher.action.timer.type.pause="Pause"
|
||||
AdvSceneSwitcher.action.timer.type.continue="Continue"
|
||||
AdvSceneSwitcher.action.timer.type.reset="Reset"
|
||||
AdvSceneSwitcher.action.timer.type.setTimeRemaining="Set time remaining of"
|
||||
AdvSceneSwitcher.action.timer.entry="{{timerAction}} timers on {{macros}} {{duration}}"
|
||||
AdvSceneSwitcher.action.random="Random"
|
||||
AdvSceneSwitcher.action.random.arguments="Macros:"
|
||||
AdvSceneSwitcher.action.random.addArgument="Add Macro"
|
||||
AdvSceneSwitcher.action.random.entry="Run {{macroSelection}}"
|
||||
|
||||
; Transition Tab
|
||||
AdvSceneSwitcher.transitionTab.title="Transition"
|
||||
AdvSceneSwitcher.transitionTab.transitionOverride="Scene transitions defined in the scene switcher take priority over Transition Overrides defined per scene"
|
||||
AdvSceneSwitcher.transitionTab.setTransitionBy="When changing transitions:"
|
||||
AdvSceneSwitcher.transitionTab.transitionOverride="Set transition overrides"
|
||||
AdvSceneSwitcher.transitionTab.adjustActiveTransitionType="Change active transition type"
|
||||
AdvSceneSwitcher.transitionTab.transitionBehaviorSelectionError="At least one option must be enabled:\n\n - Use transition overrides\n\n - Change active transition type"
|
||||
AdvSceneSwitcher.transitionTab.transitionForAToB="Use transition for automated scene switch from scene A to scene B"
|
||||
AdvSceneSwitcher.transitionTab.transitionForAToB.description="<html><head/><body><p>These settings <span style=\"font-style:italic;\">only</span> affect transitions caused by the scene switcher - Check out <a href=\"https://obsproject.com/forum/resources/obs-transition-matrix.751/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Matrix</span></a> if you want to configure this for manual scene changes.<br/>Settings defined here take priority over transition settings configured elsewhere in the scene switcher.</p></body></html>"
|
||||
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>These settings <span style=\"font-style:italic;\">only</span> affect transitions caused by the scene switcher - Check out <a href=\"https://obsproject.com/forum/resources/transition-table.1174/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Table</span></a> if you want to configure this for manual scene changes.<br/>Settings defined here take priority over transition settings configured elsewhere in the scene switcher.<br/><br/>Click the plus symbol below to add a new entry.</p></body></html>"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition="Change transition if scene is active"
|
||||
AdvSceneSwitcher.transitionTab.entry="Switch from {{scenes}} to {{scenes2}} using {{transitions}}"
|
||||
AdvSceneSwitcher.transitionTab.entry="Switch from {{scenes}} to {{scenes2}} using {{transitions}} with a duration of {{duration}}"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransitionEntry="When scene {{scenes}} is active change default scene transition to {{transitions}}"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransitionsHelp="Click on the plus symbol to add an entry."
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition.delay="Switch transition {{defTransitionDelay}} after scene change."
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition.delay.help="The delay is used to avoid cancelled scene switches, which can happen if the transition type is changed while a transition is still ongoing."
|
||||
|
||||
; Pause Scenes Tab
|
||||
AdvSceneSwitcher.pauseTab.title="Pause"
|
||||
@@ -67,6 +382,7 @@ AdvSceneSwitcher.pauseTab.pauseTypeScene="scene is active"
|
||||
AdvSceneSwitcher.pauseTab.pauseTypeWindow="window is in focus"
|
||||
AdvSceneSwitcher.pauseTab.pauseTargetAll="all"
|
||||
AdvSceneSwitcher.pauseTab.pauseEntry="Pause {{pauseTargets}} checks when {{pauseTypes}} {{scenes}} {{windows}}"
|
||||
AdvSceneSwitcher.pauseTab.help="On this tab you can configure to pause individual switching methods if a scene is active or window is in focus.\n\nClick on the highlighted plus symbol to continue."
|
||||
|
||||
; Window Title Tab
|
||||
AdvSceneSwitcher.windowTitleTab.title="Title"
|
||||
@@ -77,19 +393,24 @@ AdvSceneSwitcher.windowTitleTab.fullscreen="if fullscreen"
|
||||
AdvSceneSwitcher.windowTitleTab.maximized="if maximized"
|
||||
AdvSceneSwitcher.windowTitleTab.focused="if focused"
|
||||
AdvSceneSwitcher.windowTitleTab.entry="{{windows}} {{scenes}} {{transitions}} {{fullscreen}} {{maximized}} {{focused}}"
|
||||
AdvSceneSwitcher.windowTitleTab.windowsHelp="Switch scenes based on the window title of running applications.\nThe following additional conditions can be selected:\nThe window is Fullscreen\nThe window is maximized\nThe window is focused\n\nClick on the highlighted plus symbol to continue."
|
||||
AdvSceneSwitcher.windowTitleTab.ignoreWindowsHelp="If a window title is ignored the scene switcher will act as if the previously selected window is still in focus.\nThis will allow you to avoid scene switches, if you frequently switch to a different window, which shall not trigger a scene change.\n\nChoose a window or enter a window title above and click on the plus symbol below to add it to the list."
|
||||
|
||||
; Executable Tab
|
||||
AdvSceneSwitcher.executableTab.title="Executable"
|
||||
AdvSceneSwitcher.executableTab.implemented="Implemented by dasOven"
|
||||
AdvSceneSwitcher.executableTab.requiresFocus="only if focused"
|
||||
AdvSceneSwitcher.executableTab.entry="When {{processes}} is running switch to {{scenes}} using {{transitions}} {{requiresFocus}}"
|
||||
AdvSceneSwitcher.executableTab.help="This tab will allow you to automatically switch scenes if a process is running.\nThis can be useful in situations where the window name could change or is not known.\n\nClick on the highlighted plus symbol to continue."
|
||||
|
||||
; Screen Region Tab
|
||||
AdvSceneSwitcher.screenRegionTab.title="Region"
|
||||
AdvSceneSwitcher.screenRegionTab.currentPosition="Cursor is currently at:"
|
||||
AdvSceneSwitcher.screenRegionTab.showGuideFrames="Show guide frames"
|
||||
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="Hide guide frames"
|
||||
AdvSceneSwitcher.screenRegionTab.entry="If cursor is in {{minX}} {{minY}} x {{maxX}} {{maxY}} switch to {{scenes}} using {{transitions}}"
|
||||
AdvSceneSwitcher.screenRegionTab.excludeScenes.None="No selection"
|
||||
AdvSceneSwitcher.screenRegionTab.entry="If cursor is in {{minX}} {{minY}} x {{maxX}} {{maxY}} switch to {{scenes}} using {{transitions}} unless in {{excludeScenes}}"
|
||||
AdvSceneSwitcher.screenRegionTab.help="This tab will allow you to automatically switch scenes based on the current position of your mouse cursor.\n\nClick on the highlighted plus symbol to continue."
|
||||
|
||||
; Media Tab
|
||||
AdvSceneSwitcher.mediaTab.title="Media"
|
||||
@@ -110,6 +431,7 @@ AdvSceneSwitcher.mediaTab.timeRestriction.longer="Time longer"
|
||||
AdvSceneSwitcher.mediaTab.timeRestriction.remainShorter="Time remaining shorter"
|
||||
AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger="Time remaining longer"
|
||||
AdvSceneSwitcher.mediaTab.entry="When {{mediaSources}} state is {{states}} and {{timeRestrictions}} {{time}} switch to {{scenes}} using {{transitions}}"
|
||||
AdvSceneSwitcher.mediaTab.help="This tab will allow you to switch scenes based on the states of media sources.\nFor example, you can automatically switch back to the previous scene once the selected media sourced ended its playback.\n\nClick on the highlighted plus symbol to continue."
|
||||
|
||||
; File Tab
|
||||
AdvSceneSwitcher.fileTab.title="File"
|
||||
@@ -134,11 +456,13 @@ AdvSceneSwitcher.fileTab.checkfileContent="if content changed"
|
||||
AdvSceneSwitcher.fileTab.entry="Switch to {{scenes}} using {{transitions}} if content of {{fileType}} {{filePath}} {{browseButton}} matches:"
|
||||
AdvSceneSwitcher.fileTab.entry2="{{matchText}}"
|
||||
AdvSceneSwitcher.fileTab.entry3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.fileTab.help="This tab will allow you to automatically switch scenes based on the content of remote or local files.\n\nClick on the highlighted plus symbol to continue."
|
||||
|
||||
; Random Tab
|
||||
AdvSceneSwitcher.randomTab.title="Random"
|
||||
AdvSceneSwitcher.randomTab.randomDisabledWarning="Functionality disabled - To activate select \"If no switch condition is met switch to any scene in Random tab\" on General tab"
|
||||
AdvSceneSwitcher.randomTab.entry="If no switch condition is met switch to {{scenes}} using {{transitions}} for {{delay}}"
|
||||
AdvSceneSwitcher.randomTab.help="The scene switcher will randomly choose an entry on this tab to switch to for the configured time.\nNote that the same entry will not be chosen twice in a row.\n\nClick on the highlighted plus symbol to continue."
|
||||
|
||||
; Time Tab
|
||||
AdvSceneSwitcher.timeTab.title="Time"
|
||||
@@ -153,15 +477,12 @@ AdvSceneSwitcher.timeTab.sundays="Sundays"
|
||||
AdvSceneSwitcher.timeTab.afterstart="After streaming/recording start"
|
||||
AdvSceneSwitcher.timeTab.afterstart.tip="The time relative to the start of streaming / recording will be used"
|
||||
AdvSceneSwitcher.timeTab.entry="{{triggers}} at {{time}} switch to {{scenes}} using {{transitions}}"
|
||||
AdvSceneSwitcher.timeTab.help="This tab will allow you to automatically switch to a different scene based on the current local time.\n\nNote that the scene switcher will only switch scenes at the exact time you specified.\nMake sure you have configured the priority settings on the General tab to your liking so the selected time point will not be missed due to other switching methods having a higher priority.\n\nClick on the highlighted plus symbol to continue."
|
||||
|
||||
; Idle Tab
|
||||
AdvSceneSwitcher.idleTab.title="Idle"
|
||||
AdvSceneSwitcher.idleTab.enable="Enable Idle Detection"
|
||||
AdvSceneSwitcher.idleTab.condition1="After "
|
||||
AdvSceneSwitcher.idleTab.condition2="of no keyboard or mouse inputs "
|
||||
AdvSceneSwitcher.idleTab.switchToScene="switch to scene"
|
||||
AdvSceneSwitcher.idleTab.usingTransition1="using the"
|
||||
AdvSceneSwitcher.idleTab.usingTransition2="transition"
|
||||
AdvSceneSwitcher.idleTab.idleswitch="After {{duration}} of no keyboard or mouse inputs switch to scene {{scenes}} using the {{transitions}}"
|
||||
AdvSceneSwitcher.idleTab.dontSwitchIfFocus1="Do not switch if"
|
||||
AdvSceneSwitcher.idleTab.dontSwitchIfFocus2="is in focus"
|
||||
|
||||
@@ -175,29 +496,134 @@ AdvSceneSwitcher.sceneSequenceTab.loadTitle="Select a file to read Scene Sequenc
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadFail="Advanced Scene Switcher failed to import settings!"
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Advanced Scene Switcher settings imported successfully!"
|
||||
AdvSceneSwitcher.sceneSequenceTab.fileType="Text files (*.txt)"
|
||||
AdvSceneSwitcher.sceneSequenceTab.entry="When {{startScenes}} is active switch to {{scenes}} after {{delay}} {{delayUnits}} using {{transitions}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.interruptible="interruptible"
|
||||
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Other switching methods are allowed to interrupt this scene sequence"
|
||||
AdvSceneSwitcher.sceneSequenceTab.entry="When {{startScenes}} is active switch to {{scenes}} after {{delay}} using {{transitions}} {{interruptible}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.extendEdit="Extend Sequence"
|
||||
AdvSceneSwitcher.sceneSequenceTab.extendEntry="After {{delay}} switch to {{scenes}} using {{transitions}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.help="This tab will allow you to automatically switch to a different scene if a scene was active for a configured period of time.\nFor example, you could automatically cycle back and forth between two scenes automatically.\n\nClick on the highlighted plus symbol to continue."
|
||||
|
||||
; Audio Tab
|
||||
AdvSceneSwitcher.audioTab.title="Audio"
|
||||
AdvSceneSwitcher.audioTab.condition.above="above"
|
||||
AdvSceneSwitcher.audioTab.condition.below="below"
|
||||
AdvSceneSwitcher.audioTab.entry="When the volume of {{audioSources}} is {{condition}} {{volumeWidget}} for {{duration}} switch to {{scenes}} using {{transitions}}"
|
||||
AdvSceneSwitcher.audioTab.ignoreInactiveSource="unless source is inactive"
|
||||
AdvSceneSwitcher.audioTab.entry="When the volume of {{audioSources}} is {{condition}} {{volumeWidget}} for {{duration}} seconds switch to {{scenes}} using {{transitions}} {{ignoreInactiveSource}}"
|
||||
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="If multiple entries match ..."
|
||||
AdvSceneSwitcher.audioTab.multiMatchfallback="... for {{duration}} seconds switch to {{scenes}} using {{transitions}}"
|
||||
AdvSceneSwitcher.audioTab.help="This tab will allow you to switch scenes based on the volume of sources.\nFor example, you could automatically switch to a different scene if the volume of your microphone reaches a certain threshold.\n\nClick on the highlighted plus symbol to continue."
|
||||
|
||||
; Video Tab
|
||||
AdvSceneSwitcher.videoTab.title="Video"
|
||||
AdvSceneSwitcher.videoTab.getScreenshot="Get screenshot for selected entry"
|
||||
AdvSceneSwitcher.videoTab.getScreenshotHelp="Get Screenshot of the currently selected entry's video source and automatically set it as the target image"
|
||||
AdvSceneSwitcher.videoTab.condition.match="exactly matches"
|
||||
AdvSceneSwitcher.videoTab.condition.match.tooltip="An exact match requires the target and the source image to be of the same resolution.\nAdditionally every single pixel needs to match, which is why use of image formats which use compression (e.g. .JPG) is not recommended!"
|
||||
AdvSceneSwitcher.videoTab.condition.differ="does not match"
|
||||
AdvSceneSwitcher.videoTab.condition.hasNotChanged="has not changed"
|
||||
AdvSceneSwitcher.videoTab.condition.hasChanged="has changed"
|
||||
AdvSceneSwitcher.videoTab.ignoreInactiveSource="unless source is inactive"
|
||||
AdvSceneSwitcher.videoTab.entry="When {{videoSources}} {{condition}} {{filePath}} {{browseButton}} for {{duration}} switch to {{scenes}} using {{transitions}} {{ignoreInactiveSource}}"
|
||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>This tab will allow you to switch scenes based on the current video output of selected sources.<br/>Make sure to check out <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> for an even better implementation of this functionality.<br/><br/> Click on the highlighted plus symbol to continue.</p></body></html>"
|
||||
|
||||
; Network Tab
|
||||
AdvSceneSwitcher.networkTab.title="Network"
|
||||
AdvSceneSwitcher.networkTab.description="This tab will allow you to remotely control the active scene of another OBS instance.\nPlease note that the scene names have to match exactly on all OBS instances."
|
||||
AdvSceneSwitcher.networkTab.warning="Running the server outside of a local network will allow third parties to read the active scene."
|
||||
AdvSceneSwitcher.networkTab.DisabledWarning="This functionality unfortunately had to be disabled on macOS due to library incompatibilities when running the obs-websocket plugin in parallel."
|
||||
AdvSceneSwitcher.networkTab.server="Start server (Sends scene switch messages to all connected clients)"
|
||||
AdvSceneSwitcher.networkTab.server.port="Port"
|
||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Lock server to only using IPv4"
|
||||
AdvSceneSwitcher.networkTab.server.sendSceneChange="Send messages for scene changes"
|
||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Only send messages for automated scene switches"
|
||||
AdvSceneSwitcher.networkTab.server.sendPreview="Send messages for preview scene change when running in Studio mode"
|
||||
AdvSceneSwitcher.networkTab.startFailed.message="The WebSockets server failed to start, maybe because:\n - TCP port %1 may currently be in use elsewhere on this system, possibly by another application. Try setting a different TCP port in the WebSocket server settings, or stop any application that could be using this port.\n - Error message: %2"
|
||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="Current status"
|
||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Not running"
|
||||
AdvSceneSwitcher.networkTab.server.status.starting="Starting"
|
||||
AdvSceneSwitcher.networkTab.server.status.running="Running"
|
||||
AdvSceneSwitcher.networkTab.server.restart="Restart server"
|
||||
AdvSceneSwitcher.networkTab.client="Start client (Receives scene switches messages)"
|
||||
AdvSceneSwitcher.networkTab.client.address="Hostname or IP address"
|
||||
AdvSceneSwitcher.networkTab.client.port="Port"
|
||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="Current status"
|
||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Disconnected"
|
||||
AdvSceneSwitcher.networkTab.client.status.connecting="Connecting"
|
||||
AdvSceneSwitcher.networkTab.client.status.connected="Connected"
|
||||
AdvSceneSwitcher.networkTab.client.reconnect="Force reconnect"
|
||||
|
||||
; Scene Group Tab
|
||||
AdvSceneSwitcher.sceneGroupTab.title="Scene Group"
|
||||
AdvSceneSwitcher.sceneGroupTab.list="Scene Groups"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit="Edit Scene Groups"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.name="Name:"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.type="Type: {{type}}"
|
||||
AdvSceneSwitcher.sceneGroupTab.type.count="Count"
|
||||
AdvSceneSwitcher.sceneGroupTab.type.time="Time"
|
||||
AdvSceneSwitcher.sceneGroupTab.type.random="Random"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.count="Advance to next scene in list after {{count}} matches"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.time="Advance to next scene in list after {{time}} has passed"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.random="Choose next scene in list at random"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.repeat="Start from beginning if end of scene list is reached"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.addScene="Add scene"
|
||||
AdvSceneSwitcher.sceneGroupTab.add="Add Scene Group"
|
||||
AdvSceneSwitcher.sceneGroupTab.defaultname="Scene Group %1"
|
||||
AdvSceneSwitcher.sceneGroupTab.exists="Scene Group or Scene name exists already"
|
||||
AdvSceneSwitcher.sceneGroupTab.help="Scene Groups can be selected as a target just like a regular scene.\n\nAs the name suggests a scene group is a collection of multiple scenes.\nThe scene group will advance through the list of its assigned scenes depending on the configured settings, which can be found on the right side.\n\nYou can configure the scene group to advance to the next scene in the list:\nAfter a number of times the scene group is selected as a target.\nAfter a certain amount of time has passed.\nOr randomly.\n\nFor example, a scene group containing the scenes ...\nScene 1\nScene 2\nScene 3 \n... will activate \"Scene 1\" the first time it is selected as a target.\nThe second time it will activate \"Scene 2\".\nThe remaining times \"Scene 3\" will be activated.\n\nClick the highlighted plus symbol below to add a new scene group."
|
||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Select the scene group you want to modify on the left.\n\nSelect a scene to add to this scene group by selecting the scene above and clicking the plus symbol below.\n\nA scene can be added multiple times to the same scene group."
|
||||
|
||||
; Scene Trigger Tab
|
||||
AdvSceneSwitcher.sceneTriggerTab.title="Scene Triggers"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--select trigger--"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="is active"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="is not active"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="switched away from"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--select action--"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="start recording"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="pause recording"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="unpause recording"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="stop recording"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="stop streaming"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="start streaming"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="start replay buffer"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="stop replay buffer"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="mute source"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="unmute source"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="start the scene switcher"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="stop the scene switcher"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="start virtual camera"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="stop virtual camera"
|
||||
AdvSceneSwitcher.sceneTriggerTab.entry="When {{scenes}} {{triggers}} {{actions}} {{audioSources}} after {{duration}}"
|
||||
AdvSceneSwitcher.sceneTriggerTab.help="This tab allows you to trigger actions on scene changes, like stopping recording or streaming."
|
||||
|
||||
; Hotkey
|
||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Start the Advanced Scene Switcher"
|
||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="Stop the Advanced Scene Switcher"
|
||||
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Toggle Start/Stop for the Advanced Scene Switcher"
|
||||
AdvSceneSwitcher.hotkey.macro.pause="Pause macro %1"
|
||||
AdvSceneSwitcher.hotkey.macro.unpause="Unpause macro %1"
|
||||
|
||||
AdvSceneSwitcher.askBackup="Detected a new version of the Advanced Scene Switcher.\nShould a backup of the old settings be created?"
|
||||
|
||||
AdvSceneSwitcher.close="Close"
|
||||
AdvSceneSwitcher.browse="Browse"
|
||||
|
||||
AdvSceneSwitcher.selectScene="--select scene--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||
AdvSceneSwitcher.selectAnyScene="Any Scene"
|
||||
AdvSceneSwitcher.currentTransition="Current Transition"
|
||||
AdvSceneSwitcher.anyTransition="Any Transition"
|
||||
AdvSceneSwitcher.selectTransition="--select transition--"
|
||||
AdvSceneSwitcher.selectWindow="--select window--"
|
||||
AdvSceneSwitcher.selectSource="--select source--"
|
||||
AdvSceneSwitcher.selectAudioSource="--select audio source--"
|
||||
AdvSceneSwitcher.selectVideoSource="--select video source--"
|
||||
AdvSceneSwitcher.selectMediaSource="--select media source--"
|
||||
AdvSceneSwitcher.selectProcess="--select process--"
|
||||
AdvSceneSwitcher.selectFilter="--select filter--"
|
||||
AdvSceneSwitcher.selectMacro="--select macro--"
|
||||
AdvSceneSwitcher.selectItem="--select item--"
|
||||
AdvSceneSwitcher.enterPath="--enter path--"
|
||||
AdvSceneSwitcher.enterText="--enter text--"
|
||||
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="invalid entries will not be saved"
|
||||
@@ -205,8 +631,14 @@ AdvSceneSwitcher.selectWindowTip="Use \"OBS\" to specify OBS window\nUse \"Task
|
||||
|
||||
AdvSceneSwitcher.status.active="Active"
|
||||
AdvSceneSwitcher.status.inactive="Inactive"
|
||||
AdvSceneSwitcher.running="Plugin running"
|
||||
AdvSceneSwitcher.stopped="Plugin stopped"
|
||||
|
||||
AdvSceneSwitcher.unit.milliseconds="milliseconds"
|
||||
AdvSceneSwitcher.unit.secends="seconds"
|
||||
AdvSceneSwitcher.unit.minutes="minutes"
|
||||
AdvSceneSwitcher.unit.hours="hours"
|
||||
AdvSceneSwitcher.duration.condition.none="No time constraint"
|
||||
AdvSceneSwitcher.duration.condition.more="For at least"
|
||||
AdvSceneSwitcher.duration.condition.equal="For exactly"
|
||||
AdvSceneSwitcher.duration.condition.less="For at most"
|
||||
|
||||
422
data/locale/ru-RU.ini
Normal file
422
data/locale/ru-RU.ini
Normal file
@@ -0,0 +1,422 @@
|
||||
AdvSceneSwitcher.pluginName="Advanced Scene Switcher"
|
||||
AdvSceneSwitcher.windowTitle="Advanced Scene Switcher"
|
||||
|
||||
; General Tab
|
||||
AdvSceneSwitcher.generalTab.title="Общие"
|
||||
AdvSceneSwitcher.generalTab.status="Статус"
|
||||
AdvSceneSwitcher.generalTab.status.hotkeytips="Горячие клавиши можно определить в настройках OBS"
|
||||
AdvSceneSwitcher.generalTab.status.currentStatus="Advanced Scene Switcher сейчас:"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup="При запуске OBS:"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="Запустить переключатель сцен, если он был запущен"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Всегда запускать переключатель сцен"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Не запускать переключатель сцен"
|
||||
AdvSceneSwitcher.generalTab.status.start="Старт"
|
||||
AdvSceneSwitcher.generalTab.status.stop="Стоп"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart="Автоматически запускать переключатель сцен, когда:"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Никогда"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Запись"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Вещание"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Запись или потоковое вещание"
|
||||
AdvSceneSwitcher.generalTab.status.checkInterval="Проверять условия переключения каждый раз"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior="Общее поведение"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="Если не выполняется условие переключения для"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="Будет только настолько точным, насколько настроен интервал проверки."
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="Не переключаться"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="Переключиться на любую сцену на вкладке Random"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="Переключиться на:"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldown="После совпадения не переключаться между сценами в течение"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.cooldownHint="В течение этого времени потенциальные совпадения будут игнорироваться!"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="Включить ведение подробного журнала"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.saveWindowGeo="Сохранять положение и размер окна"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Отключить подсказки пользовательского интерфейса"
|
||||
AdvSceneSwitcher.generalTab.priority="Приоритет"
|
||||
AdvSceneSwitcher.generalTab.priority.description="Приоритет методов переключения (самый высокий приоритет - вверху)"
|
||||
AdvSceneSwitcher.generalTab.priority.threadPriority="Использовать приоритет потока"
|
||||
AdvSceneSwitcher.generalTab.priority.threadPriorityNotice="(Поднимать приоритет выше \"Нормальный\" не рекомендуется)"
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings="Сохранить / загрузить настройки"
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.export="Экспорт"
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.import="Импорт"
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle="Экспортировать настройки расширенного переключателя сцен в файл ..."
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle="Импортировать настройки Advanced Scene Switcher из файла ..."
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType="Текстовые файлы (*.txt)"
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadFail="Advanced Scene Switcher не удалось импортировать настройки"
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess="Настройки Advanced Scene Switcher импортированы успешно"
|
||||
AdvSceneSwitcher.generalTab.priority.fileContent="Содержание файла"
|
||||
AdvSceneSwitcher.generalTab.priority.sceneSequence="Последовательность сцены"
|
||||
AdvSceneSwitcher.generalTab.priority.idleDetection="Обнаружение простоя"
|
||||
AdvSceneSwitcher.generalTab.priority.executable="Исполняемый файл"
|
||||
AdvSceneSwitcher.generalTab.priority.screenRegion="Область экрана"
|
||||
AdvSceneSwitcher.generalTab.priority.windowTitle="Заголовок окна"
|
||||
AdvSceneSwitcher.generalTab.priority.media="Медиа"
|
||||
AdvSceneSwitcher.generalTab.priority.time="Время"
|
||||
AdvSceneSwitcher.generalTab.priority.audio="Аудио"
|
||||
AdvSceneSwitcher.generalTab.priority.video="Видео"
|
||||
AdvSceneSwitcher.generalTab.priority.macro="Макрос"
|
||||
|
||||
; Macro Tab
|
||||
AdvSceneSwitcher.macroTab.title="Макрос"
|
||||
AdvSceneSwitcher.macroTab.macros="Макросы"
|
||||
AdvSceneSwitcher.macroTab.help="Макросы позволяют выполнять ряд действий в зависимости от нескольких условий.\n\nНажмите на выделенный символ плюса, чтобы добавить новый макрос."
|
||||
AdvSceneSwitcher.macroTab.editConditionHelp="Этот раздел позволяет определить условия макроса.\n\nВыберите существующий или добавьте новый макрос слева."
|
||||
AdvSceneSwitcher.macroTab.editActionHelp="Этот раздел позволяет определить действия макроса.\n\n\nВыберите существующий или добавьте новый макрос слева."
|
||||
AdvSceneSwitcher.macroTab.edit="Редактировать макрос"
|
||||
AdvSceneSwitcher.macroTab.edit.logic="Тип логики:"
|
||||
AdvSceneSwitcher.macroTab.edit.condition="Тип условия:"
|
||||
AdvSceneSwitcher.macroTab.edit.action="Тип действия:"
|
||||
AdvSceneSwitcher.macroTab.add="Добавить новый макрос"
|
||||
AdvSceneSwitcher.macroTab.name="Имя:"
|
||||
AdvSceneSwitcher.macroTab.defaultname="Макрос %1"
|
||||
AdvSceneSwitcher.macroTab.exists="Имя макроса уже существует"
|
||||
AdvSceneSwitcher.macroTab.copy="Создать копию"
|
||||
; Macro Logic
|
||||
AdvSceneSwitcher.logic.none="Игнорировать вход"
|
||||
AdvSceneSwitcher.logic.and="И"
|
||||
AdvSceneSwitcher.logic.or="Или"
|
||||
AdvSceneSwitcher.logic.andNot="И не"
|
||||
AdvSceneSwitcher.logic.orNot="Или нет"
|
||||
AdvSceneSwitcher.logic.rootNone="Если"
|
||||
AdvSceneSwitcher.logic.not="Если нет"
|
||||
; Macro Conditions
|
||||
AdvSceneSwitcher.condition.audio="Аудио"
|
||||
AdvSceneSwitcher.ondition.audio.state.below="Ниже"
|
||||
AdvSceneSwitcher.ondition.audio.state.above="Выше"
|
||||
AdvSceneSwitcher.condition.audio.entry="Громкость {{audioSources}} равна {{condition}} {{volume}} в течении {{duration}} секунд"
|
||||
AdvSceneSwitcher.condition.cursor="Область экрана"
|
||||
AdvSceneSwitcher.condition.scene="Сцена"
|
||||
AdvSceneSwitcher.condition.scene.type.current="Текущий"
|
||||
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
|
||||
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} сцена является {{scenes}} на {{duration}}"
|
||||
AdvSceneSwitcher.condition.window="Окно"
|
||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} существует и ..."
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... это {{fullscreen}} полноэкранный {{maximized}} максимизированный {{focused}} сфокусированный"
|
||||
AdvSceneSwitcher.condition.file="Файл"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="Содержимое {{fileType}} {{filePath}} {{browseButton}} соответствует:"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.media="Медиа"
|
||||
AdvSceneSwitcher.condition.media.entry="{{mediaSources}} состояние {{states}} и {{timeRestrictions}} {{time}}"
|
||||
AdvSceneSwitcher.condition.video="Видео"
|
||||
AdvSceneSwitcher.condition.video.condition.match="точно соответствует"
|
||||
AdvSceneSwitcher.condition.video.condition.differ="не совпадает"
|
||||
AdvSceneSwitcher.condition.video.condition.hasChanged="изменилось"
|
||||
AdvSceneSwitcher.condition.video.condition.hasNotChanged="не изменилось"
|
||||
AdvSceneSwitcher.condition.video.condition.noImage="не имеет вывода"
|
||||
AdvSceneSwitcher.condition.video.askFileAction="Вы хотите использовать существующий файл или создать скриншот текущего выбранного источника?"
|
||||
AdvSceneSwitcher.condition.video.askFileAction.file="Использовать существующий файл"
|
||||
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Создать скриншот"
|
||||
AdvSceneSwitcher.condition.video.entry="{{videoSources}} {{condition}} {{filePath}} {{browseButton}} для {{duration}}"
|
||||
AdvSceneSwitcher.condition.stream="Потоковое вещание"
|
||||
AdvSceneSwitcher.condition.stream.state.start="Поток запущен"
|
||||
AdvSceneSwitcher.condition.stream.state.stop="Поток остановлен"
|
||||
AdvSceneSwitcher.condition.stream.entry="{{streamState}} для {{duration}}"
|
||||
AdvSceneSwitcher.condition.record="Запись"
|
||||
AdvSceneSwitcher.condition.record.state.start="Запись запущена"
|
||||
AdvSceneSwitcher.condition.record.state.pause="Запись приостановлена"
|
||||
AdvSceneSwitcher.condition.record.state.stop="Запись остановлена"
|
||||
AdvSceneSwitcher.condition.record.entry="{{recordState}} для {{duration}}"
|
||||
AdvSceneSwitcher.condition.process="Процесс"
|
||||
AdvSceneSwitcher.condition.process.entry="{{processes}} запущен {{focused}} и сфокусирован"
|
||||
AdvSceneSwitcher.condition.idle="Простой"
|
||||
AdvSceneSwitcher.condition.idle.entry="Не было ни клавиатуры, ни мыши в течении{{duration}}"
|
||||
AdvSceneSwitcher.condition.pluginState="Состояние плагина"
|
||||
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Автоматическая смена сцены была запущена в этом интервале"
|
||||
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Переключить сцену"
|
||||
AdvSceneSwitcher.action.scene.entry="Перейти к сцене {{scenes}} используя {{transitions}} с продолжительностью {{duration}} секунд"
|
||||
AdvSceneSwitcher.action.wait="Подождать"
|
||||
AdvSceneSwitcher.action.wait.type.fixed="фиксированный"
|
||||
AdvSceneSwitcher.action.wait.type.random="случайный"
|
||||
AdvSceneSwitcher.action.wait.entry.fixed="Ожидать {{waitType}} в течении {{duration}}"
|
||||
AdvSceneSwitcher.action.wait.entry.random="Ожидание {{waitType}} длительностью от {{duration}} до {{duration2}}"
|
||||
AdvSceneSwitcher.action.audio="Аудио"
|
||||
AdvSceneSwitcher.action.audio.type.mute="Замьютить"
|
||||
AdvSceneSwitcher.action.audio.type.unmute="Размьютить"
|
||||
AdvSceneSwitcher.action.audio.type.sourceVolume="Установить громкость источника"
|
||||
AdvSceneSwitcher.action.audio.type.masterVolume="Установить главную громкость"
|
||||
AdvSceneSwitcher.action.audio.entry="{{actions}} {{audioSources}} {{volume}}"
|
||||
AdvSceneSwitcher.action.recording="Запись"
|
||||
AdvSceneSwitcher.action.recording.type.stop="Остановить запись"
|
||||
AdvSceneSwitcher.action.recording.type.start="Начать запись"
|
||||
AdvSceneSwitcher.action.recording.type.pause="Пауза записи"
|
||||
AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы"
|
||||
AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись"
|
||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}"
|
||||
AdvSceneSwitcher.action.replay="Буфер воспроизведения"
|
||||
AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения"
|
||||
AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера"
|
||||
AdvSceneSwitcher.action.replay.type.save="Сохранить буфер воспроизведения"
|
||||
AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Потоковое вещание"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Остановить потоковое вещание"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="Запустить"
|
||||
AdvSceneSwitcher.action.run.entry="Запустить {{filePath}} {{browseButton}}"
|
||||
|
||||
|
||||
; Transition Tab
|
||||
AdvSceneSwitcher.transitionTab.title="Переход"
|
||||
AdvSceneSwitcher.transitionTab.setTransitionBy="При изменении переходов:"
|
||||
AdvSceneSwitcher.transitionTab.transitionOverride="Установить переопределение переходов"
|
||||
AdvSceneSwitcher.transitionTab.adjustActiveTransitionType="Изменить тип активного перехода"
|
||||
AdvSceneSwitcher.transitionTab.transitionBehaviorSelectionError="Должна быть включена хотя бы одна опция:\n\n - Использовать переопределения переходов\n\n - Изменить тип активного перехода"
|
||||
AdvSceneSwitcher.transitionTab.transitionForAToB="Использовать переход для автоматического переключения сцены со сцены A на сцену B"
|
||||
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>Эти настройки <span style=\"font-style:italic;\">только</span> влияют на переходы, вызванные переключателем сцен - Проверьте <a href=\"https://obsproject.com/forum/resources/transition-table.1174/\"><span style=\" text-decoration: underline; color:#268bd2;\">Transition Table</span></a> если вы хотите настроить его для ручного изменения сцены.<br/>Настройки, определенные здесь, имеют приоритет над настройками перехода, сконфигурированными в других местах переключателя сцен.<br/><br/>Нажмите на символ плюса ниже, чтобы добавить новую запись.</p></body></html>"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition="Изменить переход, если сцена активна"
|
||||
AdvSceneSwitcher.transitionTab.entry="Переход от {{scenes}} к {{scenes2}} с помощью {{transitions}} с длительностью {{duration}}"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransitionEntry="Когда сцена {{scenes}} активна, изменить переход сцены по умолчанию на {{transitions}}"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransitionsHelp="Нажмите на символ плюса, чтобы добавить запись."
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition.delay="Переключить переход {{defTransitionDelay}} после смены сцены."
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition.delay.help="Задержка используется для того, чтобы избежать отмены переключения сцены, что может произойти, если тип перехода будет изменен, когда переход еще продолжается."
|
||||
|
||||
; Pause Scenes Tab
|
||||
AdvSceneSwitcher.pauseTab.title="Пауза"
|
||||
AdvSceneSwitcher.pauseTab.pauseOnScene="Приостановить Scene Switcher на сцене"
|
||||
AdvSceneSwitcher.pauseTab.pauseInFocus1="Приостановить Scene Switcher когда "
|
||||
AdvSceneSwitcher.pauseTab.pauseInFocus2="находится в фокусе"
|
||||
AdvSceneSwitcher.pauseTab.pauseTypeScene="сцена активна"
|
||||
AdvSceneSwitcher.pauseTab.pauseTypeWindow="окно в фокусе"
|
||||
AdvSceneSwitcher.pauseTab.pauseTargetAll="все"
|
||||
AdvSceneSwitcher.pauseTab.pauseEntry="Пауза {{pauseTargets}} проверяет, когда {{pauseTypes}} {{scenes}} {{windows}}"
|
||||
AdvSceneSwitcher.pauseTab.help="На этой вкладке вы можете настроить приостановку отдельных методов переключения, если сцена активна или окно находится в фокусе.\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
|
||||
; Window Title Tab
|
||||
AdvSceneSwitcher.windowTitleTab.title="Название"
|
||||
AdvSceneSwitcher.windowTitleTab.regexrDescription="<html><head/><body><p>Введите либо прямые заголовки окон, либо правильное регулярное выражение. Вы можете проверить синтаксис и соответствие регулярных выражений, используя <a href=\"https://regexr.com\"><span style=\" text-decoration: underline; color:#268bd2;\">RegExr</span></a></p></body></html>"
|
||||
AdvSceneSwitcher.windowTitleTab.stayInFocus1="Игнорировать имя этого окна"
|
||||
AdvSceneSwitcher.windowTitleTab.stayInFocus2=" "
|
||||
AdvSceneSwitcher.windowTitleTab.fullscreen="if fullscreen"
|
||||
AdvSceneSwitcher.windowTitleTab.maximized="if maximized"
|
||||
AdvSceneSwitcher.windowTitleTab.focused="if focused"
|
||||
AdvSceneSwitcher.windowTitleTab.entry="{{windows}} {{scenes}} {{transitions}} {{fullscreen}} {{maximized}} {{focused}}"
|
||||
AdvSceneSwitcher.windowTitleTab.windowsHelp="Переключение сцен на основе заголовков окон запущенных приложений.\nВы можете выбрать следующие дополнительные условия:\nОкно полноэкранное\nОкно максимизированное\nОкно сфокусированное\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
AdvSceneSwitcher.windowTitleTab.ignoreWindowsHelp="Если заголовок окна игнорируется, переключатель сцен будет действовать так, как будто ранее выбранное окно все еще в фокусе.\nЭто позволит вам избежать переключения сцен, если вы часто переключаетесь на другое окно, которое не должно вызывать смену сцены.\n\nВыберите окно или введите заголовок окна выше и нажмите на символ плюса ниже, чтобы добавить его в список."
|
||||
|
||||
; Executable Tab
|
||||
AdvSceneSwitcher.executableTab.title="Исполняемый"
|
||||
AdvSceneSwitcher.executableTab.implemented="Implemented by dasOven"
|
||||
AdvSceneSwitcher.executableTab.requiresFocus="только если сфокусирован"
|
||||
AdvSceneSwitcher.executableTab.entry="Когда {{processes}} запущены, переключить на {{scenes}} используя {{transitions}} {{requiresFocus}}"
|
||||
AdvSceneSwitcher.executableTab.help="Эта вкладка позволит вам автоматически переключаться между сценами, если запущен процесс.\nЭто может быть полезно в ситуациях, когда имя окна может измениться или неизвестно.\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
|
||||
; Screen Region Tab
|
||||
AdvSceneSwitcher.screenRegionTab.title="Регион"
|
||||
AdvSceneSwitcher.screenRegionTab.currentPosition="Курсор в данный момент находится в:"
|
||||
AdvSceneSwitcher.screenRegionTab.showGuideFrames="Показать направляющие кадры"
|
||||
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="Скрыть направляющие рамки"
|
||||
AdvSceneSwitcher.screenRegionTab.excludeScenes.None="Нет выбора"
|
||||
AdvSceneSwitcher.screenRegionTab.entry="Если курсор находится в {{minX}} {{minY}} x {{maxX}} {{maxY}} переключить на {{scenes}} используя {{transitions}} если не указано {{excludeScenes}}"
|
||||
AdvSceneSwitcher.screenRegionTab.help="Эта вкладка позволит вам автоматически переключать сцены, основываясь на текущем положении курсора мыши.\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
|
||||
; Media Tab
|
||||
AdvSceneSwitcher.mediaTab.title="Медиа"
|
||||
AdvSceneSwitcher.mediaTab.implemented="Implemented by Exeldro"
|
||||
AdvSceneSwitcher.mediaTab.states.none="Нет"
|
||||
AdvSceneSwitcher.mediaTab.states.playing="Играет"
|
||||
AdvSceneSwitcher.mediaTab.states.opening="Открытие"
|
||||
AdvSceneSwitcher.mediaTab.states.buffering="Буферизация"
|
||||
AdvSceneSwitcher.mediaTab.states.Paused="Приостановлено"
|
||||
AdvSceneSwitcher.mediaTab.states.stopped="Остановлено"
|
||||
AdvSceneSwitcher.mediaTab.states.ended="Закончилось"
|
||||
AdvSceneSwitcher.mediaTab.states.error="Ошибка"
|
||||
AdvSceneSwitcher.mediaTab.states.playedToEnd="Воспроизведено до конца"
|
||||
AdvSceneSwitcher.mediaTab.states.any="Любой"
|
||||
AdvSceneSwitcher.mediaTab.timeRestriction.none="Нет"
|
||||
AdvSceneSwitcher.mediaTab.timeRestriction.shorter="Время короче"
|
||||
AdvSceneSwitcher.mediaTab.timeRestriction.longer="Время больше"
|
||||
AdvSceneSwitcher.mediaTab.timeRestriction.remainShorter="Оставшееся время короче"
|
||||
AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger="Время, оставшееся дольше"
|
||||
AdvSceneSwitcher.mediaTab.entry="Когда состояние {{mediaSources}} равно {{states}} и {{timeRestrictions}} {{time}} переключиться на {{scenes}} используя {{transitions}}"
|
||||
AdvSceneSwitcher.mediaTab.help="Эта вкладка позволит вам переключать сцены на основе состояний медиаисточников.\nНапример, вы можете автоматически переключиться на предыдущую сцену, когда выбранный медиаисточник закончил свое воспроизведение.\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
|
||||
; File Tab
|
||||
AdvSceneSwitcher.fileTab.title="Файл"
|
||||
AdvSceneSwitcher.fileTab.readWriteSceneFile="Считать / записать сцену из / в файл"
|
||||
AdvSceneSwitcher.fileTab.currentSceneOutputFile="Записать имя текущей сцены в этот файл:"
|
||||
AdvSceneSwitcher.fileTab.switchSceneBaseOnFile="Включить переключение сцен на основе ввода файла"
|
||||
AdvSceneSwitcher.fileTab.switchSceneNameInputFile="Считать имя сцены, на которую нужно переключиться, из этого файла:"
|
||||
AdvSceneSwitcher.fileTab.switchSceneBaseOnFileContent="Переключать сцену на основе содержимого файла"
|
||||
AdvSceneSwitcher.fileTab.remoteFileWarning="Обратите внимание, что при выборе опции remote переключатель сцен будет пытаться получить доступ к удаленному местоположению каждые x мс, как указано на вкладке Общие"
|
||||
AdvSceneSwitcher.fileTab.remoteFileWarning1="Обратите внимание, что переключатель сцены будет пытаться получить доступ к удаленному местоположению каждые "
|
||||
AdvSceneSwitcher.fileTab.remoteFileWarning2="ms"
|
||||
AdvSceneSwitcher.fileTab.libcurlWarning="Не удалось загрузить libcurl! Доступ к удаленным файлам невозможен!"
|
||||
AdvSceneSwitcher.fileTab.selectWrite="Выберите файл для записи в ..."
|
||||
AdvSceneSwitcher.fileTab.selectRead="Выберите файл для чтения из ..."
|
||||
AdvSceneSwitcher.fileTab.textFileType="Текстовые файлы (*.txt)"
|
||||
AdvSceneSwitcher.fileTab.anyFileType="Любые файлы (*.*)"
|
||||
AdvSceneSwitcher.fileTab.remote="удаленный файл"
|
||||
AdvSceneSwitcher.fileTab.local="локальный файл"
|
||||
AdvSceneSwitcher.fileTab.useRegExp="использовать регулярные выражения (сопоставление шаблонов)"
|
||||
AdvSceneSwitcher.fileTab.checkfileContentTime="если дата модификации изменена"
|
||||
AdvSceneSwitcher.fileTab.checkfileContent="если содержимое изменено"
|
||||
AdvSceneSwitcher.fileTab.entry="Переключиться на {{scenes}} используя {{transitions}} если содержимое {{fileType}} {{filePath}} {{browseButton}} совпадает:"
|
||||
AdvSceneSwitcher.fileTab.entry2="{{matchText}}"
|
||||
AdvSceneSwitcher.fileTab.entry3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.fileTab.help="Эта вкладка позволит вам автоматически переключать сцены на основе содержимого удаленных или локальных файлов.\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
|
||||
; Random Tab
|
||||
AdvSceneSwitcher.randomTab.title="Рандом"
|
||||
AdvSceneSwitcher.randomTab.randomDisabledWarning="Функциональность отключена - для активации выберите \"Если условие переключения не выполнено, переключиться на любую сцену на вкладке Random\" на вкладке Общие"
|
||||
AdvSceneSwitcher.randomTab.entry="Если условие переключения не выполнено, переключиться на {{scenes}} используя {{transitions}} для {{delay}}"
|
||||
AdvSceneSwitcher.randomTab.help="Переключатель сцен будет случайным образом выбирать запись на этой вкладке для переключения на заданное время.\nЗаметьте, что одна и та же запись не будет выбрана дважды подряд.\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
|
||||
; Time Tab
|
||||
AdvSceneSwitcher.timeTab.title="Время"
|
||||
AdvSceneSwitcher.timeTab.anyDay="В любой день"
|
||||
AdvSceneSwitcher.timeTab.mondays="По понедельникам"
|
||||
AdvSceneSwitcher.timeTab.tuesdays="По вторникам"
|
||||
AdvSceneSwitcher.timeTab.wednesdays="По средам"
|
||||
AdvSceneSwitcher.timeTab.thursdays="По четвергам"
|
||||
AdvSceneSwitcher.timeTab.fridays="По пятницам"
|
||||
AdvSceneSwitcher.timeTab.saturdays="По субботам"
|
||||
AdvSceneSwitcher.timeTab.sundays="По воскресеньям"
|
||||
AdvSceneSwitcher.timeTab.afterstart="После начала потокового вещания/записи"
|
||||
AdvSceneSwitcher.timeTab.afterstart.tip="Будет использоваться время относительно начала потокового вещания/записи"
|
||||
AdvSceneSwitcher.timeTab.entry="{{triggers}} в {{time}} переключаются на {{scenes}} используя {{transitions}}"
|
||||
AdvSceneSwitcher.timeTab.help="Эта вкладка позволит вам автоматически переключаться на другую сцену на основе текущего местного времени.\n\nЗаметьте, что переключатель сцен будет переключаться только в точное время, которое вы указали.\nУбедитесь, что вы настроили параметры приоритета на вкладке Общие по своему вкусу, чтобы выбранная временная точка не была пропущена из-за других методов переключения, имеющих более высокий приоритет.\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
|
||||
; Idle Tab
|
||||
AdvSceneSwitcher.idleTab.title="Бездействие"
|
||||
AdvSceneSwitcher.idleTab.enable="Включить обнаружение простоя"
|
||||
AdvSceneSwitcher.idleTab.idleswitch="После {{duration}} отсутствия ввода с клавиатуры или мыши переключиться на сцену {{scenes}} используя {{transitions}}"
|
||||
AdvSceneSwitcher.idleTab.dontSwitchIfFocus1="Не переключаться, если"
|
||||
AdvSceneSwitcher.idleTab.dontSwitchIfFocus2="находится в фокусе"
|
||||
|
||||
; Scene Sequence Tab
|
||||
AdvSceneSwitcher.sceneSequenceTab.title="Последовательность"
|
||||
AdvSceneSwitcher.sceneSequenceTab.description="Последовательность автоматического переключения сцен может быть отменена либо паузой/остановкой переключателя сцен, либо ручным переключением на другую сцену"
|
||||
AdvSceneSwitcher.sceneSequenceTab.save="Сохранить последовательность сцен в файл"
|
||||
AdvSceneSwitcher.sceneSequenceTab.load="Загрузить последовательности сцен из файла"
|
||||
AdvSceneSwitcher.sceneSequenceTab.saveTitle="Сохранить последовательность сцен в файл ..."
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadTitle="Выберите файл для чтения последовательности сцен из файла ..."
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadFail="Advanced Scene Switcher не удалось импортировать настройки!"
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Настройки Advanced Scene Switcher импортированы успешно!"
|
||||
AdvSceneSwitcher.sceneSequenceTab.fileType="Текстовые файлы (*.txt)"
|
||||
AdvSceneSwitcher.sceneSequenceTab.interruptible="прервать"
|
||||
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Другие методы переключения разрешены для прерывания этой последовательности сцен"
|
||||
AdvSceneSwitcher.sceneSequenceTab.entry="Когда {{startScenes}} активен, переключить на {{scenes}} после {{delay}} используя {{transitions}} {{interruptible}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.extendEdit="Расширить последовательность"
|
||||
AdvSceneSwitcher.sceneSequenceTab.extendEntry="После {{delay}} переключиться на {{scenes}} используя {{transitions}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.help="Эта вкладка позволит вам автоматически переключаться на другую сцену, если сцена была активна в течение заданного периода времени.\nНапример, вы можете автоматически переключаться между двумя сценами.\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
|
||||
; Audio Tab
|
||||
AdvSceneSwitcher.audioTab.title="Аудио"
|
||||
AdvSceneSwitcher.audioTab.condition.above="выше"
|
||||
AdvSceneSwitcher.audioTab.condition.below="ниже"
|
||||
AdvSceneSwitcher.audioTab.ignoreInactiveSource="если источник неактивен"
|
||||
AdvSceneSwitcher.audioTab.entry="Когда громкость {{audioSources}} равна {{condition}} {{volumeWidget}} в течение {{duration}} секунд переключить на {{scenes}} используя {{transitions}} {{ignoreInactiveSource}}"
|
||||
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="Если несколько записей совпадают ..."
|
||||
AdvSceneSwitcher.audioTab.multiMatchfallback="... в течение {{duration}} секунд переключить на {{scenes}} используя {{transitions}}"
|
||||
AdvSceneSwitcher.audioTab.help="Эта вкладка позволит вам переключать сцены в зависимости от громкости источников.\nНапример, вы можете автоматически переключиться на другую сцену, если громкость вашего микрофона достигнет определенного порога.\n\nНажмите на выделенный символ плюса, чтобы продолжить."
|
||||
|
||||
; Video Tab
|
||||
AdvSceneSwitcher.videoTab.title="Видео"
|
||||
AdvSceneSwitcher.videoTab.getScreenshot="Получить снимок экрана для выбранной записи"
|
||||
AdvSceneSwitcher.videoTab.getScreenshotHelp="Получить скриншот источника видео текущей выбранной записи и автоматически установить его в качестве целевого изображени"
|
||||
AdvSceneSwitcher.videoTab.condition.match="точно соответствует"
|
||||
AdvSceneSwitcher.videoTab.condition.match.tooltip="Точное совпадение требует, чтобы целевое и исходное изображение имели одинаковое разрешение.\nДаже каждый пиксель должен совпадать, поэтому не рекомендуется использовать форматы изображений, которые используют сжатие (например, .JPG)!"
|
||||
AdvSceneSwitcher.videoTab.condition.differ="не совпадает"
|
||||
AdvSceneSwitcher.videoTab.condition.hasNotChanged="не изменилось"
|
||||
AdvSceneSwitcher.videoTab.condition.hasChanged="изменилось"
|
||||
AdvSceneSwitcher.videoTab.ignoreInactiveSource="если источник неактивен"
|
||||
AdvSceneSwitcher.videoTab.entry="Когда {{videoSources}} {{condition}} {{filePath}} {{browseButton}} для {{duration}} переключиться на {{scenes}} используя {{transitions}} {{ignoreInactiveSource}}"
|
||||
AdvSceneSwitcher.videoTab.help="<html><head/><body><p>Эта вкладка позволит вам переключать сцены на основе текущего видеовыхода выбранных источников.<br/>Обязательно проверьте <a href=\"https://obsproject.com/forum/resources/pixel-match-switcher.1202/\"><span style=\" text-decoration: underline; color:#268bd2;\">Pixel Match Switcher</span></a> для еще лучшей реализации этой функциональности.<br/><br/> Нажмите на выделенный символ плюса, чтобы продолжить.</p></body></html>"
|
||||
|
||||
; Network Tab
|
||||
AdvSceneSwitcher.networkTab.title="Сеть"
|
||||
AdvSceneSwitcher.networkTab.warning="Запуск сервера вне локальной сети позволит третьим лицам читать активную сцену."
|
||||
AdvSceneSwitcher.networkTab.DisabledWarning="ту функциональность, к сожалению, пришлось отключить на macOS из-за несовместимости библиотек при параллельном запуске плагина obs-websocket."
|
||||
AdvSceneSwitcher.networkTab.server="Запустить сервер (отправляет сообщения о переключении сцены всем подключенным клиентам)"
|
||||
AdvSceneSwitcher.networkTab.server.port="Порт"
|
||||
AdvSceneSwitcher.networkTab.server.lockToIPv4="Заблокировать сервер на использование только IPv4"
|
||||
AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Отправлять сообщения только для автоматических переключателей сцен"
|
||||
AdvSceneSwitcher.networkTab.startFailed.message="Сервер WebSockets не удалось запустить, возможно потому, что:\n - TCP порт %1 может в настоящее время использоваться в другом месте в этой системе, возможно, другим приложением. Попробуйте установить другой TCP порт в настройках сервера WebSocket, или остановите любое приложение, которое может использовать этот порт.\n - Сообщение об ошибке: %2"
|
||||
AdvSceneSwitcher.networkTab.server.status.currentStatus="Текущий статус"
|
||||
AdvSceneSwitcher.networkTab.server.status.notRunning="Не запущен"
|
||||
AdvSceneSwitcher.networkTab.server.status.starting="Запуск"
|
||||
AdvSceneSwitcher.networkTab.server.status.running="Работает"
|
||||
AdvSceneSwitcher.networkTab.server.restart="Перезапустить сервер"
|
||||
AdvSceneSwitcher.networkTab.client="Запустить клиент (Получает сообщения о переключении сцен)"
|
||||
AdvSceneSwitcher.networkTab.client.address="Имя хоста или IP-адрес"
|
||||
AdvSceneSwitcher.networkTab.client.port="Порт"
|
||||
AdvSceneSwitcher.networkTab.client.status.currentStatus="Текущий статус"
|
||||
AdvSceneSwitcher.networkTab.client.status.disconnected="Отключено"
|
||||
AdvSceneSwitcher.networkTab.client.status.connecting="Подключение"
|
||||
AdvSceneSwitcher.networkTab.client.status.connected="Подключено"
|
||||
AdvSceneSwitcher.networkTab.client.reconnect="Принудительное переподключение"
|
||||
|
||||
; Scene Group Tab
|
||||
AdvSceneSwitcher.sceneGroupTab.title="Группа сцен"
|
||||
AdvSceneSwitcher.sceneGroupTab.list="Группы сцен"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit="Редактировать группы сцен"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.name="Имя:"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.type="Тип: {{type}}"
|
||||
AdvSceneSwitcher.sceneGroupTab.type.count="Количество"
|
||||
AdvSceneSwitcher.sceneGroupTab.type.time="Время"
|
||||
AdvSceneSwitcher.sceneGroupTab.type.random="Случайно"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.count="Переход к следующей сцене в списке после {{count}} совпадений"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.time="Переход к следующей сцене в списке по истечении {{time}}"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.random="Выбирать следующую сцену в списке случайным образом"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.repeat="Начинать с начала, если достигнут конец списка сцен"
|
||||
AdvSceneSwitcher.sceneGroupTab.edit.addScene="Добавить сцену"
|
||||
AdvSceneSwitcher.sceneGroupTab.add="Добавить группу сцен"
|
||||
AdvSceneSwitcher.sceneGroupTab.defaultname="Группа сцен %1"
|
||||
AdvSceneSwitcher.sceneGroupTab.exists="Группа сцен или название сцены уже существует"
|
||||
AdvSceneSwitcher.sceneGroupTab.help="Группы сцен могут быть выбраны в качестве цели так же, как и обычные сцены.\n\nКак следует из названия, группа сцен представляет собой набор из нескольких сцен.\nГруппа сцен будет продвигаться по списку назначенных ей сцен в зависимости от настроенных параметров, которые можно найти справа.\n\nВы можете настроить группу сцен на переход к следующей сцене в списке:\nПосле определенного количества раз, когда группа сцен выбрана в качестве цели.\nПо истечении определенного времени.\nИли случайным образом.\n\nНапример, группа сцен, содержащая сцены ...\nScene 1\nScene 2\nScene 3 \n... активирует \"Scene 1\" в первый раз, когда он выбран в качестве цели.\nВо второй раз он активируется \"Scene 2\".\nОставшееся время \"Scene 3\" будет активирован.\n\nНажмите на выделенный символ плюса ниже, чтобы добавить новую группу сцен."
|
||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Выберите группу сцен, которую вы хотите изменить слева.\n\nВыберите сцену для добавления в эту группу сцен, выбрав сцену выше и нажав на символ плюса ниже.\n\nСцена может быть добавлена несколько раз в одну и ту же группу сцен."
|
||||
|
||||
; Scene Trigger Tab
|
||||
AdvSceneSwitcher.sceneTriggerTab.title="Триггеры сцены"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.none="--выбрать триггер--"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneActive="активен"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneInactive="не активен"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerType.sceneLeave="переключился с"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.none="--выбрать действие--"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startRecording="начать запись"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.pauseRecording="приостановить запись"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unpauseRecording="отменить паузу записи"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopRecording="остановить запись"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopStreaming="остановить потоковое вещание"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startStreaming="начать потоковое вещание"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startReplayBuffer="запустить буфер воспроизведения"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopReplayBuffer="остановить буфер воспроизведения"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="отключить источник"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="включить источник"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="запустить переключатель сцены"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="остановить переключатель сцены"
|
||||
AdvSceneSwitcher.sceneTriggerTab.entry="Когда {{scenes}} {{triggers}} {{actions}} {{audioSources}} после {{duration}}"
|
||||
AdvSceneSwitcher.sceneTriggerTab.help="Эта вкладка позволяет запускать действия при изменении сцены, например, остановку записи или потоковой передачи."
|
||||
|
||||
; Hotkey
|
||||
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Запустить Advanced Scene Switcher"
|
||||
AdvSceneSwitcher.hotkey.stopSwitcherHotkey="становить Advanced Scene Switcher"
|
||||
AdvSceneSwitcher.hotkey.startStopToggleSwitcherHotkey="Переключить старт/стоп для Advanced Scene Switcher"
|
||||
|
||||
AdvSceneSwitcher.askBackup="Обнаружена новая версия Advanced Scene Switcher.\nНужно ли создать резервную копию старых настроек?"
|
||||
|
||||
AdvSceneSwitcher.close="Закрыть"
|
||||
AdvSceneSwitcher.browse="Обзор"
|
||||
|
||||
AdvSceneSwitcher.selectScene="--выбрать сцену--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Предыдущая сцена"
|
||||
AdvSceneSwitcher.currentTransition="Текущий переход"
|
||||
AdvSceneSwitcher.selectTransition="--выбрать переход--"
|
||||
AdvSceneSwitcher.selectWindow="--выбрать окно--"
|
||||
AdvSceneSwitcher.selectAudioSource="--выбрать источник звука--"
|
||||
AdvSceneSwitcher.selectVideoSource="--sвыбрать источник видео--"
|
||||
AdvSceneSwitcher.selectMediaSource="--выбрать источник мультимедиа--"
|
||||
AdvSceneSwitcher.selectProcess="--выбрать процесс--"
|
||||
AdvSceneSwitcher.enterPath="--ввести путь--"
|
||||
AdvSceneSwitcher.enterText="--ввести текст--"
|
||||
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="недействительные записи не будут сохранены"
|
||||
AdvSceneSwitcher.selectWindowTip="Используйте \"OBS\" для указания окна OBS\nИспользуйте \"Переключение задач\"для указания ALT + TAB"
|
||||
|
||||
AdvSceneSwitcher.status.active="Активный"
|
||||
AdvSceneSwitcher.status.inactive="Неактивен"
|
||||
|
||||
AdvSceneSwitcher.unit.milliseconds="миллисекунды"
|
||||
AdvSceneSwitcher.unit.secends="секунды"
|
||||
AdvSceneSwitcher.unit.minutes="минуты"
|
||||
AdvSceneSwitcher.unit.hours="часы"
|
||||
@@ -12,20 +12,17 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="总是自动启动"
|
||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="不要启动"
|
||||
AdvSceneSwitcher.generalTab.status.start="启动"
|
||||
AdvSceneSwitcher.generalTab.status.stop="停止"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="录制"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="推流"
|
||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="录制和推流"
|
||||
AdvSceneSwitcher.generalTab.status.checkInterval="检查切换条件时间间隔"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior="一般表现"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.recording="录制"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.streaming="推流"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart.recordingAndStreaming="录制和推流"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart1="自动开始"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStart2="当切换到场景时"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet="如果不符合任何切换条件"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMetDelayTooltip="时间精度最高只能达到配置的轮询间隔"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch="不切换"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom="切换到随机场景列表中任意随机场景"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo="切换到"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.verboseLogging="详细日志输出"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.automaticallyStop="当切换到场景时自动停止推流和录制"
|
||||
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="禁用UI提示"
|
||||
AdvSceneSwitcher.generalTab.priority="优先级"
|
||||
AdvSceneSwitcher.generalTab.priority.description="切换场景优先级 (最上方的项优先级最高)"
|
||||
@@ -53,7 +50,7 @@ AdvSceneSwitcher.generalTab.priority.audio="音频"
|
||||
AdvSceneSwitcher.transitionTab.title="转场特效"
|
||||
AdvSceneSwitcher.transitionTab.transitionOverride="在场景切换器中设定的转场特效优先级高于场景设定的转场特效"
|
||||
AdvSceneSwitcher.transitionTab.transitionForAToB="当自动从场景A切换到场景B时使用的转场特效"
|
||||
AdvSceneSwitcher.transitionTab.transitionForAToB.description="<html><head/><body><p>这里的设定<span style=\"font-style:bold;\">只影响由场景切换器引起的转场有效</span>,不影响你手动的引起的转场。<br/>在这里设定的转场特效优先级高于场景切换器其他地方设置的</p></body></html>"
|
||||
AdvSceneSwitcher.transitionTab.transitionsHelp="<html><head/><body><p>这里的设定<span style=\"font-style:bold;\">只影响由场景切换器引起的转场有效</span>,不影响你手动的引起的转场。<br/>在这里设定的转场特效优先级高于场景切换器其他地方设置的<br/><br/>Click the plus symbol below to continue.</p></body></html>"
|
||||
AdvSceneSwitcher.transitionTab.defaultTransition="当切换到这个场景时修改默认转场特效"
|
||||
AdvSceneSwitcher.transitionTab.switchDefaultLabel="活跃时切换默认转场特效为"
|
||||
AdvSceneSwitcher.transitionTab.entry="从场景 {{scenes}} 切换到场景 {{scenes2}} 时使用转场特效 {{transitions}}"
|
||||
@@ -86,7 +83,7 @@ AdvSceneSwitcher.screenRegionTab.title="屏幕区域"
|
||||
AdvSceneSwitcher.screenRegionTab.currentPosition="鼠标当前位置:"
|
||||
AdvSceneSwitcher.screenRegionTab.showGuideFrames="显示区域边界"
|
||||
AdvSceneSwitcher.screenRegionTab.hideGuideFrames="隐藏区域边界"
|
||||
AdvSceneSwitcher.screenRegionTab.entry="如果鼠标在 {{minX}} {{minY}} x {{maxX}} {{maxY}} 使用转场特效 {{transitions}} 切换到场景 {{scenes}}"
|
||||
AdvSceneSwitcher.screenRegionTab.entry="如果鼠标在 {{minX}} {{minY}} x {{maxX}} {{maxY}} 使用转场特效 {{transitions}} 切换到场景 {{scenes}} unless in {{excludeScenes}}"
|
||||
|
||||
; Media Tab
|
||||
AdvSceneSwitcher.mediaTab.title="媒体"
|
||||
@@ -171,7 +168,7 @@ AdvSceneSwitcher.sceneSequenceTab.loadTitle="从文件加载序列 ..."
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadFail="导入失败"
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="导入失败成功"
|
||||
AdvSceneSwitcher.sceneSequenceTab.fileType="文本文件 (*.txt)"
|
||||
AdvSceneSwitcher.sceneSequenceTab.entry="当场景 {{startScenes}} 被激活 {{delay}} {{delayUnits}}后使用转场特效 {{transitions}} 切换到场景 {{scenes}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.entry="当场景 {{startScenes}} 被激活 {{delay}} 后使用转场特效 {{transitions}} 切换到场景 {{scenes}} {{interruptible}}"
|
||||
|
||||
; Audio Tab
|
||||
AdvSceneSwitcher.audioTab.title="音频"
|
||||
|
||||
15452
data/res/cascadeClassifiers/haarcascade_eye.xml
Normal file
15452
data/res/cascadeClassifiers/haarcascade_eye.xml
Normal file
File diff suppressed because it is too large
Load Diff
33158
data/res/cascadeClassifiers/haarcascade_eye_tree_eyeglasses.xml
Normal file
33158
data/res/cascadeClassifiers/haarcascade_eye_tree_eyeglasses.xml
Normal file
File diff suppressed because it is too large
Load Diff
26161
data/res/cascadeClassifiers/haarcascade_frontalface_alt.xml
Normal file
26161
data/res/cascadeClassifiers/haarcascade_frontalface_alt.xml
Normal file
File diff suppressed because it is too large
Load Diff
23550
data/res/cascadeClassifiers/haarcascade_frontalface_alt2.xml
Normal file
23550
data/res/cascadeClassifiers/haarcascade_frontalface_alt2.xml
Normal file
File diff suppressed because it is too large
Load Diff
103493
data/res/cascadeClassifiers/haarcascade_frontalface_alt_tree.xml
Normal file
103493
data/res/cascadeClassifiers/haarcascade_frontalface_alt_tree.xml
Normal file
File diff suppressed because it is too large
Load Diff
35712
data/res/cascadeClassifiers/haarcascade_frontalface_default.xml
Normal file
35712
data/res/cascadeClassifiers/haarcascade_frontalface_default.xml
Normal file
File diff suppressed because it is too large
Load Diff
18118
data/res/cascadeClassifiers/haarcascade_fullbody.xml
Normal file
18118
data/res/cascadeClassifiers/haarcascade_fullbody.xml
Normal file
File diff suppressed because it is too large
Load Diff
9803
data/res/cascadeClassifiers/haarcascade_lefteye_2splits.xml
Normal file
9803
data/res/cascadeClassifiers/haarcascade_lefteye_2splits.xml
Normal file
File diff suppressed because it is too large
Load Diff
15085
data/res/cascadeClassifiers/haarcascade_lowerbody.xml
Normal file
15085
data/res/cascadeClassifiers/haarcascade_lowerbody.xml
Normal file
File diff suppressed because it is too large
Load Diff
31930
data/res/cascadeClassifiers/haarcascade_profileface.xml
Normal file
31930
data/res/cascadeClassifiers/haarcascade_profileface.xml
Normal file
File diff suppressed because it is too large
Load Diff
9833
data/res/cascadeClassifiers/haarcascade_righteye_2splits.xml
Normal file
9833
data/res/cascadeClassifiers/haarcascade_righteye_2splits.xml
Normal file
File diff suppressed because it is too large
Load Diff
29767
data/res/cascadeClassifiers/haarcascade_upperbody.xml
Normal file
29767
data/res/cascadeClassifiers/haarcascade_upperbody.xml
Normal file
File diff suppressed because it is too large
Load Diff
3
data/res/time.svg
Normal file
3
data/res/time.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M599.62 325.49C599.62 477.26 476.41 600.47 324.64 600.47C172.88 600.47 49.67 477.26 49.67 325.49C49.67 173.73 172.88 50.52 324.64 50.52C476.41 50.52 599.62 173.73 599.62 325.49Z" id="c3Wyq0kfYS"></path><mask id="maskanTyyngos" x="-20.33" y="-19.48" width="689.95" height="689.95" maskUnits="userSpaceOnUse"><rect x="-20.33" y="-19.48" width="689.95" height="689.95" fill="white"></rect><use xlink:href="#c3Wyq0kfYS" opacity="1" fill="black"></use></mask><path d="M334.97 96.07C339.51 96.07 343.2 99.75 343.2 104.3C343.2 151.24 343.2 283.84 343.2 330.78C343.2 335.32 339.51 339 334.97 339C329.2 339 320.09 339 314.31 339C309.77 339 306.09 335.32 306.09 330.78C306.09 283.84 306.09 151.24 306.09 104.3C306.09 99.75 309.77 96.07 314.31 96.07C320.09 96.07 329.2 96.07 334.97 96.07Z" id="fxMeu932c"></path><path d="M471.96 338.21C471.97 341.31 469.46 343.83 466.37 343.84C434.35 343.93 343.92 344.21 311.91 344.31C308.81 344.32 306.3 341.82 306.29 338.72C306.27 332.42 306.23 319.13 306.21 312.83C306.2 309.73 308.7 307.21 311.8 307.2C343.81 307.11 434.24 306.83 466.25 306.73C469.35 306.72 471.87 309.23 471.88 312.32C471.9 318.62 471.94 331.91 471.96 338.21Z" id="h65nGmP2BL"></path></defs><g><g><g><g mask="url(#maskanTyyngos)"><use xlink:href="#c3Wyq0kfYS" opacity="1" fill-opacity="0" stroke="#d2d2d2" stroke-width="70" stroke-opacity="1"></use></g></g><g><use xlink:href="#fxMeu932c" opacity="1" fill="#d2d2d2" fill-opacity="1"></use></g><g><use xlink:href="#h65nGmP2BL" opacity="1" fill="#d2d2d2" fill-opacity="1"></use></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
1
deps/asio
vendored
Submodule
1
deps/asio
vendored
Submodule
Submodule deps/asio added at b73dc1d2c0
1
deps/opencv
vendored
Submodule
1
deps/opencv
vendored
Submodule
Submodule deps/opencv added at ad6e82942b
1
deps/websocketpp
vendored
Submodule
1
deps/websocketpp
vendored
Submodule
Submodule deps/websocketpp added at c6d7e295bf
107
external/FindLibObs.cmake
vendored
107
external/FindLibObs.cmake
vendored
@@ -1,107 +0,0 @@
|
||||
# This module can be copied and used by external plugins for OBS
|
||||
#
|
||||
# Once done these will be defined:
|
||||
#
|
||||
# LIBOBS_FOUND
|
||||
# LIBOBS_INCLUDE_DIRS
|
||||
# LIBOBS_LIBRARIES
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(_OBS QUIET obs libobs)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(_lib_suffix 64)
|
||||
else()
|
||||
set(_lib_suffix 32)
|
||||
endif()
|
||||
|
||||
if(DEFINED CMAKE_BUILD_TYPE)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(_build_type_base "debug")
|
||||
else()
|
||||
set(_build_type_base "release")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_path(LIBOBS_INCLUDE_DIR
|
||||
NAMES obs.h
|
||||
HINTS
|
||||
ENV obsPath${_lib_suffix}
|
||||
ENV obsPath
|
||||
${obsPath}
|
||||
PATHS
|
||||
/usr/include /usr/local/include /opt/local/include /sw/include
|
||||
PATH_SUFFIXES
|
||||
libobs
|
||||
)
|
||||
|
||||
function(find_obs_lib base_name repo_build_path lib_name)
|
||||
string(TOUPPER "${base_name}" base_name_u)
|
||||
|
||||
if(DEFINED _build_type_base)
|
||||
set(_build_type_${repo_build_path} "${_build_type_base}/${repo_build_path}")
|
||||
set(_build_type_${repo_build_path}${_lib_suffix} "${_build_type_base}${_lib_suffix}/${repo_build_path}")
|
||||
endif()
|
||||
|
||||
find_library(${base_name_u}_LIB
|
||||
NAMES ${_${base_name_u}_LIBRARIES} ${lib_name} lib${lib_name}
|
||||
HINTS
|
||||
ENV obsPath${_lib_suffix}
|
||||
ENV obsPath
|
||||
${obsPath}
|
||||
${_${base_name_u}_LIBRARY_DIRS}
|
||||
PATHS
|
||||
/usr/lib /usr/local/lib /opt/local/lib /sw/lib
|
||||
PATH_SUFFIXES
|
||||
lib${_lib_suffix} lib
|
||||
libs${_lib_suffix} libs
|
||||
bin${_lib_suffix} bin
|
||||
../lib${_lib_suffix} ../lib
|
||||
../libs${_lib_suffix} ../libs
|
||||
../bin${_lib_suffix} ../bin
|
||||
# base repo non-msvc-specific search paths
|
||||
${_build_type_${repo_build_path}}
|
||||
${_build_type_${repo_build_path}${_lib_suffix}}
|
||||
build/${repo_build_path}
|
||||
build${_lib_suffix}/${repo_build_path}
|
||||
# base repo msvc-specific search paths on windows
|
||||
build${_lib_suffix}/${repo_build_path}/Debug
|
||||
build${_lib_suffix}/${repo_build_path}/RelWithDebInfo
|
||||
build/${repo_build_path}/Debug
|
||||
build/${repo_build_path}/RelWithDebInfo
|
||||
)
|
||||
endfunction()
|
||||
|
||||
find_obs_lib(LIBOBS libobs obs)
|
||||
|
||||
if(MSVC)
|
||||
find_obs_lib(W32_PTHREADS deps/w32-pthreads w32-pthreads)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Libobs DEFAULT_MSG LIBOBS_LIB LIBOBS_INCLUDE_DIR)
|
||||
mark_as_advanced(LIBOBS_INCLUDE_DIR LIBOBS_LIB)
|
||||
|
||||
if(LIBOBS_FOUND)
|
||||
if(MSVC)
|
||||
if (NOT DEFINED W32_PTHREADS_LIB)
|
||||
message(FATAL_ERROR "Could not find the w32-pthreads library" )
|
||||
endif()
|
||||
|
||||
set(W32_PTHREADS_INCLUDE_DIR ${LIBOBS_INCLUDE_DIR}/../deps/w32-pthreads)
|
||||
endif()
|
||||
|
||||
set(LIBOBS_INCLUDE_DIRS ${LIBOBS_INCLUDE_DIR} ${W32_PTHREADS_INCLUDE_DIR})
|
||||
set(LIBOBS_LIBRARIES ${LIBOBS_LIB} ${W32_PTHREADS_LIB})
|
||||
include(${LIBOBS_INCLUDE_DIR}/../cmake/external/ObsPluginHelpers.cmake)
|
||||
|
||||
# allows external plugins to easily use/share common dependencies that are often included with libobs (such as FFmpeg)
|
||||
if(NOT DEFINED INCLUDED_LIBOBS_CMAKE_MODULES)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LIBOBS_INCLUDE_DIR}/../cmake/Modules/")
|
||||
set(INCLUDED_LIBOBS_CMAKE_MODULES true)
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Could not find the libobs library" )
|
||||
endif()
|
||||
163
external/ObsPluginHelpers.cmake
vendored
163
external/ObsPluginHelpers.cmake
vendored
@@ -1,163 +0,0 @@
|
||||
# Functions for generating external plugins
|
||||
|
||||
set(EXTERNAL_PLUGIN_OUTPUT_DIR "${CMAKE_BINARY_DIR}/rundir")
|
||||
|
||||
# Fix XCode includes to ignore warnings on system includes
|
||||
function(target_include_directories_system _target)
|
||||
if(XCODE)
|
||||
foreach(_arg ${ARGN})
|
||||
if("${_arg}" STREQUAL "PRIVATE" OR "${_arg}" STREQUAL "PUBLIC" OR "${_arg}" STREQUAL "INTERFACE")
|
||||
set(_scope ${_arg})
|
||||
else()
|
||||
target_compile_options(${_target} ${_scope} -isystem${_arg})
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
target_include_directories(${_target} SYSTEM ${_scope} ${ARGN})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(install_external_plugin_data_internal target source_dir target_dir)
|
||||
install(DIRECTORY ${source_dir}/
|
||||
DESTINATION "${target}/${target_dir}"
|
||||
USE_SOURCE_PERMISSIONS)
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${source_dir}" "${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/${target_dir}"
|
||||
VERBATIM)
|
||||
endfunction()
|
||||
|
||||
# Installs data
|
||||
# 'target' is the destination target project being installed to
|
||||
# 'data_loc' specifies the directory of the data
|
||||
function(install_external_plugin_data target data_loc)
|
||||
install_external_plugin_data_internal(${target} ${data_loc} "data")
|
||||
endfunction()
|
||||
|
||||
# Installs data in an architecture-specific data directory on windows/linux (data/32bit or data/64bit). Does not apply for mac.
|
||||
# 'target' is the destination target project being installed to
|
||||
# 'data_loc' specifies the directory of the data being installed
|
||||
function(install_external_plugin_arch_data target data_loc)
|
||||
if(APPLE)
|
||||
set(_bit_suffix "")
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(_bit_suffix "/64bit")
|
||||
else()
|
||||
set(_bit_suffix "/32bit")
|
||||
endif()
|
||||
|
||||
install_external_plugin_data_internal(${target} ${data_loc} "data${_bit_suffix}")
|
||||
endfunction()
|
||||
|
||||
# Installs data in the target's bin directory
|
||||
# 'target' is the destination target project being installed to
|
||||
# 'data_loc' specifies the directory of the data being installed
|
||||
function(install_external_plugin_data_to_bin target data_loc)
|
||||
if(APPLE)
|
||||
set(_bit_suffix "")
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(_bit_suffix "/64bit")
|
||||
else()
|
||||
set(_bit_suffix "/32bit")
|
||||
endif()
|
||||
|
||||
install_external_plugin_data_internal(${target} ${data_loc} "bin${_bit_suffix}")
|
||||
endfunction()
|
||||
|
||||
# Installs an additional binary to a target
|
||||
# 'target' is the destination target project being installed to
|
||||
# 'additional_target' specifies the additional binary
|
||||
function(install_external_plugin_additional target additional_target)
|
||||
if(APPLE)
|
||||
set(_bit_suffix "")
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(_bit_suffix "64bit/")
|
||||
else()
|
||||
set(_bit_suffix "32bit/")
|
||||
endif()
|
||||
|
||||
set_target_properties(${additional_target} PROPERTIES
|
||||
PREFIX "")
|
||||
|
||||
install(TARGETS ${additional_target}
|
||||
LIBRARY DESTINATION "bin"
|
||||
RUNTIME DESTINATION "bin")
|
||||
add_custom_command(TARGET ${additional_target} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||
"$<TARGET_FILE:${additional_target}>"
|
||||
"${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/bin/${_bit_suffix}$<TARGET_FILE_NAME:${additional_target}>"
|
||||
VERBATIM)
|
||||
endfunction()
|
||||
|
||||
# Installs the binary of the target
|
||||
# 'target' is the target project being installed
|
||||
function(install_external_plugin target)
|
||||
install_external_plugin_additional(${target} ${target})
|
||||
endfunction()
|
||||
|
||||
# Installs the binary and data of the target
|
||||
# 'target' is the destination target project being installed to
|
||||
function(install_external_plugin_with_data target data_loc)
|
||||
install_external_plugin(${target})
|
||||
install_external_plugin_data(${target} ${data_loc})
|
||||
endfunction()
|
||||
|
||||
# Installs an additional binary to the data of a target
|
||||
# 'target' is the destination target project being installed to
|
||||
# 'additional_target' specifies the additional binary
|
||||
function(install_external_plugin_bin_to_data target additional_target)
|
||||
install(TARGETS ${additional_target}
|
||||
LIBRARY DESTINATION "data"
|
||||
RUNTIME DESTINATION "data")
|
||||
add_custom_command(TARGET ${additional_target} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||
"$<TARGET_FILE:${additional_target}>"
|
||||
"${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/data/$<TARGET_FILE_NAME:${additional_target}>"
|
||||
VERBATIM)
|
||||
endfunction()
|
||||
|
||||
# Installs an additional binary in an architecture-specific data directory on windows/linux (data/32bit or data/64bit). Does not apply for mac.
|
||||
# 'target' is the destination target project being installed to
|
||||
# 'additional_target' specifies the additional binary
|
||||
function(install_external_plugin_bin_to_arch_data target additional_target)
|
||||
if(APPLE)
|
||||
set(_bit_suffix "")
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(_bit_suffix "/64bit")
|
||||
else()
|
||||
set(_bit_suffix "/32bit")
|
||||
endif()
|
||||
|
||||
install(TARGETS ${additional_target}
|
||||
LIBRARY DESTINATION "data${_bit_suffix}"
|
||||
RUNTIME DESTINATION "data${_bit_suffix}")
|
||||
add_custom_command(TARGET ${additional_target} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||
"$<TARGET_FILE:${additional_target}>"
|
||||
"${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/data${_bit_suffix}/$<TARGET_FILE_NAME:${additional_target}>"
|
||||
VERBATIM)
|
||||
endfunction()
|
||||
|
||||
# Installs an additional file in an architecture-specific data directory on windows/linux (data/32bit or data/64bit). Does not apply for mac.
|
||||
# 'target' is the destination target project being installed to
|
||||
# 'additional_target' specifies the additional binary
|
||||
function(install_external_plugin_data_file_to_arch_data target additional_target file_target)
|
||||
if(APPLE)
|
||||
set(_bit_suffix "")
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(_bit_suffix "/64bit")
|
||||
else()
|
||||
set(_bit_suffix "/32bit")
|
||||
endif()
|
||||
|
||||
get_filename_component(file_target_name ${file_target} NAME)
|
||||
|
||||
install(TARGETS ${additional_target}
|
||||
LIBRARY DESTINATION "data${_bit_suffix}"
|
||||
RUNTIME DESTINATION "data${_bit_suffix}")
|
||||
add_custom_command(TARGET ${additional_target} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||
"${file_target}"
|
||||
"${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/data${_bit_suffix}/${file_target_name}"
|
||||
VERBATIM)
|
||||
endfunction()
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,17 @@ bool resolveCurl()
|
||||
|
||||
bool loadCurl()
|
||||
{
|
||||
loaded_curl_lib = new QLibrary(curl_library_name, nullptr);
|
||||
if (resolveCurl()) {
|
||||
blog(LOG_INFO, "[adv-ss] found curl library");
|
||||
return true;
|
||||
} else {
|
||||
delete loaded_curl_lib;
|
||||
loaded_curl_lib = nullptr;
|
||||
blog(LOG_WARNING,
|
||||
"[adv-ss] couldn't find the curl library in PATH");
|
||||
}
|
||||
|
||||
QStringList locations;
|
||||
locations << QDir::currentPath();
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
@@ -54,9 +65,9 @@ bool loadCurl()
|
||||
libFilePath.toUtf8().constData());
|
||||
|
||||
loaded_curl_lib = new QLibrary(libFilePath, nullptr);
|
||||
if (resolveCurl())
|
||||
if (resolveCurl()) {
|
||||
return true;
|
||||
else {
|
||||
} else {
|
||||
delete loaded_curl_lib;
|
||||
loaded_curl_lib = nullptr;
|
||||
}
|
||||
|
||||
291
src/duration-control.cpp
Normal file
291
src/duration-control.cpp
Normal file
@@ -0,0 +1,291 @@
|
||||
#include "headers/duration-control.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "obs-module.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
void Duration::Save(obs_data_t *obj, const char *secondsName,
|
||||
const char *unitName)
|
||||
{
|
||||
obs_data_set_double(obj, secondsName, seconds);
|
||||
obs_data_set_int(obj, unitName, static_cast<int>(displayUnit));
|
||||
}
|
||||
|
||||
void Duration::Load(obs_data_t *obj, const char *secondsName,
|
||||
const char *unitName)
|
||||
{
|
||||
seconds = obs_data_get_double(obj, secondsName);
|
||||
displayUnit =
|
||||
static_cast<DurationUnit>(obs_data_get_int(obj, unitName));
|
||||
}
|
||||
|
||||
bool Duration::DurationReached()
|
||||
{
|
||||
if (_startTime.time_since_epoch().count() == 0) {
|
||||
_startTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
auto runTime = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::high_resolution_clock::now() - _startTime);
|
||||
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::SetTimeRemaining(double remaining)
|
||||
{
|
||||
long long msPassed = (seconds - remaining) * 1000;
|
||||
_startTime = std::chrono::high_resolution_clock::now() -
|
||||
std::chrono::milliseconds(msPassed);
|
||||
}
|
||||
|
||||
void Duration::Reset()
|
||||
{
|
||||
_startTime = {};
|
||||
}
|
||||
|
||||
int durationUnitToMultiplier(DurationUnit u)
|
||||
{
|
||||
switch (u) {
|
||||
case DurationUnit::SECONDS:
|
||||
return 1;
|
||||
case DurationUnit::MINUTES:
|
||||
return 60;
|
||||
case DurationUnit::HOURS:
|
||||
return 3600;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string durationUnitToString(DurationUnit u)
|
||||
{
|
||||
switch (u) {
|
||||
case DurationUnit::SECONDS:
|
||||
return obs_module_text("AdvSceneSwitcher.unit.secends");
|
||||
case DurationUnit::MINUTES:
|
||||
return obs_module_text("AdvSceneSwitcher.unit.minutes");
|
||||
case DurationUnit::HOURS:
|
||||
return obs_module_text("AdvSceneSwitcher.unit.hours");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string Duration::ToString()
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << std::fixed << std::setprecision(2)
|
||||
<< seconds / durationUnitToMultiplier(displayUnit) << " "
|
||||
<< durationUnitToString(displayUnit);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static void populateUnits(QComboBox *list)
|
||||
{
|
||||
list->addItem(obs_module_text("AdvSceneSwitcher.unit.secends"));
|
||||
list->addItem(obs_module_text("AdvSceneSwitcher.unit.minutes"));
|
||||
list->addItem(obs_module_text("AdvSceneSwitcher.unit.hours"));
|
||||
}
|
||||
|
||||
DurationSelection::DurationSelection(QWidget *parent, bool showUnitSelection)
|
||||
: QWidget(parent), _unitMultiplier(1)
|
||||
{
|
||||
_duration = new QDoubleSpinBox(parent);
|
||||
_duration->setMaximum(86400); // 24 hours
|
||||
|
||||
_unitSelection = new QComboBox();
|
||||
populateUnits(_unitSelection);
|
||||
|
||||
QWidget::connect(_duration, SIGNAL(valueChanged(double)), this,
|
||||
SLOT(_DurationChanged(double)));
|
||||
QWidget::connect(_unitSelection, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(_UnitChanged(int)));
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(11);
|
||||
layout->addWidget(_duration);
|
||||
if (showUnitSelection) {
|
||||
layout->addWidget(_unitSelection);
|
||||
}
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void DurationSelection::SetValue(double value)
|
||||
{
|
||||
_duration->setValue(value / _unitMultiplier);
|
||||
}
|
||||
|
||||
void DurationSelection::SetUnit(DurationUnit u)
|
||||
{
|
||||
_unitSelection->setCurrentIndex(static_cast<int>(u));
|
||||
}
|
||||
|
||||
void DurationSelection::SetDuration(Duration d)
|
||||
{
|
||||
SetUnit(d.displayUnit);
|
||||
SetValue(d.seconds);
|
||||
}
|
||||
|
||||
void DurationSelection::_DurationChanged(double value)
|
||||
{
|
||||
emit DurationChanged(value * _unitMultiplier);
|
||||
}
|
||||
|
||||
void DurationSelection::_UnitChanged(int idx)
|
||||
{
|
||||
DurationUnit unit = static_cast<DurationUnit>(idx);
|
||||
double prevMultiplier = _unitMultiplier;
|
||||
_unitMultiplier = durationUnitToMultiplier(unit);
|
||||
_duration->setValue(_duration->value() *
|
||||
(prevMultiplier / _unitMultiplier));
|
||||
|
||||
emit UnitChanged(unit);
|
||||
}
|
||||
|
||||
void DurationConstraint::Save(obs_data_t *obj, const char *condName,
|
||||
const char *secondsName, const char *unitName)
|
||||
{
|
||||
obs_data_set_int(obj, condName, static_cast<int>(_type));
|
||||
_dur.Save(obj, secondsName, unitName);
|
||||
}
|
||||
|
||||
void DurationConstraint::Load(obs_data_t *obj, const char *condName,
|
||||
const char *secondsName, const char *unitName)
|
||||
{
|
||||
// For backwards compatability check if duration value exist without
|
||||
// time constraint condition - if so assume DurationCondition::MORE
|
||||
if (!obs_data_has_user_value(obj, condName) &&
|
||||
obs_data_has_user_value(obj, secondsName)) {
|
||||
obs_data_set_int(obj, condName,
|
||||
static_cast<int>(DurationCondition::MORE));
|
||||
}
|
||||
|
||||
_type = static_cast<DurationCondition>(obs_data_get_int(obj, condName));
|
||||
_dur.Load(obj, secondsName, unitName);
|
||||
}
|
||||
|
||||
bool DurationConstraint::DurationReached()
|
||||
{
|
||||
switch (_type) {
|
||||
case DurationCondition::NONE:
|
||||
return true;
|
||||
break;
|
||||
case DurationCondition::MORE:
|
||||
return _dur.DurationReached();
|
||||
break;
|
||||
case DurationCondition::EQUAL:
|
||||
if (_dur.DurationReached() && !_timeReached) {
|
||||
_timeReached = true;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case DurationCondition::LESS:
|
||||
return !_dur.DurationReached();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DurationConstraint::Reset()
|
||||
{
|
||||
_timeReached = false;
|
||||
_dur.Reset();
|
||||
}
|
||||
|
||||
static void populateConditions(QComboBox *list)
|
||||
{
|
||||
list->addItem(
|
||||
obs_module_text("AdvSceneSwitcher.duration.condition.none"));
|
||||
list->addItem(
|
||||
obs_module_text("AdvSceneSwitcher.duration.condition.more"));
|
||||
list->addItem(
|
||||
obs_module_text("AdvSceneSwitcher.duration.condition.equal"));
|
||||
list->addItem(
|
||||
obs_module_text("AdvSceneSwitcher.duration.condition.less"));
|
||||
}
|
||||
|
||||
DurationConstraintEdit::DurationConstraintEdit(QWidget *parent)
|
||||
{
|
||||
_condition = new QComboBox(parent);
|
||||
_duration = new DurationSelection(parent);
|
||||
_toggle = new QPushButton(parent);
|
||||
_toggle->setMaximumSize(22, 22);
|
||||
_toggle->setIcon(
|
||||
QIcon(QString::fromStdString(getDataFilePath("res/time.svg"))));
|
||||
populateConditions(_condition);
|
||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(_ConditionChanged(int)));
|
||||
QObject::connect(_duration, &DurationSelection::DurationChanged, this,
|
||||
&DurationConstraintEdit::DurationChanged);
|
||||
QObject::connect(_duration, &DurationSelection::UnitChanged, this,
|
||||
&DurationConstraintEdit::UnitChanged);
|
||||
QWidget::connect(_toggle, SIGNAL(clicked()), this,
|
||||
SLOT(ToggleClicked()));
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(11);
|
||||
layout->addWidget(_toggle);
|
||||
layout->addWidget(_condition);
|
||||
layout->addWidget(_duration);
|
||||
setLayout(layout);
|
||||
Collapse(true);
|
||||
}
|
||||
|
||||
void DurationConstraintEdit::SetValue(DurationConstraint &value)
|
||||
{
|
||||
_duration->SetDuration(value.GetDuration());
|
||||
_condition->setCurrentIndex(static_cast<int>(value.GetCondition()));
|
||||
_duration->setVisible(value.GetCondition() != DurationCondition::NONE);
|
||||
}
|
||||
|
||||
void DurationConstraintEdit::SetUnit(DurationUnit u)
|
||||
{
|
||||
_duration->SetUnit(u);
|
||||
}
|
||||
|
||||
void DurationConstraintEdit::SetDuration(const Duration &d)
|
||||
{
|
||||
_duration->SetDuration(d);
|
||||
}
|
||||
|
||||
void DurationConstraintEdit::_ConditionChanged(int value)
|
||||
{
|
||||
auto cond = static_cast<DurationCondition>(value);
|
||||
Collapse(cond == DurationCondition::NONE);
|
||||
emit ConditionChanged(cond);
|
||||
}
|
||||
|
||||
void DurationConstraintEdit::ToggleClicked()
|
||||
{
|
||||
Collapse(false);
|
||||
}
|
||||
|
||||
void DurationConstraintEdit::Collapse(bool collapse)
|
||||
{
|
||||
_toggle->setVisible(collapse);
|
||||
_duration->setVisible(!collapse);
|
||||
_condition->setVisible(!collapse);
|
||||
}
|
||||
49
src/file-selection.cpp
Normal file
49
src/file-selection.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "headers/file-selection.hpp"
|
||||
|
||||
#include <obs-module.h>
|
||||
#include <QLayout>
|
||||
#include <QFileDialog>
|
||||
|
||||
FileSelection::FileSelection(FileSelection::Type type, QWidget *parent)
|
||||
: QWidget(parent), _type(type)
|
||||
{
|
||||
_filePath = new QLineEdit();
|
||||
_browseButton =
|
||||
new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
|
||||
|
||||
QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
|
||||
SLOT(PathChange()));
|
||||
QWidget::connect(_browseButton, SIGNAL(clicked()), this,
|
||||
SLOT(BrowseButtonClicked()));
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
layout->addWidget(_filePath);
|
||||
layout->addWidget(_browseButton);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void FileSelection::SetPath(const QString &path)
|
||||
{
|
||||
_filePath->setText(path);
|
||||
}
|
||||
|
||||
void FileSelection::BrowseButtonClicked()
|
||||
{
|
||||
QString path;
|
||||
if (_type == FileSelection::Type::WRITE) {
|
||||
path = QFileDialog::getSaveFileName(this);
|
||||
} else {
|
||||
path = QFileDialog::getOpenFileName(this);
|
||||
}
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_filePath->setText(path);
|
||||
emit PathChanged(path);
|
||||
}
|
||||
|
||||
void FileSelection::PathChange()
|
||||
{
|
||||
emit PathChanged(_filePath->text());
|
||||
}
|
||||
935
src/general.cpp
935
src/general.cpp
File diff suppressed because it is too large
Load Diff
@@ -5,10 +5,17 @@
|
||||
#include "ui_advanced-scene-switcher.h"
|
||||
#endif
|
||||
#include "switcher-data-structs.hpp"
|
||||
#include "platform-funcs.hpp"
|
||||
|
||||
#define blog(level, msg, ...) blog(level, "[adv-ss] " msg, ##__VA_ARGS__)
|
||||
#define vblog(level, msg, ...) \
|
||||
if (switcher->verbose) { \
|
||||
blog(level, msg, ##__VA_ARGS__); \
|
||||
}
|
||||
|
||||
class QCloseEvent;
|
||||
class MacroActionEdit;
|
||||
class MacroConditionEdit;
|
||||
|
||||
/*******************************************************************************
|
||||
* Advanced Scene Switcher window
|
||||
@@ -19,9 +26,12 @@ class AdvSceneSwitcher : public QDialog {
|
||||
public:
|
||||
std::unique_ptr<Ui_AdvSceneSwitcher> ui;
|
||||
bool loading = true;
|
||||
bool currentStatusActive = false;
|
||||
|
||||
AdvSceneSwitcher(QWidget *parent);
|
||||
~AdvSceneSwitcher();
|
||||
|
||||
void reject() override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
void SetStarted();
|
||||
@@ -35,10 +45,20 @@ public:
|
||||
int IgnoreIdleWindowsFindByData(const QString &window);
|
||||
|
||||
void UpdateNonMatchingScene(const QString &name);
|
||||
void UpdateAutoStopScene(const QString &name);
|
||||
void UpdateAutoStartScene(const QString &name);
|
||||
void UpdateIdleDataTransition(const QString &name);
|
||||
void UpdateIdleDataScene(const QString &name);
|
||||
void OpenSequenceExtendEdit(SequenceWidget *sw);
|
||||
void SetEditSceneGroup(SceneGroup &sg);
|
||||
|
||||
bool addNewMacro(std::string &name);
|
||||
Macro *getSelectedMacro();
|
||||
void SetEditMacro(Macro &m);
|
||||
void HighlightAction(int idx);
|
||||
void HighlightCondition(int idx);
|
||||
void PopulateMacroActions(Macro &m, uint32_t afterIdx = 0);
|
||||
void PopulateMacroConditions(Macro &m, uint32_t afterIdx = 0);
|
||||
void ConnectControlSignals(MacroActionEdit *);
|
||||
void ConnectControlSignals(MacroConditionEdit *);
|
||||
void SwapActions(Macro *m, int pos1, int pos2);
|
||||
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||
|
||||
void loadUI();
|
||||
void setupGeneralTab();
|
||||
@@ -54,30 +74,21 @@ public:
|
||||
void setupFileTab();
|
||||
void setupTimeTab();
|
||||
void setupAudioTab();
|
||||
void setupSceneGroupTab();
|
||||
void setupTriggerTab();
|
||||
void setupVideoTab();
|
||||
void setupNetworkTab();
|
||||
void setupMacroTab();
|
||||
void setTabOrder();
|
||||
void restoreWindowGeo();
|
||||
|
||||
static void populateSceneSelection(QComboBox *sel,
|
||||
bool addPrevious = false,
|
||||
bool addSelect = true);
|
||||
static void populateTransitionSelection(QComboBox *sel,
|
||||
bool addSelect = true);
|
||||
static void populateWindowSelection(QComboBox *sel,
|
||||
bool addSelect = true);
|
||||
static void populateAudioSelection(QComboBox *sel,
|
||||
bool addSelect = true);
|
||||
static void populateMediaSelection(QComboBox *sel,
|
||||
bool addSelect = true);
|
||||
static void populateProcessSelection(QComboBox *sel,
|
||||
bool addSelect = true);
|
||||
QMetaObject::Connection PulseWidget(QWidget *widget, QColor endColor,
|
||||
QColor = QColor(0, 0, 0, 0),
|
||||
QString specifier = "QLabel ");
|
||||
|
||||
void listAddClicked(QListWidget *list, SwitchWidget *newWidget,
|
||||
QPushButton *addButton = nullptr,
|
||||
QMetaObject::Connection *addHighlight = nullptr);
|
||||
bool listMoveUp(QListWidget *list);
|
||||
bool listMoveDown(QListWidget *list);
|
||||
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);
|
||||
|
||||
public slots:
|
||||
void on_windowUp_clicked();
|
||||
@@ -87,14 +98,46 @@ public slots:
|
||||
void on_noMatchDontSwitch_clicked();
|
||||
void on_noMatchSwitch_clicked();
|
||||
void on_noMatchRandomSwitch_clicked();
|
||||
void on_noMatchDelay_valueChanged(double i);
|
||||
void NoMatchDelayDurationChanged(double);
|
||||
void NoMatchDelayUnitChanged(DurationUnit);
|
||||
void CooldownDurationChanged(double);
|
||||
void CooldownUnitChanged(DurationUnit);
|
||||
void on_startupBehavior_currentIndexChanged(int index);
|
||||
void on_autoStartEvent_currentIndexChanged(int index);
|
||||
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
||||
void on_checkInterval_valueChanged(int value);
|
||||
void on_toggleStartButton_clicked();
|
||||
void on_tabMoved(int from, int to);
|
||||
void on_tabWidget_currentChanged(int index);
|
||||
|
||||
void on_macroAdd_clicked();
|
||||
void on_macroRemove_clicked();
|
||||
void on_macroUp_clicked();
|
||||
void on_macroDown_clicked();
|
||||
void on_macroName_editingFinished();
|
||||
void on_macros_currentRowChanged(int idx);
|
||||
void on_macros_itemChanged(QListWidgetItem *);
|
||||
void on_conditionAdd_clicked();
|
||||
void on_conditionRemove_clicked();
|
||||
void on_actionAdd_clicked();
|
||||
void on_actionRemove_clicked();
|
||||
void ShowMacroContextMenu(const QPoint &);
|
||||
void ShowMacroActionsContextMenu(const QPoint &);
|
||||
void ShowMacroConditionsContextMenu(const QPoint &);
|
||||
void CopyMacro();
|
||||
void ExpandAllActions();
|
||||
void ExpandAllConditions();
|
||||
void CollapseAllActions();
|
||||
void CollapseAllConditions();
|
||||
void AddMacroAction(int idx);
|
||||
void RemoveMacroAction(int idx);
|
||||
void MoveMacroActionUp(int idx);
|
||||
void MoveMacroActionDown(int idx);
|
||||
void AddMacroCondition(int idx);
|
||||
void RemoveMacroCondition(int idx);
|
||||
void MoveMacroConditionUp(int idx);
|
||||
void MoveMacroConditionDown(int idx);
|
||||
|
||||
void on_screenRegionSwitches_currentRowChanged(int idx);
|
||||
void on_showFrame_clicked();
|
||||
void on_screenRegionAdd_clicked();
|
||||
@@ -113,19 +156,16 @@ public slots:
|
||||
|
||||
void on_sceneSequenceAdd_clicked();
|
||||
void on_sceneSequenceRemove_clicked();
|
||||
void on_sceneSequenceSave_clicked();
|
||||
void on_sceneSequenceLoad_clicked();
|
||||
void on_sceneSequenceUp_clicked();
|
||||
void on_sceneSequenceDown_clicked();
|
||||
|
||||
void on_autoStopSceneCheckBox_stateChanged(int state);
|
||||
void on_autoStopScenes_currentTextChanged(const QString &text);
|
||||
|
||||
void on_autoStartSceneCheckBox_stateChanged(int state);
|
||||
void on_autoStartType_currentIndexChanged(int index);
|
||||
void on_autoStartScenes_currentTextChanged(const QString &text);
|
||||
void on_sceneSequenceSave_clicked();
|
||||
void on_sceneSequenceLoad_clicked();
|
||||
void on_sequenceEdit_clicked();
|
||||
void on_sceneSequenceSwitches_itemDoubleClicked(QListWidgetItem *item);
|
||||
|
||||
void on_verboseLogging_stateChanged(int state);
|
||||
void on_saveWindowGeo_stateChanged(int state);
|
||||
void on_showTrayNotifications_stateChanged(int state);
|
||||
void on_uiHintsDisable_stateChanged(int state);
|
||||
|
||||
void on_exportSettings_clicked();
|
||||
@@ -140,6 +180,8 @@ public slots:
|
||||
void on_defaultTransitionsUp_clicked();
|
||||
void on_defaultTransitionsDown_clicked();
|
||||
void on_transitionOverridecheckBox_stateChanged(int state);
|
||||
void on_adjustActiveTransitionType_stateChanged(int state);
|
||||
void defTransitionDelayValueChanged(int value);
|
||||
|
||||
void on_browseButton_clicked();
|
||||
void on_readFileCheckBox_stateChanged(int state);
|
||||
@@ -153,9 +195,6 @@ public slots:
|
||||
void on_executableRemove_clicked();
|
||||
|
||||
void on_idleCheckBox_stateChanged(int state);
|
||||
void on_idleTransitions_currentTextChanged(const QString &text);
|
||||
void on_idleScenes_currentTextChanged(const QString &text);
|
||||
void on_idleSpinBox_valueChanged(int i);
|
||||
void on_ignoreIdleWindows_currentRowChanged(int idx);
|
||||
void on_ignoreIdleAdd_clicked();
|
||||
void on_ignoreIdleRemove_clicked();
|
||||
@@ -183,58 +222,71 @@ public slots:
|
||||
void on_audioRemove_clicked();
|
||||
void on_audioUp_clicked();
|
||||
void on_audioDown_clicked();
|
||||
void on_audioFallback_toggled(bool on);
|
||||
|
||||
void on_videoAdd_clicked();
|
||||
void on_videoRemove_clicked();
|
||||
void on_videoUp_clicked();
|
||||
void on_videoDown_clicked();
|
||||
void on_getScreenshot_clicked();
|
||||
|
||||
void on_serverSettings_toggled(bool on);
|
||||
void on_serverPort_valueChanged(int value);
|
||||
void on_lockToIPv4_stateChanged(int state);
|
||||
void on_serverRestart_clicked();
|
||||
void updateServerStatus();
|
||||
void on_clientSettings_toggled(bool on);
|
||||
void on_clientHostname_textChanged(const QString &text);
|
||||
void on_clientPort_valueChanged(int value);
|
||||
void on_sendSceneChange_stateChanged(int state);
|
||||
void on_restrictSend_stateChanged(int state);
|
||||
void on_sendPreview_stateChanged(int state);
|
||||
void on_clientReconnect_clicked();
|
||||
void updateClientStatus();
|
||||
|
||||
void on_sceneGroupAdd_clicked();
|
||||
void on_sceneGroupRemove_clicked();
|
||||
void on_sceneGroupUp_clicked();
|
||||
void on_sceneGroupDown_clicked();
|
||||
void on_sceneGroupName_editingFinished();
|
||||
void on_sceneGroups_currentRowChanged(int idx);
|
||||
|
||||
void on_sceneGroupSceneAdd_clicked();
|
||||
void on_sceneGroupSceneRemove_clicked();
|
||||
void on_sceneGroupSceneUp_clicked();
|
||||
void on_sceneGroupSceneDown_clicked();
|
||||
|
||||
void on_triggerAdd_clicked();
|
||||
void on_triggerRemove_clicked();
|
||||
void on_triggerUp_clicked();
|
||||
void on_triggerDown_clicked();
|
||||
|
||||
void on_priorityUp_clicked();
|
||||
void on_priorityDown_clicked();
|
||||
void on_threadPriority_currentTextChanged(const QString &text);
|
||||
|
||||
void updateScreenRegionCursorPos();
|
||||
void updateStatus();
|
||||
|
||||
void on_close_clicked();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
/********************************************************************************
|
||||
* Windowtitle helper
|
||||
********************************************************************************/
|
||||
void GetWindowList(std::vector<std::string> &windows);
|
||||
void GetWindowList(QStringList &windows); // Overloaded
|
||||
void GetCurrentWindowTitle(std::string &title);
|
||||
bool isFullscreen(std::string &title);
|
||||
bool isMaximized(std::string &title);
|
||||
|
||||
/********************************************************************************
|
||||
* Screenregion helper
|
||||
********************************************************************************/
|
||||
std::pair<int, int> getCursorPos();
|
||||
|
||||
/********************************************************************************
|
||||
* Idle detection helper
|
||||
********************************************************************************/
|
||||
int secondsSinceLastInput();
|
||||
|
||||
/********************************************************************************
|
||||
* Executable helper
|
||||
********************************************************************************/
|
||||
void GetProcessList(QStringList &processes);
|
||||
bool isInFocus(const QString &executable);
|
||||
|
||||
/********************************************************************************
|
||||
/******************************************************************************
|
||||
* Sceneswitch helper
|
||||
********************************************************************************/
|
||||
******************************************************************************/
|
||||
|
||||
void setNextTransition(OBSWeakSource &targetScene, obs_source_t *currentSource,
|
||||
OBSWeakSource &transition,
|
||||
bool &transitionOverrideOverride, transitionData &td);
|
||||
void overwriteTransitionOverride(obs_weak_source_t *sceneWs,
|
||||
obs_source_t *transition, transitionData &td);
|
||||
void restoreTransitionOverride(obs_source_t *scene, transitionData td);
|
||||
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||
bool &transitionOverrideOverride);
|
||||
void setNextTransition(const sceneSwitchInfo &ssi, obs_source_t *currentSource,
|
||||
transitionData &td);
|
||||
void overwriteTransitionOverride(const sceneSwitchInfo &ssi,
|
||||
transitionData &td);
|
||||
void restoreTransitionOverride(obs_source_t *scene, const transitionData &td);
|
||||
void switchScene(const sceneSwitchInfo &ssi);
|
||||
void switchPreviewScene(const OBSWeakSource &ws);
|
||||
|
||||
/********************************************************************************
|
||||
/******************************************************************************
|
||||
* Main SwitcherData
|
||||
********************************************************************************/
|
||||
******************************************************************************/
|
||||
struct SwitcherData;
|
||||
extern SwitcherData *switcher;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#if defined(WIN32)
|
||||
constexpr auto curl_library_name = "libcurl.dll";
|
||||
#elif __APPLE__
|
||||
#define curl_library_name "libcurl.4.dylib"
|
||||
constexpr auto curl_library_name = "libcurl.4.dylib";
|
||||
#else
|
||||
#define curl_library_name "libcurl.so.4"
|
||||
constexpr auto curl_library_name = "libcurl.so.4";
|
||||
#endif
|
||||
|
||||
typedef CURL *(*initFunction)(void);
|
||||
|
||||
112
src/headers/duration-control.hpp
Normal file
112
src/headers/duration-control.hpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
#include <QWidget>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <chrono>
|
||||
|
||||
#include "obs-data.h"
|
||||
|
||||
enum class DurationUnit {
|
||||
SECONDS,
|
||||
MINUTES,
|
||||
HOURS,
|
||||
};
|
||||
|
||||
class Duration {
|
||||
public:
|
||||
void Save(obs_data_t *obj, const char *secondsName = "seconds",
|
||||
const char *unitName = "displayUnit");
|
||||
void Load(obs_data_t *obj, const char *secondsName = "seconds",
|
||||
const char *unitName = "displayUnit");
|
||||
|
||||
bool DurationReached();
|
||||
double TimeRemaining();
|
||||
void SetTimeRemaining(double);
|
||||
void Reset();
|
||||
std::string ToString();
|
||||
|
||||
double seconds = 0.;
|
||||
// only used for UI
|
||||
DurationUnit displayUnit = DurationUnit::SECONDS;
|
||||
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point _startTime;
|
||||
};
|
||||
|
||||
class DurationSelection : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DurationSelection(QWidget *parent = nullptr,
|
||||
bool showUnitSelection = true);
|
||||
void SetValue(double value);
|
||||
void SetUnit(DurationUnit u);
|
||||
void SetDuration(Duration d);
|
||||
|
||||
private slots:
|
||||
void _DurationChanged(double value);
|
||||
void _UnitChanged(int idx);
|
||||
signals:
|
||||
void DurationChanged(double value); // always reutrn value in seconds
|
||||
void UnitChanged(DurationUnit u);
|
||||
|
||||
private:
|
||||
QDoubleSpinBox *_duration;
|
||||
QComboBox *_unitSelection;
|
||||
|
||||
double _unitMultiplier;
|
||||
};
|
||||
|
||||
enum class DurationCondition {
|
||||
NONE,
|
||||
MORE,
|
||||
EQUAL,
|
||||
LESS,
|
||||
};
|
||||
|
||||
class DurationConstraint {
|
||||
public:
|
||||
void Save(obs_data_t *obj, const char *condName = "time_constraint",
|
||||
const char *secondsName = "seconds",
|
||||
const char *unitName = "displayUnit");
|
||||
void Load(obs_data_t *obj, const char *condName = "time_constraint",
|
||||
const char *secondsName = "seconds",
|
||||
const char *unitName = "displayUnit");
|
||||
void SetCondition(DurationCondition cond) { _type = cond; }
|
||||
void SetDuration(const Duration &dur) { _dur = dur; }
|
||||
void SetValue(double value) { _dur.seconds = value; }
|
||||
void SetUnit(DurationUnit u) { _dur.displayUnit = u; }
|
||||
DurationCondition GetCondition() { return _type; }
|
||||
Duration GetDuration() { return _dur; }
|
||||
bool DurationReached();
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
DurationCondition _type = DurationCondition::NONE;
|
||||
Duration _dur;
|
||||
bool _timeReached = false;
|
||||
};
|
||||
|
||||
class DurationConstraintEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DurationConstraintEdit(QWidget *parent = nullptr);
|
||||
void SetValue(DurationConstraint &value);
|
||||
void SetUnit(DurationUnit u);
|
||||
void SetDuration(const Duration &d);
|
||||
|
||||
private slots:
|
||||
void _ConditionChanged(int value);
|
||||
void ToggleClicked();
|
||||
signals:
|
||||
void DurationChanged(double value);
|
||||
void UnitChanged(DurationUnit u);
|
||||
void ConditionChanged(DurationCondition value);
|
||||
|
||||
private:
|
||||
void Collapse(bool collapse);
|
||||
|
||||
DurationSelection *_duration;
|
||||
QComboBox *_condition;
|
||||
QPushButton *_toggle;
|
||||
};
|
||||
30
src/headers/file-selection.hpp
Normal file
30
src/headers/file-selection.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
|
||||
class FileSelection : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class Type {
|
||||
READ,
|
||||
WRITE,
|
||||
};
|
||||
|
||||
FileSelection(FileSelection::Type type = FileSelection::Type::READ,
|
||||
QWidget *parent = 0);
|
||||
void SetPath(const QString &);
|
||||
QPushButton *Button() { return _browseButton; }
|
||||
|
||||
private slots:
|
||||
void BrowseButtonClicked();
|
||||
void PathChange();
|
||||
signals:
|
||||
void PathChanged(const QString &);
|
||||
|
||||
private:
|
||||
Type _type;
|
||||
QLineEdit *_filePath;
|
||||
QPushButton *_browseButton;
|
||||
};
|
||||
125
src/headers/hotkey.hpp
Normal file
125
src/headers/hotkey.hpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#pragma once
|
||||
|
||||
extern bool canSimulateKeyPresses;
|
||||
|
||||
enum class HotkeyType {
|
||||
Key_NoKey = 0,
|
||||
|
||||
Key_A,
|
||||
Key_B,
|
||||
Key_C,
|
||||
Key_D,
|
||||
Key_E,
|
||||
Key_F,
|
||||
Key_G,
|
||||
Key_H,
|
||||
Key_I,
|
||||
Key_J,
|
||||
Key_K,
|
||||
Key_L,
|
||||
Key_M,
|
||||
Key_N,
|
||||
Key_O,
|
||||
Key_P,
|
||||
Key_Q,
|
||||
Key_R,
|
||||
Key_S,
|
||||
Key_T,
|
||||
Key_U,
|
||||
Key_V,
|
||||
Key_W,
|
||||
Key_X,
|
||||
Key_Y,
|
||||
Key_Z,
|
||||
|
||||
Key_0,
|
||||
Key_1,
|
||||
Key_2,
|
||||
Key_3,
|
||||
Key_4,
|
||||
Key_5,
|
||||
Key_6,
|
||||
Key_7,
|
||||
Key_8,
|
||||
Key_9,
|
||||
|
||||
Key_F1,
|
||||
Key_F2,
|
||||
Key_F3,
|
||||
Key_F4,
|
||||
Key_F5,
|
||||
Key_F6,
|
||||
Key_F7,
|
||||
Key_F8,
|
||||
Key_F9,
|
||||
Key_F10,
|
||||
Key_F11,
|
||||
Key_F12,
|
||||
Key_F13,
|
||||
Key_F14,
|
||||
Key_F15,
|
||||
Key_F16,
|
||||
Key_F17,
|
||||
Key_F18,
|
||||
Key_F19,
|
||||
Key_F20,
|
||||
Key_F21,
|
||||
Key_F22,
|
||||
Key_F23,
|
||||
Key_F24,
|
||||
|
||||
Key_Escape,
|
||||
Key_Space,
|
||||
Key_Return,
|
||||
Key_Backspace,
|
||||
Key_Tab,
|
||||
|
||||
Key_Shift_L,
|
||||
Key_Shift_R,
|
||||
Key_Control_L,
|
||||
Key_Control_R,
|
||||
Key_Alt_L,
|
||||
Key_Alt_R,
|
||||
Key_Win_L,
|
||||
Key_Win_R,
|
||||
Key_Apps,
|
||||
|
||||
Key_CapsLock,
|
||||
Key_NumLock,
|
||||
Key_ScrollLock,
|
||||
|
||||
Key_PrintScreen,
|
||||
Key_Pause,
|
||||
|
||||
Key_Insert,
|
||||
Key_Delete,
|
||||
Key_PageUP,
|
||||
Key_PageDown,
|
||||
Key_Home,
|
||||
Key_End,
|
||||
|
||||
Key_Left,
|
||||
Key_Right,
|
||||
Key_Up,
|
||||
Key_Down,
|
||||
|
||||
Key_Numpad0,
|
||||
Key_Numpad1,
|
||||
Key_Numpad2,
|
||||
Key_Numpad3,
|
||||
Key_Numpad4,
|
||||
Key_Numpad5,
|
||||
Key_Numpad6,
|
||||
Key_Numpad7,
|
||||
Key_Numpad8,
|
||||
Key_Numpad9,
|
||||
|
||||
Key_NumpadAdd,
|
||||
Key_NumpadSubtract,
|
||||
Key_NumpadMultiply,
|
||||
Key_NumpadDivide,
|
||||
Key_NumpadDecimal,
|
||||
Key_NumpadEnter
|
||||
};
|
||||
|
||||
void registerHotkeys();
|
||||
77
src/headers/macro-action-audio.hpp
Normal file
77
src/headers/macro-action-audio.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class AudioAction {
|
||||
MUTE,
|
||||
UNMUTE,
|
||||
SOURCE_VOLUME,
|
||||
MASTER_VOLUME,
|
||||
};
|
||||
|
||||
class MacroActionAudio : 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<MacroActionAudio>();
|
||||
}
|
||||
|
||||
OBSWeakSource _audioSource;
|
||||
AudioAction _action = AudioAction::MUTE;
|
||||
int _volume = 0;
|
||||
bool _fade = false;
|
||||
Duration _duration;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionAudioEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionAudioEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionAudio> entryData = nullptr);
|
||||
void SetWidgetVisibility();
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionAudioEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionAudio>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void VolumeChanged(int value);
|
||||
void FadeChanged(int value);
|
||||
void DurationChanged(double seconds);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_audioSources;
|
||||
QComboBox *_actions;
|
||||
QSpinBox *_volumePercent;
|
||||
QCheckBox *_fade;
|
||||
DurationSelection *_duration;
|
||||
QHBoxLayout *_fadeLayout;
|
||||
std::shared_ptr<MacroActionAudio> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
47
src/headers/macro-action-edit.hpp
Normal file
47
src/headers/macro-action-edit.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
|
||||
struct MacroActionInfo {
|
||||
using TCreateMethod = std::shared_ptr<MacroAction> (*)();
|
||||
using TCreateWidgetMethod = QWidget *(*)(QWidget *parent,
|
||||
std::shared_ptr<MacroAction>);
|
||||
TCreateMethod _createFunc;
|
||||
TCreateWidgetMethod _createWidgetFunc;
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
class MacroActionFactory {
|
||||
public:
|
||||
MacroActionFactory() = delete;
|
||||
static bool Register(const std::string &id, MacroActionInfo);
|
||||
static std::shared_ptr<MacroAction> Create(const std::string &id);
|
||||
static QWidget *CreateWidget(const std::string &id, QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action);
|
||||
static auto GetActionTypes() { return _methods; }
|
||||
static std::string GetActionName(const std::string &id);
|
||||
static std::string GetIdByName(const QString &name);
|
||||
|
||||
private:
|
||||
static std::map<std::string, MacroActionInfo> _methods;
|
||||
};
|
||||
|
||||
class MacroActionEdit : public MacroSegmentEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionEdit(QWidget *parent = nullptr,
|
||||
std::shared_ptr<MacroAction> * = nullptr,
|
||||
const std::string &id = "scene_switch");
|
||||
void UpdateEntryData(const std::string &id);
|
||||
|
||||
private slots:
|
||||
void ActionSelectionChanged(const QString &text);
|
||||
|
||||
private:
|
||||
MacroSegment *Data();
|
||||
|
||||
QComboBox *_actionSelection;
|
||||
|
||||
std::shared_ptr<MacroAction> *_entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
65
src/headers/macro-action-file.hpp
Normal file
65
src/headers/macro-action-file.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "file-selection.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 PathChanged(const QString &text);
|
||||
void TextChanged();
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
FileSelection *_filePath;
|
||||
QPlainTextEdit *_text;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionFile> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
71
src/headers/macro-action-filter.hpp
Normal file
71
src/headers/macro-action-filter.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
enum class FilterAction {
|
||||
ENABLE,
|
||||
DISABLE,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
class MacroActionFilter : 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<MacroActionFilter>();
|
||||
}
|
||||
|
||||
OBSWeakSource _source;
|
||||
OBSWeakSource _filter;
|
||||
FilterAction _action = FilterAction::ENABLE;
|
||||
std::string _settings = "";
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionFilterEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionFilterEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionFilter> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionFilterEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionFilter>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void FilterChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
QComboBox *_filters;
|
||||
QComboBox *_actions;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
std::shared_ptr<MacroActionFilter> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(bool);
|
||||
bool _loading = true;
|
||||
};
|
||||
92
src/headers/macro-action-hotkey.hpp
Normal file
92
src/headers/macro-action-hotkey.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "hotkey.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
#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;
|
||||
int _duration = 300; // in ms
|
||||
#ifdef __APPLE__
|
||||
bool _onlySendToObs = true;
|
||||
#else
|
||||
bool _onlySendToObs = false;
|
||||
#endif
|
||||
|
||||
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);
|
||||
void DurationChanged(int ms);
|
||||
void OnlySendToOBSChanged(int state);
|
||||
|
||||
protected:
|
||||
QComboBox *_keys;
|
||||
QCheckBox *_leftShift;
|
||||
QCheckBox *_rightShift;
|
||||
QCheckBox *_leftCtrl;
|
||||
QCheckBox *_rightCtrl;
|
||||
QCheckBox *_leftAlt;
|
||||
QCheckBox *_rightAlt;
|
||||
QCheckBox *_leftMeta;
|
||||
QCheckBox *_rightMeta;
|
||||
QSpinBox *_duration;
|
||||
QCheckBox *_onlySendToOBS;
|
||||
QLabel *_noKeyPressSimulationWarning;
|
||||
|
||||
std::shared_ptr<MacroActionHotkey> _entryData;
|
||||
|
||||
private:
|
||||
void SetWarningVisibility();
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
64
src/headers/macro-action-macro.hpp
Normal file
64
src/headers/macro-action-macro.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "macro-selection.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class PerformMacroAction {
|
||||
PAUSE,
|
||||
UNPAUSE,
|
||||
RESET_COUNTER,
|
||||
};
|
||||
|
||||
class MacroActionMacro : public MacroRefAction {
|
||||
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<MacroActionMacro>();
|
||||
}
|
||||
|
||||
PerformMacroAction _action = PerformMacroAction::PAUSE;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionMacroEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionMacroEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionMacro> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionMacroEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionMacro>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void MacroRemove(const QString &name);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
MacroSelection *_macros;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionMacro> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
67
src/headers/macro-action-media.hpp
Normal file
67
src/headers/macro-action-media.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class MediaAction {
|
||||
PLAY,
|
||||
PAUSE,
|
||||
STOP,
|
||||
RESTART,
|
||||
NEXT,
|
||||
PREVIOUS,
|
||||
};
|
||||
|
||||
class MacroActionMedia : 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<MacroActionMedia>();
|
||||
}
|
||||
|
||||
OBSWeakSource _mediaSource;
|
||||
MediaAction _action = MediaAction::PLAY;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionMediaEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionMediaEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionMedia> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionMediaEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionMedia>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_mediaSources;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionMedia> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
65
src/headers/macro-action-plugin-state.hpp
Normal file
65
src/headers/macro-action-plugin-state.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class PluginStateAction {
|
||||
STOP,
|
||||
NO_MATCH_BEHAVIOUR,
|
||||
};
|
||||
|
||||
class MacroActionPluginState : 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<MacroActionPluginState>();
|
||||
}
|
||||
|
||||
PluginStateAction _action = PluginStateAction::STOP;
|
||||
int _value = 0;
|
||||
OBSWeakSource _scene;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionPluginStateEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionPluginStateEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionPluginState> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionPluginStateEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionPluginState>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
void ValueChanged(int value);
|
||||
void SceneChanged(const QString &text);
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
QComboBox *_values;
|
||||
QComboBox *_scenes;
|
||||
std::shared_ptr<MacroActionPluginState> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(PluginStateAction, int);
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
54
src/headers/macro-action-preview-scene.hpp
Normal file
54
src/headers/macro-action-preview-scene.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
class MacroActionPreviewScene : 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<MacroActionPreviewScene>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionPreviewSceneEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionPreviewSceneEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionPreviewScene> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionPreviewSceneEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionPreviewScene>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
std::shared_ptr<MacroActionPreviewScene> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
63
src/headers/macro-action-random.hpp
Normal file
63
src/headers/macro-action-random.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "macro-selection.hpp"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QListWidget>
|
||||
#include <unordered_map>
|
||||
|
||||
class MacroActionRandom : public MultiMacroRefAction {
|
||||
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<MacroActionRandom>();
|
||||
}
|
||||
|
||||
// TODO: add weights to each macro ...
|
||||
// std::unordered_map<MacroRef, int> _weights;
|
||||
|
||||
private:
|
||||
MacroRef lastRandomMacro;
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionRandomEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionRandomEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionRandom> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionRandomEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionRandom>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void MacroRemove(const QString &name);
|
||||
void MacroRename(const QString &oldName, const QString &newName);
|
||||
void AddMacro();
|
||||
void RemoveMacro();
|
||||
int FindEntry(const std::string ¯o);
|
||||
void MacroSelectionChanged(int idx);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MacroActionRandom> _entryData;
|
||||
|
||||
private:
|
||||
MacroSelection *_macroSelection;
|
||||
QListWidget *_macroList;
|
||||
QPushButton *_add;
|
||||
QPushButton *_remove;
|
||||
bool _loading = true;
|
||||
};
|
||||
60
src/headers/macro-action-recording.hpp
Normal file
60
src/headers/macro-action-recording.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class RecordAction {
|
||||
STOP,
|
||||
START,
|
||||
PAUSE,
|
||||
UNPAUSE,
|
||||
};
|
||||
|
||||
class MacroActionRecord : 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<MacroActionRecord>();
|
||||
}
|
||||
|
||||
RecordAction _action = RecordAction::STOP;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionRecordEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionRecordEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionRecord> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionRecordEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionRecord>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
QLabel *_pauseHint;
|
||||
std::shared_ptr<MacroActionRecord> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
71
src/headers/macro-action-replay-buffer.hpp
Normal file
71
src/headers/macro-action-replay-buffer.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifdef REPLAYBUFFER_SUPPORTED
|
||||
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class ReplayBufferAction {
|
||||
STOP,
|
||||
START,
|
||||
SAVE,
|
||||
};
|
||||
|
||||
class MacroActionReplayBuffer : 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<MacroActionReplayBuffer>();
|
||||
}
|
||||
|
||||
ReplayBufferAction _action = ReplayBufferAction::STOP;
|
||||
|
||||
private:
|
||||
// Add artifical delay before trying to save the replay buffer again.
|
||||
//
|
||||
// Continiously calling obs_frontend_replay_buffer_save() does not
|
||||
// result in any output actually being written.
|
||||
// OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED also seems to be sent before
|
||||
// any data is written.
|
||||
Duration _duration;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionReplayBufferEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionReplayBufferEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionReplayBuffer> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionReplayBufferEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionReplayBuffer>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionReplayBuffer> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
#endif
|
||||
66
src/headers/macro-action-run.hpp
Normal file
66
src/headers/macro-action-run.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "file-selection.hpp"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QListWidget>
|
||||
#include <QStringList>
|
||||
|
||||
class MacroActionRun : 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<MacroActionRun>();
|
||||
}
|
||||
|
||||
std::string _path = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
QStringList _args;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionRunEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionRunEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionRun> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionRunEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionRun>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void PathChanged(const QString &text);
|
||||
void AddArg();
|
||||
void RemoveArg();
|
||||
void ArgUp();
|
||||
void ArgDown();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MacroActionRun> _entryData;
|
||||
|
||||
private:
|
||||
FileSelection *_filePath;
|
||||
QListWidget *_argList;
|
||||
QPushButton *_addArg;
|
||||
QPushButton *_removeArg;
|
||||
QPushButton *_argUp;
|
||||
QPushButton *_argDown;
|
||||
bool _loading = true;
|
||||
};
|
||||
72
src/headers/macro-action-scene-order.hpp
Normal file
72
src/headers/macro-action-scene-order.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
enum class SceneOrderAction {
|
||||
MOVE_UP,
|
||||
MOVE_DOWN,
|
||||
MOVE_TOP,
|
||||
MOVE_BOTTOM,
|
||||
POSITION,
|
||||
};
|
||||
|
||||
class MacroActionSceneOrder : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionSceneOrder>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
SceneOrderAction _action = SceneOrderAction::MOVE_UP;
|
||||
int _position = 0;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSceneOrderEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSceneOrderEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSceneOrder> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSceneOrderEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionSceneOrder>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void PositionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_actions;
|
||||
QSpinBox *_position;
|
||||
std::shared_ptr<MacroActionSceneOrder> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
38
src/headers/macro-action-scene-swap.hpp
Normal file
38
src/headers/macro-action-scene-swap.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
class MacroActionSceneSwap : 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<MacroActionSceneSwap>();
|
||||
}
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSceneSwapEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSceneSwapEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSceneSwap> entryData = nullptr);
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSceneSwapEdit(
|
||||
parent, std::dynamic_pointer_cast<MacroActionSceneSwap>(
|
||||
action));
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MacroActionSceneSwap> _entryData;
|
||||
};
|
||||
55
src/headers/macro-action-scene-switch.hpp
Normal file
55
src/headers/macro-action-scene-switch.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "switch-generic.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
// TODO: Switch to using SceneSelection class and widget instead
|
||||
|
||||
class MacroActionSwitchScene : public MacroAction, public SceneSwitcherEntry {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionSwitchScene>();
|
||||
}
|
||||
Duration _duration;
|
||||
|
||||
private:
|
||||
const char *getType() { return "MacroActionSwitchScene"; }
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSwitchSceneEdit : public SwitchWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSwitchSceneEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSwitchScene> entryData = nullptr);
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSwitchSceneEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionSwitchScene>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void DurationChanged(double seconds);
|
||||
void ChangeHeaderInfo(const QString &);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
DurationSelection *_duration;
|
||||
std::shared_ptr<MacroActionSwitchScene> _entryData;
|
||||
};
|
||||
66
src/headers/macro-action-scene-transform.hpp
Normal file
66
src/headers/macro-action-scene-transform.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
class MacroActionSceneTransform : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionSceneTransform>();
|
||||
}
|
||||
std::string GetSettings();
|
||||
void SetSettings(std::string &);
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
struct obs_transform_info _info;
|
||||
struct obs_sceneitem_crop _crop;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSceneTransformEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSceneTransformEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSceneTransform> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSceneTransformEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionSceneTransform>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
std::shared_ptr<MacroActionSceneTransform> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
75
src/headers/macro-action-scene-visibility.hpp
Normal file
75
src/headers/macro-action-scene-visibility.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
enum class SceneVisibilityAction {
|
||||
SHOW,
|
||||
HIDE,
|
||||
};
|
||||
|
||||
enum class SceneItemSourceType {
|
||||
SOURCE,
|
||||
SOURCE_GROUP,
|
||||
};
|
||||
|
||||
class MacroActionSceneVisibility : 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<MacroActionSceneVisibility>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
SceneItemSourceType _sourceType = SceneItemSourceType::SOURCE;
|
||||
OBSWeakSource _source;
|
||||
std::string _sourceGroup = "";
|
||||
SceneVisibilityAction _action = SceneVisibilityAction::SHOW;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSceneVisibilityEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSceneVisibilityEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSceneVisibility> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSceneVisibilityEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionSceneVisibility>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceTypeChanged(int value);
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sourceTypes;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionSceneVisibility> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
72
src/headers/macro-action-source.hpp
Normal file
72
src/headers/macro-action-source.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
enum class SourceAction {
|
||||
ENABLE,
|
||||
DISABLE,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
class MacroActionSource : 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<MacroActionSource>();
|
||||
}
|
||||
|
||||
OBSWeakSource _source;
|
||||
std::string _settings = "";
|
||||
SourceAction _action = SourceAction::ENABLE;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSourceEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSourceEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSource> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSourceEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionSource>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
QComboBox *_actions;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
QLabel *_warning;
|
||||
std::shared_ptr<MacroActionSource> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(bool);
|
||||
bool _loading = true;
|
||||
};
|
||||
63
src/headers/macro-action-streaming.hpp
Normal file
63
src/headers/macro-action-streaming.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QComboBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class StreamAction {
|
||||
STOP,
|
||||
START,
|
||||
};
|
||||
|
||||
class MacroActionStream : 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<MacroActionStream>();
|
||||
}
|
||||
|
||||
StreamAction _action = StreamAction::STOP;
|
||||
|
||||
private:
|
||||
// Acts as a safeguard for misconfigured streaming setups leading to an
|
||||
// endless error spam.
|
||||
Duration _retryCooldown;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionStreamEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionStreamEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionStream> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionStreamEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionStream>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionStream> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
72
src/headers/macro-action-timer.hpp
Normal file
72
src/headers/macro-action-timer.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
#include "macro-selection.hpp"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class TimerAction {
|
||||
PAUSE,
|
||||
CONTINUE,
|
||||
RESET,
|
||||
SET_TIME_REMAINING,
|
||||
};
|
||||
|
||||
class MacroActionTimer : public MacroRefAction {
|
||||
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<MacroActionTimer>();
|
||||
}
|
||||
Duration _duration;
|
||||
TimerAction _actionType = TimerAction::PAUSE;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionTimerEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionTimerEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionTimer> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionTimerEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionTimer>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void MacroRemove(const QString &name);
|
||||
void DurationChanged(double value);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
void ActionTypeChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
MacroSelection *_macros;
|
||||
DurationSelection *_duration;
|
||||
QComboBox *_timerAction;
|
||||
std::shared_ptr<MacroActionTimer> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
68
src/headers/macro-action-transition.hpp
Normal file
68
src/headers/macro-action-transition.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
#include "transition-selection.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
class MacroActionTransition : 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<MacroActionTransition>();
|
||||
}
|
||||
|
||||
bool _setDuration = true;
|
||||
bool _setType = true;
|
||||
TransitionSelection _transition;
|
||||
Duration _duration;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionTransitionEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionTransitionEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionTransition> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionTransitionEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionTransition>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SetTypeChanged(int state);
|
||||
void SetDurationChanged(int state);
|
||||
void TransitionChanged(const TransitionSelection &);
|
||||
void DurationChanged(double seconds);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QCheckBox *_setType;
|
||||
QCheckBox *_setDuration;
|
||||
TransitionSelectionWidget *_transitions;
|
||||
DurationSelection *_duration;
|
||||
QHBoxLayout *_typeLayout;
|
||||
QHBoxLayout *_durationLayout;
|
||||
std::shared_ptr<MacroActionTransition> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
61
src/headers/macro-action-virtual-cam.hpp
Normal file
61
src/headers/macro-action-virtual-cam.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifdef VCAM_SUPPORTED
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
#endif
|
||||
66
src/headers/macro-action-wait.hpp
Normal file
66
src/headers/macro-action-wait.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
enum class WaitType {
|
||||
FIXED,
|
||||
RANDOM,
|
||||
};
|
||||
|
||||
class MacroActionWait : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
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<MacroActionWait>();
|
||||
}
|
||||
Duration _duration;
|
||||
Duration _duration2;
|
||||
WaitType _waitType = WaitType::FIXED;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionWaitEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionWaitEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionWait> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
void SetupFixedDurationEdit();
|
||||
void SetupRandomDurationEdit();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionWaitEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionWait>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void DurationChanged(double value);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
void Duration2Changed(double value);
|
||||
void Duration2UnitChanged(DurationUnit unit);
|
||||
void TypeChanged(int value);
|
||||
|
||||
protected:
|
||||
DurationSelection *_duration;
|
||||
DurationSelection *_duration2;
|
||||
QComboBox *_waitType;
|
||||
std::shared_ptr<MacroActionWait> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
76
src/headers/macro-condition-audio.hpp
Normal file
76
src/headers/macro-condition-audio.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "volume-control.hpp"
|
||||
#include <limits>
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <chrono>
|
||||
|
||||
enum class AudioCondition {
|
||||
ABOVE,
|
||||
BELOW,
|
||||
};
|
||||
|
||||
class MacroConditionAudio : public MacroCondition {
|
||||
public:
|
||||
~MacroConditionAudio();
|
||||
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<MacroConditionAudio>();
|
||||
}
|
||||
static void SetVolumeLevel(void *data,
|
||||
const float magnitude[MAX_AUDIO_CHANNELS],
|
||||
const float peak[MAX_AUDIO_CHANNELS],
|
||||
const float inputPeak[MAX_AUDIO_CHANNELS]);
|
||||
void ResetVolmeter();
|
||||
|
||||
OBSWeakSource _audioSource;
|
||||
int _volume = 0;
|
||||
AudioCondition _condition = AudioCondition::ABOVE;
|
||||
obs_volmeter_t *_volmeter = nullptr;
|
||||
|
||||
private:
|
||||
float _peak = -std::numeric_limits<float>::infinity();
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionAudioEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionAudioEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionAudio> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionAudioEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionAudio>(cond));
|
||||
}
|
||||
void UpdateVolmeterSource();
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void VolumeThresholdChanged(int vol);
|
||||
void ConditionChanged(int cond);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_audioSources;
|
||||
QComboBox *_condition;
|
||||
QSpinBox *_volume;
|
||||
VolControl *_volMeter = nullptr;
|
||||
std::shared_ptr<MacroConditionAudio> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
76
src/headers/macro-condition-cursor.hpp
Normal file
76
src/headers/macro-condition-cursor.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
#include <QFrame>
|
||||
|
||||
enum class CursorCondition {
|
||||
REGION,
|
||||
MOVING,
|
||||
};
|
||||
|
||||
class MacroConditionCursor : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionCursor>();
|
||||
}
|
||||
|
||||
CursorCondition _condition = CursorCondition::REGION;
|
||||
int _minX = 0, _minY = 0, _maxX = 0, _maxY = 0;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionCursorEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionCursorEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionCursor> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionCursorEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionCursor>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ConditionChanged(int cond);
|
||||
void MinXChanged(int pos);
|
||||
void MinYChanged(int pos);
|
||||
void MaxXChanged(int pos);
|
||||
void MaxYChanged(int pos);
|
||||
void UpdateCursorPos();
|
||||
void ToggleFrame();
|
||||
|
||||
protected:
|
||||
QSpinBox *_minX;
|
||||
QSpinBox *_minY;
|
||||
QSpinBox *_maxX;
|
||||
QSpinBox *_maxY;
|
||||
QComboBox *_conditions;
|
||||
QPushButton *_frameToggle;
|
||||
QLabel *_xPos;
|
||||
QLabel *_yPos;
|
||||
std::shared_ptr<MacroConditionCursor> _entryData;
|
||||
|
||||
private:
|
||||
void SetRegionSelectionVisible(bool);
|
||||
void SetupFrame();
|
||||
QTimer _timer;
|
||||
QFrame _frame;
|
||||
bool _loading = true;
|
||||
};
|
||||
82
src/headers/macro-condition-date.hpp
Normal file
82
src/headers/macro-condition-date.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDateTimeEdit>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class DateCondition {
|
||||
AT,
|
||||
AFTER,
|
||||
BEFORE,
|
||||
BETWEEN,
|
||||
};
|
||||
|
||||
class MacroConditionDate : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionDate>();
|
||||
}
|
||||
|
||||
QDateTime _dateTime;
|
||||
QDateTime _dateTime2;
|
||||
bool _ignoreDate = false;
|
||||
bool _ignoreTime = false;
|
||||
bool _repeat = false;
|
||||
Duration _duration;
|
||||
DateCondition _condition = DateCondition::AT;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionDateEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionDateEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionDate> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionDateEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionDate>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ConditionChanged(int cond);
|
||||
void DateTimeChanged(const QDateTime &datetime);
|
||||
void DateTime2Changed(const QDateTime &datetime);
|
||||
void IgnoreDateChanged(int state);
|
||||
void IgnoreTimeChanged(int state);
|
||||
void RepeatChanged(int state);
|
||||
void DurationChanged(double seconds);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_condition;
|
||||
QDateTimeEdit *_dateTime;
|
||||
QDateTimeEdit *_dateTime2;
|
||||
QCheckBox *_ignoreDate;
|
||||
QCheckBox *_ignoreTime;
|
||||
QCheckBox *_repeat;
|
||||
DurationSelection *_duration;
|
||||
std::shared_ptr<MacroConditionDate> _entryData;
|
||||
|
||||
private:
|
||||
void ShowSecondDateSelection(bool visible);
|
||||
bool _loading = true;
|
||||
};
|
||||
58
src/headers/macro-condition-edit.hpp
Normal file
58
src/headers/macro-condition-edit.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
|
||||
struct MacroConditionInfo {
|
||||
using TCreateMethod = std::shared_ptr<MacroCondition> (*)();
|
||||
using TCreateWidgetMethod =
|
||||
QWidget *(*)(QWidget *parent, std::shared_ptr<MacroCondition>);
|
||||
TCreateMethod _createFunc;
|
||||
TCreateWidgetMethod _createWidgetFunc;
|
||||
std::string _name;
|
||||
bool _useDurationConstraint = true;
|
||||
};
|
||||
|
||||
class MacroConditionFactory {
|
||||
public:
|
||||
MacroConditionFactory() = delete;
|
||||
static bool Register(const std::string &, MacroConditionInfo);
|
||||
static std::shared_ptr<MacroCondition> Create(const std::string &);
|
||||
static QWidget *CreateWidget(const std::string &id, QWidget *parent,
|
||||
std::shared_ptr<MacroCondition>);
|
||||
static auto GetConditionTypes() { return _methods; }
|
||||
static std::string GetConditionName(const std::string &);
|
||||
static std::string GetIdByName(const QString &name);
|
||||
static bool UsesDurationConstraint(const std::string &id);
|
||||
|
||||
private:
|
||||
static std::map<std::string, MacroConditionInfo> _methods;
|
||||
};
|
||||
|
||||
class MacroConditionEdit : public MacroSegmentEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionEdit(QWidget *parent = nullptr,
|
||||
std::shared_ptr<MacroCondition> * = nullptr,
|
||||
const std::string &id = "scene", bool root = true);
|
||||
bool IsRootNode();
|
||||
void SetRootNode(bool);
|
||||
void UpdateEntryData(const std::string &id);
|
||||
|
||||
private slots:
|
||||
void LogicSelectionChanged(int idx);
|
||||
void ConditionSelectionChanged(const QString &text);
|
||||
void DurationChanged(double seconds);
|
||||
void DurationConditionChanged(DurationCondition cond);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
|
||||
private:
|
||||
MacroSegment *Data();
|
||||
|
||||
QComboBox *_logicSelection;
|
||||
QComboBox *_conditionSelection;
|
||||
DurationConstraintEdit *_dur;
|
||||
|
||||
std::shared_ptr<MacroCondition> *_entryData;
|
||||
bool _isRoot = true;
|
||||
bool _loading = true;
|
||||
};
|
||||
85
src/headers/macro-condition-file.hpp
Normal file
85
src/headers/macro-condition-file.hpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "file-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <QDateTime>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QCheckBox>
|
||||
|
||||
enum class FileType {
|
||||
LOCAL,
|
||||
REMOTE,
|
||||
};
|
||||
|
||||
class MacroConditionFile : 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<MacroConditionFile>();
|
||||
}
|
||||
|
||||
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
std::string _text = obs_module_text("AdvSceneSwitcher.enterText");
|
||||
FileType _fileType = FileType::LOCAL;
|
||||
bool _useRegex = false;
|
||||
bool _useTime = false;
|
||||
bool _onlyMatchIfChanged = false;
|
||||
|
||||
private:
|
||||
bool matchFileContent(QString &filedata);
|
||||
bool checkRemoteFileContent();
|
||||
bool checkLocalFileContent();
|
||||
|
||||
QDateTime _lastMod;
|
||||
size_t _lastHash = 0;
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionFileEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionFileEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionFile> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionFileEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionFile>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void FileTypeChanged(int index);
|
||||
void PathChanged(const QString &text);
|
||||
void MatchTextChanged();
|
||||
void UseRegexChanged(int state);
|
||||
void CheckModificationDateChanged(int state);
|
||||
void OnlyMatchIfChangedChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_fileType;
|
||||
FileSelection *_filePath;
|
||||
QPlainTextEdit *_matchText;
|
||||
QCheckBox *_useRegex;
|
||||
QCheckBox *_checkModificationDate;
|
||||
QCheckBox *_checkFileContent;
|
||||
std::shared_ptr<MacroConditionFile> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
77
src/headers/macro-condition-filter.hpp
Normal file
77
src/headers/macro-condition-filter.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QCheckBox>
|
||||
|
||||
enum class FilterCondition {
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
class MacroConditionFilter : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionFilter>();
|
||||
}
|
||||
|
||||
OBSWeakSource _source;
|
||||
OBSWeakSource _filter;
|
||||
FilterCondition _condition = FilterCondition::ENABLED;
|
||||
std::string _settings = "";
|
||||
bool _regex = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionFilterEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionFilterEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionFilter> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionFilterEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionFilter>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void FilterChanged(const QString &text);
|
||||
void ConditionChanged(int cond);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void RegexChanged(int);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
QComboBox *_filters;
|
||||
QComboBox *_conditions;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
QCheckBox *_regex;
|
||||
|
||||
std::shared_ptr<MacroConditionFilter> _entryData;
|
||||
|
||||
private:
|
||||
void SetSettingsSelectionVisible(bool visible);
|
||||
bool _loading = true;
|
||||
};
|
||||
54
src/headers/macro-condition-hotkey.hpp
Normal file
54
src/headers/macro-condition-hotkey.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QLineEdit>
|
||||
|
||||
class MacroConditionHotkey : public MacroCondition {
|
||||
public:
|
||||
MacroConditionHotkey();
|
||||
~MacroConditionHotkey();
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionHotkey>();
|
||||
}
|
||||
void SetPressed() { _pressed = true; }
|
||||
|
||||
std::string _name;
|
||||
obs_hotkey_id _hotkeyID = OBS_INVALID_HOTKEY_ID;
|
||||
|
||||
private:
|
||||
bool _pressed = false;
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionHotkeyEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionHotkeyEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionHotkey> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionHotkeyEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionHotkey>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void NameChanged();
|
||||
|
||||
protected:
|
||||
QLineEdit *_name;
|
||||
std::shared_ptr<MacroConditionHotkey> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
52
src/headers/macro-condition-idle.hpp
Normal file
52
src/headers/macro-condition-idle.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
class MacroConditionIdle : 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<MacroConditionIdle>();
|
||||
}
|
||||
|
||||
Duration _duration;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionIdleEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionIdleEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionIdle> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionIdleEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionIdle>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void DurationChanged(double seconds);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
|
||||
protected:
|
||||
DurationSelection *_duration;
|
||||
std::shared_ptr<MacroConditionIdle> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
93
src/headers/macro-condition-macro.hpp
Normal file
93
src/headers/macro-condition-macro.hpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "macro-selection.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
#include <QPushButton>
|
||||
#include <QHBoxLayout>
|
||||
#include <QTimer>
|
||||
|
||||
enum class MacroConditionMacroType {
|
||||
COUNT,
|
||||
STATE,
|
||||
};
|
||||
|
||||
enum class CounterCondition {
|
||||
BELOW,
|
||||
ABOVE,
|
||||
EQUAL,
|
||||
};
|
||||
|
||||
class MacroConditionMacro : public MacroRefCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionMacro>();
|
||||
}
|
||||
|
||||
MacroConditionMacroType _type = MacroConditionMacroType::STATE;
|
||||
CounterCondition _counterCondition = CounterCondition::BELOW;
|
||||
int _count = 0;
|
||||
|
||||
private:
|
||||
bool CheckCountCondition();
|
||||
bool CheckStateCondition();
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionMacroEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionMacroEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionMacro> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionMacroEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionMacro>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void MacroRemove(const QString &name);
|
||||
void TypeChanged(int type);
|
||||
void CountChanged(int value);
|
||||
void ConditionChanged(int cond);
|
||||
void ResetClicked();
|
||||
void UpdateCount();
|
||||
void UpdatePaused();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
MacroSelection *_macros;
|
||||
QComboBox *_types;
|
||||
QComboBox *_counterConditions;
|
||||
QSpinBox *_count;
|
||||
QLabel *_currentCount;
|
||||
QLabel *_pausedWarning;
|
||||
QPushButton *_resetCount;
|
||||
QHBoxLayout *_settingsLine1;
|
||||
QHBoxLayout *_settingsLine2;
|
||||
QTimer _countTimer;
|
||||
QTimer _pausedTimer;
|
||||
std::shared_ptr<MacroConditionMacro> _entryData;
|
||||
|
||||
private:
|
||||
void ClearLayouts();
|
||||
void SetupStateWidgets();
|
||||
void SetupCountWidgets();
|
||||
bool _loading = true;
|
||||
};
|
||||
106
src/headers/macro-condition-media.hpp
Normal file
106
src/headers/macro-condition-media.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <limits>
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
#include "duration-control.hpp"
|
||||
|
||||
enum class MediaTimeRestriction {
|
||||
TIME_RESTRICTION_NONE,
|
||||
TIME_RESTRICTION_SHORTER,
|
||||
TIME_RESTRICTION_LONGER,
|
||||
TIME_RESTRICTION_REMAINING_SHORTER,
|
||||
TIME_RESTRICTION_REMAINING_LONGER,
|
||||
};
|
||||
|
||||
constexpr auto custom_media_states_offset = 100;
|
||||
|
||||
enum class MediaState {
|
||||
// OBS's internal states
|
||||
OBS_MEDIA_STATE_NONE,
|
||||
OBS_MEDIA_STATE_PLAYING,
|
||||
OBS_MEDIA_STATE_OPENING,
|
||||
OBS_MEDIA_STATE_BUFFERING,
|
||||
OBS_MEDIA_STATE_PAUSED,
|
||||
OBS_MEDIA_STATE_STOPPED,
|
||||
OBS_MEDIA_STATE_ENDED,
|
||||
OBS_MEDIA_STATE_ERROR,
|
||||
// Just a marker
|
||||
LAST_OBS_MEDIA_STATE,
|
||||
// states added for use in the plugin
|
||||
PLAYED_TO_END = custom_media_states_offset,
|
||||
ANY,
|
||||
};
|
||||
|
||||
class MacroConditionMedia : public MacroCondition {
|
||||
public:
|
||||
~MacroConditionMedia();
|
||||
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<MacroConditionMedia>();
|
||||
}
|
||||
void ClearSignalHandler();
|
||||
void ResetSignalHandler();
|
||||
static void MediaStopped(void *data, calldata_t *);
|
||||
static void MediaEnded(void *data, calldata_t *);
|
||||
|
||||
OBSWeakSource _source = nullptr;
|
||||
MediaState _state = MediaState::OBS_MEDIA_STATE_NONE;
|
||||
MediaTimeRestriction _restriction =
|
||||
MediaTimeRestriction::TIME_RESTRICTION_NONE;
|
||||
Duration _time;
|
||||
|
||||
private:
|
||||
std::atomic_bool _stopped = {false};
|
||||
std::atomic_bool _ended = {false};
|
||||
// Trigger scene change only once even if media state might trigger repeatedly
|
||||
bool _alreadyMatched = false;
|
||||
// Workaround to enable use of "ended" to specify end of VLC playlist
|
||||
bool _previousStateEnded = false;
|
||||
bool _playedToEnd = false;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionMediaEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionMediaEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionMedia> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionMediaEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionMedia>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void StateChanged(int index);
|
||||
void TimeRestrictionChanged(int index);
|
||||
void TimeChanged(double seconds);
|
||||
void TimeUnitChanged(DurationUnit unit);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_mediaSources;
|
||||
QComboBox *_states;
|
||||
QComboBox *_timeRestrictions;
|
||||
DurationSelection *_time;
|
||||
std::shared_ptr<MacroConditionMedia> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
54
src/headers/macro-condition-plugin-state.hpp
Normal file
54
src/headers/macro-condition-plugin-state.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class PluginStateCondition {
|
||||
SCENESWITCHED,
|
||||
};
|
||||
|
||||
class MacroConditionPluginState : 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<MacroConditionPluginState>();
|
||||
}
|
||||
|
||||
PluginStateCondition _condition = PluginStateCondition::SCENESWITCHED;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionPluginStateEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionPluginStateEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionPluginState> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionPluginStateEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionPluginState>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ConditionChanged(int cond);
|
||||
|
||||
protected:
|
||||
QComboBox *_condition;
|
||||
std::shared_ptr<MacroConditionPluginState> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
56
src/headers/macro-condition-process.hpp
Normal file
56
src/headers/macro-condition-process.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
class MacroConditionProcess : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionProcess>();
|
||||
}
|
||||
|
||||
std::string _process;
|
||||
bool _focus = true;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionProcessEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionProcessEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionProcess> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionProcessEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionProcess>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ProcessChanged(const QString &text);
|
||||
void FocusChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_processSelection;
|
||||
QCheckBox *_focused;
|
||||
std::shared_ptr<MacroConditionProcess> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
55
src/headers/macro-condition-recording.hpp
Normal file
55
src/headers/macro-condition-recording.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class RecordState {
|
||||
STOP,
|
||||
PAUSE,
|
||||
START,
|
||||
};
|
||||
|
||||
class MacroConditionRecord : 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<MacroConditionRecord>();
|
||||
}
|
||||
|
||||
RecordState _recordState;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionRecordEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionRecordEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionRecord> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionRecordEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionRecord>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void StateChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_recordState;
|
||||
std::shared_ptr<MacroConditionRecord> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
60
src/headers/macro-condition-replay-buffer.hpp
Normal file
60
src/headers/macro-condition-replay-buffer.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifdef REPLAYBUFFER_SUPPORTED
|
||||
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class ReplayBufferState {
|
||||
STOP,
|
||||
START,
|
||||
SAVE,
|
||||
};
|
||||
|
||||
class MacroConditionReplayBuffer : 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<MacroConditionReplayBuffer>();
|
||||
}
|
||||
|
||||
ReplayBufferState _state;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionReplayBufferEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionReplayBufferEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionReplayBuffer> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionReplayBufferEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionReplayBuffer>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void StateChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_state;
|
||||
std::shared_ptr<MacroConditionReplayBuffer> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
#endif
|
||||
76
src/headers/macro-condition-scene-order.hpp
Normal file
76
src/headers/macro-condition-scene-order.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class SceneOrderCondition {
|
||||
ABOVE,
|
||||
BELOW,
|
||||
POSITION,
|
||||
};
|
||||
|
||||
class MacroConditionSceneOrder : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionSceneOrder>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
OBSWeakSource _source2;
|
||||
int _position = 0;
|
||||
SceneOrderCondition _condition = SceneOrderCondition::ABOVE;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionSceneOrderEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionSceneOrderEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionSceneOrder> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionSceneOrderEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionSceneOrder>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void Source2Changed(const QString &text);
|
||||
void ConditionChanged(int cond);
|
||||
void PositionChanged(int cond);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_conditions;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_sources2;
|
||||
QSpinBox *_position;
|
||||
QLabel *_posInfo;
|
||||
|
||||
std::shared_ptr<MacroConditionSceneOrder> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(bool showPos);
|
||||
bool _loading = true;
|
||||
};
|
||||
69
src/headers/macro-condition-scene-transform.hpp
Normal file
69
src/headers/macro-condition-scene-transform.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QCheckBox>
|
||||
|
||||
class MacroConditionSceneTransform : 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<MacroConditionSceneTransform>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
bool _regex = false;
|
||||
std::string _settings = "";
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionSceneTransformEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionSceneTransformEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionSceneTransform> entryData =
|
||||
nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionSceneTransformEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionSceneTransform>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void RegexChanged(int);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
QCheckBox *_regex;
|
||||
|
||||
std::shared_ptr<MacroConditionSceneTransform> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
66
src/headers/macro-condition-scene-visibility.hpp
Normal file
66
src/headers/macro-condition-scene-visibility.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
enum class SceneVisibilityCondition {
|
||||
SHOWN,
|
||||
HIDDEN,
|
||||
};
|
||||
|
||||
class MacroConditionSceneVisibility : 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<MacroConditionSceneVisibility>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
SceneVisibilityCondition _condition = SceneVisibilityCondition::SHOWN;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionSceneVisibilityEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionSceneVisibilityEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionSceneVisibility> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionSceneVisibilityEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionSceneVisibility>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void ConditionChanged(int cond);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_conditions;
|
||||
|
||||
std::shared_ptr<MacroConditionSceneVisibility> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
70
src/headers/macro-condition-scene.hpp
Normal file
70
src/headers/macro-condition-scene.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
enum class SceneType {
|
||||
CURRENT,
|
||||
PREVIOUS,
|
||||
CHANGED,
|
||||
NOTCHANGED,
|
||||
};
|
||||
|
||||
class MacroConditionScene : 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<MacroConditionScene>();
|
||||
}
|
||||
|
||||
bool _waitForTransition = false;
|
||||
SceneSelection _scene;
|
||||
SceneType _type;
|
||||
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point _lastSceneChangeTime{};
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionSceneEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionSceneEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionScene> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionSceneEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionScene>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void TypeChanged(int value);
|
||||
void WaitForTransitionChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sceneType;
|
||||
QCheckBox *_waitForTransition;
|
||||
std::shared_ptr<MacroConditionScene> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
74
src/headers/macro-condition-source.hpp
Normal file
74
src/headers/macro-condition-source.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QCheckBox>
|
||||
|
||||
enum class SourceCondition {
|
||||
ACTIVE,
|
||||
SHOWING,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
class MacroConditionSource : 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<MacroConditionSource>();
|
||||
}
|
||||
|
||||
OBSWeakSource _source = nullptr;
|
||||
SourceCondition _condition = SourceCondition::ACTIVE;
|
||||
std::string _settings = "";
|
||||
bool _regex = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionSourceEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionSourceEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionSource> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionSourceEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionSource>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void ConditionChanged(int cond);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void RegexChanged(int);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
QComboBox *_conditions;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
QCheckBox *_regex;
|
||||
|
||||
std::shared_ptr<MacroConditionSource> _entryData;
|
||||
|
||||
private:
|
||||
void SetSettingsSelectionVisible(bool visible);
|
||||
bool _loading = true;
|
||||
};
|
||||
59
src/headers/macro-condition-streaming.hpp
Normal file
59
src/headers/macro-condition-streaming.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class StreamState {
|
||||
STOP,
|
||||
START,
|
||||
STARTING,
|
||||
STOPPING,
|
||||
};
|
||||
|
||||
class MacroConditionStream : 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<MacroConditionStream>();
|
||||
}
|
||||
|
||||
StreamState _streamState;
|
||||
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point _lastStreamStartingTime{};
|
||||
std::chrono::high_resolution_clock::time_point _lastStreamStoppingTime{};
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionStreamEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionStreamEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionStream> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionStreamEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionStream>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void StateChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_streamState;
|
||||
std::shared_ptr<MacroConditionStream> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
73
src/headers/macro-condition-timer.hpp
Normal file
73
src/headers/macro-condition-timer.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
|
||||
class MacroConditionTimer : 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<MacroConditionTimer>();
|
||||
}
|
||||
void Pause();
|
||||
void Continue();
|
||||
void Reset();
|
||||
|
||||
Duration _duration;
|
||||
bool _paused = false;
|
||||
bool _saveRemaining = false;
|
||||
double _remaining = 0.;
|
||||
bool _oneshot = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionTimerEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionTimerEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionTimer> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionTimerEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionTimer>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void DurationChanged(double seconds);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
void SaveRemainingChanged(int state);
|
||||
void AutoResetChanged(int state);
|
||||
void PauseContinueClicked();
|
||||
void ResetClicked();
|
||||
void UpdateTimeRemaining();
|
||||
|
||||
protected:
|
||||
void SetPauseContinueButtonLabel();
|
||||
|
||||
DurationSelection *_duration;
|
||||
QCheckBox *_autoReset;
|
||||
QCheckBox *_saveRemaining;
|
||||
QPushButton *_reset;
|
||||
QPushButton *_pauseConinue;
|
||||
QLabel *_remaining;
|
||||
std::shared_ptr<MacroConditionTimer> _entryData;
|
||||
|
||||
private:
|
||||
QTimer timer;
|
||||
bool _loading = true;
|
||||
};
|
||||
79
src/headers/macro-condition-transition.hpp
Normal file
79
src/headers/macro-condition-transition.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "duration-control.hpp"
|
||||
#include "transition-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class TransitionCondition {
|
||||
CURRENT,
|
||||
DURATION,
|
||||
STARTED,
|
||||
ENDED,
|
||||
};
|
||||
|
||||
class MacroConditionTransition : 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<MacroConditionTransition>();
|
||||
}
|
||||
void ConnectToTransitionSignals();
|
||||
void DisconnectTransitionSignals();
|
||||
|
||||
TransitionCondition _condition = TransitionCondition::CURRENT;
|
||||
TransitionSelection _transition;
|
||||
Duration _duration;
|
||||
|
||||
private:
|
||||
static void TransitionStarted(void *data, calldata_t *);
|
||||
static void TransitionEnded(void *data, calldata_t *);
|
||||
|
||||
bool _started = false;
|
||||
bool _ended = false;
|
||||
std::chrono::high_resolution_clock::time_point _lastTransitionEndTime{};
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionTransitionEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionTransitionEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionTransition> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionTransitionEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionTransition>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ConditionChanged(int cond);
|
||||
void TransitionChanged(const TransitionSelection &);
|
||||
void DurationChanged(double seconds);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_conditions;
|
||||
TransitionSelectionWidget *_transitions;
|
||||
DurationSelection *_duration;
|
||||
QLabel *_durationSuffix;
|
||||
std::shared_ptr<MacroConditionTransition> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
182
src/headers/macro-condition-video.hpp
Normal file
182
src/headers/macro-condition-video.hpp
Normal file
@@ -0,0 +1,182 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "screenshot-helper.hpp"
|
||||
#include "file-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <chrono>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
enum class VideoCondition {
|
||||
MATCH,
|
||||
DIFFER,
|
||||
HAS_NOT_CHANGED,
|
||||
HAS_CHANGED,
|
||||
NO_IMAGE,
|
||||
PATTERN,
|
||||
OBJECT,
|
||||
};
|
||||
|
||||
struct PatternMatchData {
|
||||
cv::Mat4b rgbaPattern;
|
||||
cv::Mat3b rgbPattern;
|
||||
cv::Mat1b mask;
|
||||
};
|
||||
|
||||
constexpr int minMinNeighbors = 3;
|
||||
constexpr int maxMinNeighbors = 6;
|
||||
|
||||
class MacroConditionVideo : 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; };
|
||||
QImage GetMatchImage() { return _matchImage; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionVideo>();
|
||||
}
|
||||
void GetScreenshot();
|
||||
bool LoadImageFromFile();
|
||||
bool LoadModelData(std::string &path);
|
||||
std::string GetModelDataPath() { return _modelDataPath; }
|
||||
void ResetLastMatch() { _lastMatchResult = false; }
|
||||
|
||||
OBSWeakSource _videoSource;
|
||||
VideoCondition _condition = VideoCondition::MATCH;
|
||||
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
bool _useAlphaAsMask = false;
|
||||
bool _usePatternForChangedCheck = false;
|
||||
PatternMatchData _patternData;
|
||||
double _patternThreshold = 0.8;
|
||||
cv::CascadeClassifier _objectCascade;
|
||||
double _scaleFactor = 1.1;
|
||||
int _minNeighbors = minMinNeighbors;
|
||||
int _minSizeX = 0;
|
||||
int _minSizeY = 0;
|
||||
int _maxSizeX = 0;
|
||||
int _maxSizeY = 0;
|
||||
|
||||
bool _throttleEnabled = false;
|
||||
int _throttleCount = 3;
|
||||
|
||||
private:
|
||||
bool OutputChanged();
|
||||
bool ScreenshotContainsPattern();
|
||||
bool ScreenshotContainsObject();
|
||||
bool Compare();
|
||||
bool CheckShouldBeSkipped();
|
||||
|
||||
std::unique_ptr<AdvSSScreenshotObj> _screenshotData = nullptr;
|
||||
QImage _matchImage;
|
||||
std::string _modelDataPath =
|
||||
obs_get_module_data_path(obs_current_module()) +
|
||||
std::string(
|
||||
"/res/cascadeClassifiers/haarcascade_frontalface_alt.xml");
|
||||
bool _lastMatchResult = false;
|
||||
int _runCount = 0;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class ThresholdSlider : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ThresholdSlider(double min = 0., double max = 1.,
|
||||
const QString &label = "threshold",
|
||||
const QString &description = "", QWidget *parent = 0);
|
||||
void SetDoubleValue(double);
|
||||
public slots:
|
||||
void NotifyValueChanged(int value);
|
||||
signals:
|
||||
void DoubleValueChanged(double value);
|
||||
|
||||
private:
|
||||
void SetDoubleValueText(double);
|
||||
QLabel *_value;
|
||||
QSlider *_slider;
|
||||
double _scale = 100.0;
|
||||
int _precision = 2;
|
||||
};
|
||||
|
||||
class MacroConditionVideoEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionVideoEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionVideo> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionVideoEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionVideo>(cond));
|
||||
}
|
||||
|
||||
void UpdatePreviewTooltip();
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void ConditionChanged(int cond);
|
||||
void ImagePathChanged(const QString &text);
|
||||
void ImageBrowseButtonClicked();
|
||||
void UsePatternForChangedCheckChanged(int value);
|
||||
void PatternThresholdChanged(double);
|
||||
void UseAlphaAsMaskChanged(int value);
|
||||
|
||||
void ModelPathChanged(const QString &text);
|
||||
void ObjectScaleThresholdChanged(double);
|
||||
void MinNeighborsChanged(int value);
|
||||
void MinSizeXChanged(int value);
|
||||
void MinSizeYChanged(int value);
|
||||
void MaxSizeXChanged(int value);
|
||||
void MaxSizeYChanged(int value);
|
||||
|
||||
void ThrottleEnableChanged(int value);
|
||||
void ThrottleCountChanged(int value);
|
||||
void ShowMatchClicked();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_videoSelection;
|
||||
QComboBox *_condition;
|
||||
|
||||
QCheckBox *_usePatternForChangedCheck;
|
||||
FileSelection *_imagePath;
|
||||
ThresholdSlider *_patternThreshold;
|
||||
QCheckBox *_useAlphaAsMask;
|
||||
|
||||
FileSelection *_modelDataPath;
|
||||
QHBoxLayout *_modelPathLayout;
|
||||
ThresholdSlider *_objectScaleThreshold;
|
||||
QHBoxLayout *_neighborsControlLayout;
|
||||
QSpinBox *_minNeighbors;
|
||||
QLabel *_minNeighborsDescription;
|
||||
QHBoxLayout *_minSizeControlLayout;
|
||||
QSpinBox *_minSizeX;
|
||||
QSpinBox *_minSizeY;
|
||||
QHBoxLayout *_maxSizeControlLayout;
|
||||
QSpinBox *_maxSizeX;
|
||||
QSpinBox *_maxSizeY;
|
||||
|
||||
QHBoxLayout *_throttleControlLayout;
|
||||
QCheckBox *_throttleEnable;
|
||||
QSpinBox *_throttleCount;
|
||||
QPushButton *_showMatch;
|
||||
|
||||
std::shared_ptr<MacroConditionVideo> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
58
src/headers/macro-condition-virtual-cam.hpp
Normal file
58
src/headers/macro-condition-virtual-cam.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifdef VCAM_SUPPORTED
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
#endif
|
||||
71
src/headers/macro-condition-window.hpp
Normal file
71
src/headers/macro-condition-window.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
class MacroConditionWindow : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionWindow>();
|
||||
}
|
||||
|
||||
private:
|
||||
bool CheckWindowTitleSwitchDirect(std::string ¤tWindowTitle);
|
||||
bool CheckWindowTitleSwitchRegex(std::string ¤tWindowTitle,
|
||||
std::vector<std::string> &windowList);
|
||||
|
||||
public:
|
||||
std::string _window;
|
||||
bool _fullscreen = false;
|
||||
bool _maximized = false;
|
||||
bool _focus = true;
|
||||
bool _windowFocusChanged = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionWindowEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionWindowEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionWindow> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionWindowEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionWindow>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void WindowChanged(const QString &text);
|
||||
void FullscreenChanged(int state);
|
||||
void MaximizedChanged(int state);
|
||||
void FocusedChanged(int state);
|
||||
void WindowFocusChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_windowSelection;
|
||||
QCheckBox *_fullscreen;
|
||||
QCheckBox *_maximized;
|
||||
QCheckBox *_focused;
|
||||
QCheckBox *_windowFocusChanged;
|
||||
std::shared_ptr<MacroConditionWindow> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
31
src/headers/macro-controls.hpp
Normal file
31
src/headers/macro-controls.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QScrollArea>
|
||||
#include <QPushButton>
|
||||
#include <QLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class MacroEntryControls : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MacroEntryControls(const int animationDuration = 300,
|
||||
QWidget *parent = 0);
|
||||
|
||||
void Show(bool visible = true);
|
||||
|
||||
signals:
|
||||
void Add();
|
||||
void Remove();
|
||||
void Up();
|
||||
void Down();
|
||||
|
||||
private:
|
||||
QPushButton *_add;
|
||||
QPushButton *_remove;
|
||||
QPushButton *_up;
|
||||
QPushButton *_down;
|
||||
QPropertyAnimation *_animation = nullptr;
|
||||
};
|
||||
72
src/headers/macro-segment.hpp
Normal file
72
src/headers/macro-segment.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#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();
|
||||
void SetCollapsed(bool collapsed);
|
||||
|
||||
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;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user