mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-07 09:05:57 -05:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
084c263260 | ||
|
|
a1c592f1ec | ||
|
|
41f34f8f40 | ||
|
|
9711390aac | ||
|
|
25f28b9796 | ||
|
|
a1484f9621 | ||
|
|
b54506c5ee | ||
|
|
4af7540497 | ||
|
|
ba15e6812f | ||
|
|
22a90c7d64 | ||
|
|
f6c3c65e26 | ||
|
|
4f6275619a | ||
|
|
d461342835 | ||
|
|
16c4a2d5a9 | ||
|
|
45a880d8f8 | ||
|
|
bcf132685b | ||
|
|
e5c1e81d81 | ||
|
|
2ae97cd90e | ||
|
|
e5fffa0b82 | ||
|
|
a0119426d6 | ||
|
|
45e5738d2c | ||
|
|
cdd1259f12 | ||
|
|
e5d6f2eef0 | ||
|
|
e026bd7420 | ||
|
|
4cc1a53244 | ||
|
|
8eb99a3fde | ||
|
|
bf30a058ee | ||
|
|
0c6a7b140e | ||
|
|
d279b35086 | ||
|
|
8e26148255 | ||
|
|
1a3ed0d09c |
59
.github/workflows/build.yml
vendored
59
.github/workflows/build.yml
vendored
@@ -19,12 +19,12 @@ jobs:
|
|||||||
MACOS_DEPS_VERSION: '2020-08-30'
|
MACOS_DEPS_VERSION: '2020-08-30'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
repository: obsproject/obs-studio
|
repository: obsproject/obs-studio
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
- name: "Checkout plugin"
|
- name: "Checkout plugin"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
|
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
|
||||||
- name: Fetch Git Tags
|
- name: Fetch Git Tags
|
||||||
@@ -34,12 +34,15 @@ jobs:
|
|||||||
- name: 'Install prerequisites (Homebrew)'
|
- name: 'Install prerequisites (Homebrew)'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}/CI/macos
|
if [ -d /usr/local/opt/openssl@1.0.2t ]; then
|
||||||
brew untap local/openssl
|
brew uninstall openssl@1.0.2t
|
||||||
brew untap local/python2
|
brew untap local/openssl
|
||||||
brew update
|
fi
|
||||||
brew bundle
|
if [ -d /usr/local/opt/python@2.7.17 ]; then
|
||||||
cd -
|
brew uninstall python@2.7.17
|
||||||
|
brew untap local/python2
|
||||||
|
fi
|
||||||
|
brew bundle --file ./CI/scripts/macos/Brewfile
|
||||||
- name: 'Install prerequisite: Pre-built dependencies'
|
- name: 'Install prerequisite: Pre-built dependencies'
|
||||||
if: steps.deps-cache.outputs.cache-hit != 'true'
|
if: steps.deps-cache.outputs.cache-hit != 'true'
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -59,7 +62,7 @@ jobs:
|
|||||||
echo "add_subdirectory(${{ env.PLUGIN_NAME }})" >> UI/frontend-plugins/CMakeLists.txt
|
echo "add_subdirectory(${{ env.PLUGIN_NAME }})" >> UI/frontend-plugins/CMakeLists.txt
|
||||||
mkdir ./build
|
mkdir ./build
|
||||||
cd ./build
|
cd ./build
|
||||||
cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 -DDISABLE_PYTHON=ON -DDepsPath="/tmp/obsdeps" -DQTDIR="/tmp/obsdeps" ..
|
cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DDISABLE_PYTHON=ON -DDepsPath="/tmp/obsdeps" -DQTDIR="/tmp/obsdeps" ..
|
||||||
cd -
|
cd -
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -86,14 +89,14 @@ jobs:
|
|||||||
install_name_tool -change /tmp/obsdeps/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ../../../build/UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
install_name_tool -change /tmp/obsdeps/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ../../../build/UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||||
FILE_DATE=$(date +%Y-%m-%d)
|
FILE_DATE=$(date +%Y-%m-%d)
|
||||||
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-macos.pkg
|
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-macos.pkg
|
||||||
echo "::set-env name=FILE_NAME::${FILE_NAME}"
|
echo "FILE_NAME=${FILE_NAME}" >> $GITHUB_ENV
|
||||||
packagesbuild ./CI/macos/${{ env.PLUGIN_NAME }}.pkgproj
|
packagesbuild ./CI/macos/${{ env.PLUGIN_NAME }}.pkgproj
|
||||||
cd -
|
cd -
|
||||||
mkdir ./nightly
|
mkdir ./nightly
|
||||||
mv UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.PLUGIN_NAME }}.pkg ./nightly/${FILE_NAME}
|
mv UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.PLUGIN_NAME }}.pkg ./nightly/${FILE_NAME}
|
||||||
- name: Publish
|
- name: Publish
|
||||||
if: success()
|
if: success()
|
||||||
uses: actions/upload-artifact@v2-preview
|
uses: actions/upload-artifact@v2.2.1
|
||||||
with:
|
with:
|
||||||
name: '${{ env.FILE_NAME }}'
|
name: '${{ env.FILE_NAME }}'
|
||||||
path: ./nightly/*.pkg
|
path: ./nightly/*.pkg
|
||||||
@@ -102,12 +105,12 @@ jobs:
|
|||||||
runs-on: [ubuntu-latest]
|
runs-on: [ubuntu-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
repository: obsproject/obs-studio
|
repository: obsproject/obs-studio
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
- name: "Checkout plugin"
|
- name: "Checkout plugin"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
|
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
|
||||||
- name: Add plugin to obs cmake
|
- name: Add plugin to obs cmake
|
||||||
@@ -166,7 +169,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir ./build
|
mkdir ./build
|
||||||
cd ./build
|
cd ./build
|
||||||
cmake -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DBUILD_CAPTIONS=OFF -DWITH_RTMPS=OFF -DBUILD_BROWSER=OFF ..
|
cmake -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DWITH_RTMPS=OFF -DBUILD_BROWSER=OFF ..
|
||||||
- name: 'Build'
|
- name: 'Build'
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ${{ github.workspace }}/build
|
working-directory: ${{ github.workspace }}/build
|
||||||
@@ -176,12 +179,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
FILE_DATE=$(date +%Y-%m-%d)
|
FILE_DATE=$(date +%Y-%m-%d)
|
||||||
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-linux64.tar.gz
|
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-linux64.tar.gz
|
||||||
echo "::set-env name=FILE_NAME::${FILE_NAME}"
|
echo "FILE_NAME=${FILE_NAME}" >> $GITHUB_ENV
|
||||||
mkdir -p ./${{ env.PLUGIN_NAME }}/bin/64bit/
|
mkdir -p ./${{ env.PLUGIN_NAME }}/bin/64bit/
|
||||||
mv ./build/UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.LIB_NAME }}.so ./${{ env.PLUGIN_NAME }}/bin/64bit/${{ env.LIB_NAME }}.so
|
mv ./build/UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.LIB_NAME }}.so ./${{ env.PLUGIN_NAME }}/bin/64bit/${{ env.LIB_NAME }}.so
|
||||||
tar -cvzf "${FILE_NAME}" ${{ env.PLUGIN_NAME }}
|
tar -cvzf "${FILE_NAME}" ${{ env.PLUGIN_NAME }}
|
||||||
- name: 'Publish'
|
- name: 'Publish'
|
||||||
uses: actions/upload-artifact@v2-preview
|
uses: actions/upload-artifact@v2.2.1
|
||||||
with:
|
with:
|
||||||
name: '${{ env.FILE_NAME }}'
|
name: '${{ env.FILE_NAME }}'
|
||||||
path: '*.tar.gz'
|
path: '*.tar.gz'
|
||||||
@@ -194,14 +197,14 @@ jobs:
|
|||||||
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
|
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
|
||||||
steps:
|
steps:
|
||||||
- name: Add msbuild to PATH
|
- name: Add msbuild to PATH
|
||||||
uses: microsoft/setup-msbuild@v1.0.0
|
uses: microsoft/setup-msbuild@v1.0.2
|
||||||
- name: Checkout obs
|
- name: Checkout obs
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
repository: obsproject/obs-studio
|
repository: obsproject/obs-studio
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
- name: Checkout plugin
|
- name: Checkout plugin
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
path: UI/frontend-plugins/${{ env.PLUGIN_NAME}}
|
path: UI/frontend-plugins/${{ env.PLUGIN_NAME}}
|
||||||
- name: Add plugin to obs cmake
|
- name: Add plugin to obs cmake
|
||||||
@@ -222,7 +225,7 @@ jobs:
|
|||||||
mkdir ./build
|
mkdir ./build
|
||||||
mkdir ./build64
|
mkdir ./build64
|
||||||
cd ./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 ..
|
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=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
|
- name: Build
|
||||||
run: msbuild /m /p:Configuration=RelWithDebInfo .\build64\obs-studio.sln
|
run: msbuild /m /p:Configuration=RelWithDebInfo .\build64\obs-studio.sln
|
||||||
- name: Package
|
- name: Package
|
||||||
@@ -230,12 +233,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
$env:FILE_DATE=(Get-Date -UFormat "%F")
|
$env:FILE_DATE=(Get-Date -UFormat "%F")
|
||||||
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-win64.zip"
|
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-win64.zip"
|
||||||
echo "::set-env name=FILE_NAME::${env:FILE_NAME}"
|
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
|
||||||
robocopy .\build64\rundir\RelWithDebInfo\obs-plugins\64bit\ .\build\obs-plugins\64bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
robocopy .\build64\rundir\RelWithDebInfo\obs-plugins\64bit\ .\build\obs-plugins\64bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
||||||
7z a ${env:FILE_NAME} .\build\*
|
7z a ${env:FILE_NAME} .\build\*
|
||||||
- name: Publish
|
- name: Publish
|
||||||
if: success()
|
if: success()
|
||||||
uses: actions/upload-artifact@v2-preview
|
uses: actions/upload-artifact@v2.2.1
|
||||||
with:
|
with:
|
||||||
name: '${{ env.FILE_NAME }}'
|
name: '${{ env.FILE_NAME }}'
|
||||||
path: '*-win64.zip'
|
path: '*-win64.zip'
|
||||||
@@ -248,14 +251,14 @@ jobs:
|
|||||||
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
|
CMAKE_SYSTEM_VERSION: "10.0.18363.657"
|
||||||
steps:
|
steps:
|
||||||
- name: Add msbuild to PATH
|
- name: Add msbuild to PATH
|
||||||
uses: microsoft/setup-msbuild@v1.0.0
|
uses: microsoft/setup-msbuild@v1.0.2
|
||||||
- name: Checkout obs
|
- name: Checkout obs
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
repository: obsproject/obs-studio
|
repository: obsproject/obs-studio
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
- name: Checkout plugin
|
- name: Checkout plugin
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
|
path: UI/frontend-plugins/${{ env.PLUGIN_NAME }}
|
||||||
- name: Add plugin to obs cmake
|
- name: Add plugin to obs cmake
|
||||||
@@ -276,7 +279,7 @@ jobs:
|
|||||||
mkdir ./build
|
mkdir ./build
|
||||||
mkdir ./build32
|
mkdir ./build32
|
||||||
cd ./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 ..
|
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=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 ..
|
||||||
- name: Build
|
- name: Build
|
||||||
run: msbuild /m /p:Configuration=RelWithDebInfo .\build32\obs-studio.sln
|
run: msbuild /m /p:Configuration=RelWithDebInfo .\build32\obs-studio.sln
|
||||||
- name: Package
|
- name: Package
|
||||||
@@ -284,12 +287,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
$env:FILE_DATE=(Get-Date -UFormat "%F")
|
$env:FILE_DATE=(Get-Date -UFormat "%F")
|
||||||
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-win32.zip"
|
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-win32.zip"
|
||||||
echo "::set-env name=FILE_NAME::${env:FILE_NAME}"
|
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
|
||||||
robocopy .\build32\rundir\RelWithDebInfo\obs-plugins\32bit\ .\build\obs-plugins\32bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
robocopy .\build32\rundir\RelWithDebInfo\obs-plugins\32bit\ .\build\obs-plugins\32bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
||||||
7z a ${env:FILE_NAME} .\build\*
|
7z a ${env:FILE_NAME} .\build\*
|
||||||
- name: Publish
|
- name: Publish
|
||||||
if: success()
|
if: success()
|
||||||
uses: actions/upload-artifact@v2-preview
|
uses: actions/upload-artifact@v2.2.1
|
||||||
with:
|
with:
|
||||||
name: '${{ env.FILE_NAME }}'
|
name: '${{ env.FILE_NAME }}'
|
||||||
path: '*-win32.zip'
|
path: '*-win32.zip'
|
||||||
|
|||||||
32
.github/workflows/clang-format.yml
vendored
Normal file
32
.github/workflows/clang-format.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: Clang Format Check
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ubuntu64:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Check the Formatting
|
||||||
|
run: |
|
||||||
|
./CI/formatcode.sh
|
||||||
|
./CI/check-format.sh
|
||||||
11
CI/check-format.sh
Executable file
11
CI/check-format.sh
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
dirty=$(git ls-files --modified)
|
||||||
|
|
||||||
|
set +x
|
||||||
|
if [[ $dirty ]]; then
|
||||||
|
echo "================================="
|
||||||
|
echo "Files were not formatted properly"
|
||||||
|
echo "$dirty"
|
||||||
|
echo "================================="
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
31
CI/formatcode.sh
Executable file
31
CI/formatcode.sh
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Original source https://github.com/Project-OSRM/osrm-backend/blob/master/scripts/format.sh
|
||||||
|
|
||||||
|
set +x
|
||||||
|
set -o errexit
|
||||||
|
set -o pipefail
|
||||||
|
set -o nounset
|
||||||
|
|
||||||
|
# Runs the Clang Formatter in parallel on the code base.
|
||||||
|
# Return codes:
|
||||||
|
# - 1 there are files to be formatted
|
||||||
|
# - 0 everything looks fine
|
||||||
|
|
||||||
|
# Get CPU count
|
||||||
|
OS=$(uname)
|
||||||
|
NPROC=1
|
||||||
|
if [[ $OS = "Linux" || $OS = "Darwin" ]] ; then
|
||||||
|
NPROC=$(getconf _NPROCESSORS_ONLN)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Discover clang-format
|
||||||
|
if 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' \
|
||||||
|
| xargs -L100 -P${NPROC} ${CLANG_FORMAT} -i -style=file -fallback-style=none
|
||||||
@@ -2,6 +2,12 @@ cmake_minimum_required(VERSION 3.5)
|
|||||||
|
|
||||||
project(advanced-scene-switcher)
|
project(advanced-scene-switcher)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
if(BUILD_OUT_OF_TREE)
|
if(BUILD_OUT_OF_TREE)
|
||||||
# out of tree builds
|
# out of tree builds
|
||||||
# credits to c3r1c3
|
# credits to c3r1c3
|
||||||
@@ -48,6 +54,7 @@ if(BUILD_OUT_OF_TREE)
|
|||||||
src/headers/switch-window.hpp
|
src/headers/switch-window.hpp
|
||||||
src/headers/switch-sequence.hpp
|
src/headers/switch-sequence.hpp
|
||||||
src/headers/switch-generic.hpp
|
src/headers/switch-generic.hpp
|
||||||
|
src/headers/version.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(advanced-scene-switcher_SOURCES
|
set(advanced-scene-switcher_SOURCES
|
||||||
@@ -73,6 +80,7 @@ if(BUILD_OUT_OF_TREE)
|
|||||||
src/switch-generic.cpp
|
src/switch-generic.cpp
|
||||||
src/curl-helper.cpp
|
src/curl-helper.cpp
|
||||||
src/volume-control.cpp
|
src/volume-control.cpp
|
||||||
|
src/version.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(advanced-scene-switcher_UI
|
set(advanced-scene-switcher_UI
|
||||||
@@ -198,6 +206,7 @@ else ()
|
|||||||
src/headers/switch-window.hpp
|
src/headers/switch-window.hpp
|
||||||
src/headers/switch-sequence.hpp
|
src/headers/switch-sequence.hpp
|
||||||
src/headers/switch-generic.hpp
|
src/headers/switch-generic.hpp
|
||||||
|
src/headers/version.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(advanced-scene-switcher_SOURCES
|
set(advanced-scene-switcher_SOURCES
|
||||||
@@ -223,6 +232,7 @@ else ()
|
|||||||
src/switch-generic.cpp
|
src/switch-generic.cpp
|
||||||
src/curl-helper.cpp
|
src/curl-helper.cpp
|
||||||
src/volume-control.cpp
|
src/volume-control.cpp
|
||||||
|
src/version.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(advanced-scene-switcher_UI
|
set(advanced-scene-switcher_UI
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ 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
|
## Compiling in tree (recommended)
|
||||||
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
|
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
|
||||||
```
|
```
|
||||||
cd obs-studio/UI/frontend-plugins/
|
cd obs-studio/UI/frontend-plugins/
|
||||||
|
|||||||
279
cmake/GetGitRevisionDescription.cmake
Normal file
279
cmake/GetGitRevisionDescription.cmake
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
# - Returns a version string from Git
|
||||||
|
#
|
||||||
|
# These functions force a re-configure on each git commit so that you can
|
||||||
|
# trust the values of the variables in your build system.
|
||||||
|
#
|
||||||
|
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the refspec and sha hash of the current head revision
|
||||||
|
#
|
||||||
|
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe on the source tree, and adjusting
|
||||||
|
# the output so that it tests false if an error occurs.
|
||||||
|
#
|
||||||
|
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe on the working tree (--dirty option),
|
||||||
|
# and adjusting the output so that it tests false if an error occurs.
|
||||||
|
#
|
||||||
|
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe --exact-match on the source tree,
|
||||||
|
# and adjusting the output so that it tests false if there was no exact
|
||||||
|
# matching tag.
|
||||||
|
#
|
||||||
|
# git_local_changes(<var>)
|
||||||
|
#
|
||||||
|
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||||
|
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||||
|
# Does not regard untracked files.
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
#
|
||||||
|
# Copyright 2009-2013, Iowa State University.
|
||||||
|
# Copyright 2013-2020, Ryan Pavlik
|
||||||
|
# Copyright 2013-2020, Contributors
|
||||||
|
# SPDX-License-Identifier: BSL-1.0
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
if(__get_git_revision_description)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(__get_git_revision_description YES)
|
||||||
|
|
||||||
|
# We must run the following at "include" time, not at function call time,
|
||||||
|
# to find the path to this module rather than the path to a calling list file
|
||||||
|
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||||
|
|
||||||
|
# Function _git_find_closest_git_dir finds the next closest .git directory
|
||||||
|
# that is part of any directory in the path defined by _start_dir.
|
||||||
|
# The result is returned in the parent scope variable whose name is passed
|
||||||
|
# as variable _git_dir_var. If no .git directory can be found, the
|
||||||
|
# function returns an empty string via _git_dir_var.
|
||||||
|
#
|
||||||
|
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
|
||||||
|
# neither foo nor bar contain a file/directory .git. This wil return
|
||||||
|
# C:/bla/.git
|
||||||
|
#
|
||||||
|
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
||||||
|
set(cur_dir "${_start_dir}")
|
||||||
|
set(git_dir "${_start_dir}/.git")
|
||||||
|
while(NOT EXISTS "${git_dir}")
|
||||||
|
# .git dir not found, search parent directories
|
||||||
|
set(git_previous_parent "${cur_dir}")
|
||||||
|
get_filename_component(cur_dir ${cur_dir} DIRECTORY)
|
||||||
|
if(cur_dir STREQUAL git_previous_parent)
|
||||||
|
# We have reached the root directory, we are not in git
|
||||||
|
set(${_git_dir_var}
|
||||||
|
""
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(git_dir "${cur_dir}/.git")
|
||||||
|
endwhile()
|
||||||
|
set(${_git_dir_var}
|
||||||
|
"${git_dir}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(get_git_head_revision _refspecvar _hashvar)
|
||||||
|
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
|
||||||
|
|
||||||
|
if(NOT "${GIT_DIR}" STREQUAL "")
|
||||||
|
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
|
||||||
|
"${GIT_DIR}")
|
||||||
|
if("${_relative_to_source_dir}" MATCHES "[.][.]")
|
||||||
|
# We've gone above the CMake root dir.
|
||||||
|
set(GIT_DIR "")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if("${GIT_DIR}" STREQUAL "")
|
||||||
|
set(${_refspecvar}
|
||||||
|
"GITDIR-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
set(${_hashvar}
|
||||||
|
"GITDIR-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check if the current source dir is a git submodule or a worktree.
|
||||||
|
# In both cases .git is a file instead of a directory.
|
||||||
|
#
|
||||||
|
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||||
|
# The following git command will return a non empty string that
|
||||||
|
# points to the super project working tree if the current
|
||||||
|
# source dir is inside a git submodule.
|
||||||
|
# Otherwise the command will return an empty string.
|
||||||
|
#
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" rev-parse
|
||||||
|
--show-superproject-working-tree
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT "${out}" STREQUAL "")
|
||||||
|
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
|
||||||
|
file(READ ${GIT_DIR} submodule)
|
||||||
|
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
|
||||||
|
${submodule})
|
||||||
|
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
|
||||||
|
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||||
|
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
|
||||||
|
ABSOLUTE)
|
||||||
|
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||||
|
else()
|
||||||
|
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
|
||||||
|
file(READ ${GIT_DIR} worktree_ref)
|
||||||
|
# The .git directory contains a path to the worktree information directory
|
||||||
|
# inside the parent git repo of the worktree.
|
||||||
|
#
|
||||||
|
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
|
||||||
|
${worktree_ref})
|
||||||
|
string(STRIP ${git_worktree_dir} git_worktree_dir)
|
||||||
|
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
|
||||||
|
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||||
|
endif()
|
||||||
|
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||||
|
if(NOT EXISTS "${GIT_DATA}")
|
||||||
|
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||||
|
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
|
||||||
|
|
||||||
|
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||||
|
"${GIT_DATA}/grabRef.cmake" @ONLY)
|
||||||
|
include("${GIT_DATA}/grabRef.cmake")
|
||||||
|
|
||||||
|
set(${_refspecvar}
|
||||||
|
"${HEAD_REF}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
set(${_hashvar}
|
||||||
|
"${HEAD_HASH}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_describe _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
get_git_head_revision(refspec hash)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var}
|
||||||
|
"GIT-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
if(NOT hash)
|
||||||
|
set(${_var}
|
||||||
|
"HEAD-HASH-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# TODO sanitize
|
||||||
|
#if((${ARGN}" MATCHES "&&") OR
|
||||||
|
# (ARGN MATCHES "||") OR
|
||||||
|
# (ARGN MATCHES "\\;"))
|
||||||
|
# message("Please report the following error to the project!")
|
||||||
|
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||||
|
#endif()
|
||||||
|
|
||||||
|
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE res
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT res EQUAL 0)
|
||||||
|
set(out "${out}-${res}-NOTFOUND")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${_var}
|
||||||
|
"${out}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_describe_working_tree _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var}
|
||||||
|
"GIT-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE res
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT res EQUAL 0)
|
||||||
|
set(out "${out}-${res}-NOTFOUND")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${_var}
|
||||||
|
"${out}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_get_exact_tag _var)
|
||||||
|
git_describe(out --exact-match ${ARGN})
|
||||||
|
set(${_var}
|
||||||
|
"${out}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_local_changes _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
get_git_head_revision(refspec hash)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var}
|
||||||
|
"GIT-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
if(NOT hash)
|
||||||
|
set(${_var}
|
||||||
|
"HEAD-HASH-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE res
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(res EQUAL 0)
|
||||||
|
set(${_var}
|
||||||
|
"CLEAN"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${_var}
|
||||||
|
"DIRTY"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
41
cmake/GetGitRevisionDescription.cmake.in
Normal file
41
cmake/GetGitRevisionDescription.cmake.in
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#
|
||||||
|
# Internal file for GetGitRevisionDescription.cmake
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
# Iowa State University HCI Graduate Program/VRAC
|
||||||
|
#
|
||||||
|
# Copyright Iowa State University 2009-2010.
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
set(HEAD_HASH)
|
||||||
|
|
||||||
|
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||||
|
|
||||||
|
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||||
|
if(HEAD_CONTENTS MATCHES "ref")
|
||||||
|
# named branch
|
||||||
|
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||||
|
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||||
|
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
else()
|
||||||
|
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||||
|
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||||
|
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||||
|
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# detached HEAD
|
||||||
|
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT HEAD_HASH)
|
||||||
|
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||||
|
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||||
|
endif()
|
||||||
3
cmake/version.cpp.in
Normal file
3
cmake/version.cpp.in
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#include "src/headers/version.h"
|
||||||
|
#define GIT_SHA1 "@GIT_SHA1@"
|
||||||
|
const char g_GIT_SHA1[] = GIT_SHA1;
|
||||||
@@ -289,13 +289,23 @@
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>If no switch condition is met</string>
|
<string>If no switch condition is met for</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="noMatchDelay">
|
||||||
|
<property name="suffix">
|
||||||
|
<string>s</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>999999.989999999990687</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@@ -586,13 +596,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="close">
|
|
||||||
<property name="text">
|
|
||||||
<string>Close</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="transitionsTab">
|
<widget class="QWidget" name="transitionsTab">
|
||||||
@@ -1172,7 +1175,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="titleTab">
|
<widget class="QWidget" name="windowTitleTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string notr="true">Title</string>
|
<string notr="true">Title</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
@@ -2624,7 +2627,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="IdleTab">
|
<widget class="QWidget" name="idleTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string notr="true">Idle</string>
|
<string notr="true">Idle</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
@@ -3176,6 +3179,13 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="close">
|
||||||
|
<property name="text">
|
||||||
|
<string>Close</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "headers/advanced-scene-switcher.hpp"
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
#include "headers/curl-helper.hpp"
|
#include "headers/curl-helper.hpp"
|
||||||
|
#include "headers/version.h"
|
||||||
|
|
||||||
SwitcherData *switcher = nullptr;
|
SwitcherData *switcher = nullptr;
|
||||||
|
|
||||||
@@ -328,34 +329,49 @@ void SwitcherData::Thread()
|
|||||||
{
|
{
|
||||||
blog(LOG_INFO, "started");
|
blog(LOG_INFO, "started");
|
||||||
int sleep = 0;
|
int sleep = 0;
|
||||||
|
std::chrono::milliseconds duration;
|
||||||
|
auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
|
auto endTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
startLoop:
|
|
||||||
std::unique_lock<std::mutex> lock(m);
|
std::unique_lock<std::mutex> lock(m);
|
||||||
|
|
||||||
bool match = false;
|
bool match = false;
|
||||||
OBSWeakSource scene;
|
OBSWeakSource scene;
|
||||||
OBSWeakSource transition;
|
OBSWeakSource transition;
|
||||||
std::chrono::milliseconds duration;
|
|
||||||
if (sleep > interval) {
|
bool defTransitionMatch = false;
|
||||||
|
OBSWeakSource defTransition;
|
||||||
|
|
||||||
|
endTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
auto runTime =
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
endTime - startTime);
|
||||||
|
|
||||||
|
if (sleep) {
|
||||||
duration = std::chrono::milliseconds(sleep);
|
duration = std::chrono::milliseconds(sleep);
|
||||||
if (verbose)
|
|
||||||
blog(LOG_INFO, "sleep for %d", sleep);
|
|
||||||
} else {
|
} else {
|
||||||
duration = std::chrono::milliseconds(interval);
|
duration =
|
||||||
if (verbose)
|
std::chrono::milliseconds(interval) - runTime;
|
||||||
blog(LOG_INFO, "sleep for %d", interval);
|
if (duration.count() < 0)
|
||||||
|
duration = std::chrono::milliseconds(0);
|
||||||
}
|
}
|
||||||
sleep = 0;
|
|
||||||
switcher->Prune();
|
|
||||||
writeSceneInfoToFile();
|
|
||||||
//sleep for a bit
|
//sleep for a bit
|
||||||
|
if (verbose)
|
||||||
|
blog(LOG_INFO, "sleep for %d", duration.count());
|
||||||
cv.wait_for(lock, duration);
|
cv.wait_for(lock, duration);
|
||||||
|
|
||||||
|
startTime = std::chrono::high_resolution_clock::now();
|
||||||
|
sleep = 0;
|
||||||
|
|
||||||
|
switcher->Prune();
|
||||||
|
|
||||||
if (switcher->stop) {
|
if (switcher->stop) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefaultSceneTransitions();
|
|
||||||
|
|
||||||
if (autoStopEnable) {
|
if (autoStopEnable) {
|
||||||
autoStopStreamAndRecording();
|
autoStopStreamAndRecording();
|
||||||
}
|
}
|
||||||
@@ -368,6 +384,8 @@ void SwitcherData::Thread()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkDefaultSceneTransitions(defTransitionMatch, defTransition);
|
||||||
|
|
||||||
for (int switchFuncName : functionNamesByPriority) {
|
for (int switchFuncName : functionNamesByPriority) {
|
||||||
switch (switchFuncName) {
|
switch (switchFuncName) {
|
||||||
case read_file_func:
|
case read_file_func:
|
||||||
@@ -381,7 +399,6 @@ void SwitcherData::Thread()
|
|||||||
case exe_func:
|
case exe_func:
|
||||||
checkExeSwitch(match, scene, transition);
|
checkExeSwitch(match, scene, transition);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case screen_region_func:
|
case screen_region_func:
|
||||||
checkScreenRegionSwitch(match, scene,
|
checkScreenRegionSwitch(match, scene,
|
||||||
transition);
|
transition);
|
||||||
@@ -393,10 +410,6 @@ void SwitcherData::Thread()
|
|||||||
case round_trip_func:
|
case round_trip_func:
|
||||||
checkSceneSequence(match, scene, transition,
|
checkSceneSequence(match, scene, transition,
|
||||||
lock);
|
lock);
|
||||||
if (sceneChangedDuringWait()) //scene might have changed during the sleep
|
|
||||||
{
|
|
||||||
goto startLoop;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case media_func:
|
case media_func:
|
||||||
checkMediaSwitch(match, scene, transition);
|
checkMediaSwitch(match, scene, transition);
|
||||||
@@ -417,44 +430,44 @@ void SwitcherData::Thread()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!match && switchIfNotMatching == SWITCH &&
|
checkNoMatchSwitch(match, scene, transition, sleep);
|
||||||
nonMatchingScene) {
|
|
||||||
match = true;
|
// After this point we will call frontend functions
|
||||||
scene = nonMatchingScene;
|
// obs_frontend_set_current_scene() and
|
||||||
transition = nullptr;
|
// obs_frontend_set_current_transition()
|
||||||
}
|
//
|
||||||
if (!match && switchIfNotMatching == RANDOM_SWITCH) {
|
// During this time SaveSceneSwitcher() could be called
|
||||||
checkRandom(match, scene, transition, sleep);
|
// leading to a deadlock, so we have to unlock()
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
if (!match && defTransitionMatch) {
|
||||||
|
setCurrentDefTransition(defTransition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
switchScene(scene, transition,
|
switchScene(scene, transition,
|
||||||
tansitionOverrideOverride, lock);
|
tansitionOverrideOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writeSceneInfoToFile();
|
||||||
}
|
}
|
||||||
endLoop:
|
endLoop:
|
||||||
blog(LOG_INFO, "stopped");
|
blog(LOG_INFO, "stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
|
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||||
bool &transitionOverrideOverride,
|
bool &transitionOverrideOverride)
|
||||||
std::unique_lock<std::mutex> &lock)
|
|
||||||
{
|
{
|
||||||
obs_source_t *source = obs_weak_source_get_source(scene);
|
obs_source_t *source = obs_weak_source_get_source(scene);
|
||||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||||
|
|
||||||
if (source && source != currentSource) {
|
if (source && source != currentSource) {
|
||||||
|
|
||||||
// this call might block when OBS_FRONTEND_EVENT_SCENE_CHANGED is active and mutex is held
|
|
||||||
// thus unlock mutex to avoid deadlock
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
transitionData td;
|
transitionData td;
|
||||||
setNextTransition(scene, currentSource, transition,
|
setNextTransition(scene, currentSource, transition,
|
||||||
transitionOverrideOverride, td);
|
transitionOverrideOverride, td);
|
||||||
obs_frontend_set_current_scene(source);
|
obs_frontend_set_current_scene(source);
|
||||||
if (transitionOverrideOverride)
|
if (transitionOverrideOverride)
|
||||||
restoreTransitionOverride(source, td);
|
restoreTransitionOverride(source, td);
|
||||||
lock.lock();
|
|
||||||
|
|
||||||
if (switcher->verbose)
|
if (switcher->verbose)
|
||||||
blog(LOG_INFO, "switched scene");
|
blog(LOG_INFO, "switched scene");
|
||||||
@@ -463,18 +476,6 @@ void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
|
|||||||
obs_source_release(source);
|
obs_source_release(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwitcherData::sceneChangedDuringWait()
|
|
||||||
{
|
|
||||||
bool r = false;
|
|
||||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
|
||||||
if (!currentSource)
|
|
||||||
return true;
|
|
||||||
obs_source_release(currentSource);
|
|
||||||
if (waitScene && currentSource != waitScene)
|
|
||||||
r = true;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::Start()
|
void SwitcherData::Start()
|
||||||
{
|
{
|
||||||
if (!(th && th->isRunning())) {
|
if (!(th && th->isRunning())) {
|
||||||
@@ -497,6 +498,15 @@ void SwitcherData::Stop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SwitcherData::sceneChangedDuringWait()
|
||||||
|
{
|
||||||
|
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||||
|
if (!currentSource)
|
||||||
|
return true;
|
||||||
|
obs_source_release(currentSource);
|
||||||
|
return (waitScene && currentSource != waitScene);
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* OBS module setup
|
* OBS module setup
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
@@ -515,7 +525,6 @@ extern "C" void FreeSceneSwitcher()
|
|||||||
|
|
||||||
void handleSceneChange(SwitcherData *s)
|
void handleSceneChange(SwitcherData *s)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(s->m);
|
|
||||||
//stop waiting if scene was manually changed
|
//stop waiting if scene was manually changed
|
||||||
if (s->sceneChangedDuringWait())
|
if (s->sceneChangedDuringWait())
|
||||||
s->cv.notify_one();
|
s->cv.notify_one();
|
||||||
@@ -525,14 +534,18 @@ void handleSceneChange(SwitcherData *s)
|
|||||||
obs_weak_source_t *ws = obs_source_get_weak_source(source);
|
obs_weak_source_t *ws = obs_source_get_weak_source(source);
|
||||||
obs_source_release(source);
|
obs_source_release(source);
|
||||||
obs_weak_source_release(ws);
|
obs_weak_source_release(ws);
|
||||||
if (source && s->PreviousScene2 != ws) {
|
if (source && s->previousScene2 != ws) {
|
||||||
s->previousScene = s->PreviousScene2;
|
s->previousScene = s->previousScene2;
|
||||||
s->PreviousScene2 = ws;
|
s->previousScene2 = ws;
|
||||||
}
|
}
|
||||||
|
|
||||||
//reset events only hanled on scene change
|
//reset events only hanled on scene change
|
||||||
s->autoStartedRecently = false;
|
s->autoStartedRecently = false;
|
||||||
s->changedDefTransitionRecently = false;
|
}
|
||||||
|
|
||||||
|
void handleTransitionStop(SwitcherData *s)
|
||||||
|
{
|
||||||
|
s->checkedDefTransition = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLiveTime(SwitcherData *s)
|
void setLiveTime(SwitcherData *s)
|
||||||
@@ -545,6 +558,9 @@ void resetLiveTime(SwitcherData *s)
|
|||||||
s->liveTime = QDateTime();
|
s->liveTime = QDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note to future self:
|
||||||
|
// be careful using switcher->m here as there is potential for deadlocks when using
|
||||||
|
// frontend functions such as obs_frontend_set_current_scene()
|
||||||
static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
@@ -554,6 +570,9 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
|||||||
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
||||||
handleSceneChange((SwitcherData *)switcher);
|
handleSceneChange((SwitcherData *)switcher);
|
||||||
break;
|
break;
|
||||||
|
case OBS_FRONTEND_EVENT_TRANSITION_STOPPED:
|
||||||
|
handleTransitionStop((SwitcherData *)switcher);
|
||||||
|
break;
|
||||||
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
|
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
|
||||||
case OBS_FRONTEND_EVENT_STREAMING_STARTED:
|
case OBS_FRONTEND_EVENT_STREAMING_STARTED:
|
||||||
setLiveTime((SwitcherData *)switcher);
|
setLiveTime((SwitcherData *)switcher);
|
||||||
@@ -569,6 +588,8 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
|||||||
|
|
||||||
extern "C" void InitSceneSwitcher()
|
extern "C" void InitSceneSwitcher()
|
||||||
{
|
{
|
||||||
|
blog(LOG_INFO, "version: %s", g_GIT_SHA1);
|
||||||
|
|
||||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
|
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
|
||||||
"Advanced Scene Switcher");
|
"Advanced Scene Switcher");
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ bool loadCurl()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (QString path : locations) {
|
for (QString path : locations) {
|
||||||
blog(LOG_INFO, "[adv-ss] trying '%s'", path.toUtf8().constData());
|
blog(LOG_INFO, "[adv-ss] trying '%s'",
|
||||||
|
path.toUtf8().constData());
|
||||||
QFileInfo libPath(
|
QFileInfo libPath(
|
||||||
QDir(path).absoluteFilePath(curl_library_name));
|
QDir(path).absoluteFilePath(curl_library_name));
|
||||||
|
|
||||||
|
|||||||
115
src/general.cpp
115
src/general.cpp
@@ -56,6 +56,14 @@ void AdvSceneSwitcher::on_noMatchRandomSwitch_clicked()
|
|||||||
ui->randomDisabledWarning->setVisible(false);
|
ui->randomDisabledWarning->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::on_noMatchDelay_valueChanged(double i)
|
||||||
|
{
|
||||||
|
if (loading)
|
||||||
|
return;
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
switcher->noMatchDelay = i;
|
||||||
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
|
void AdvSceneSwitcher::on_startupBehavior_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
if (loading)
|
if (loading)
|
||||||
@@ -158,10 +166,18 @@ void SwitcherData::autoStopStreamAndRecording()
|
|||||||
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
|
obs_weak_source_t *ws = obs_source_get_weak_source(currentSource);
|
||||||
|
|
||||||
if (ws && autoStopScene == ws) {
|
if (ws && autoStopScene == ws) {
|
||||||
if (obs_frontend_streaming_active())
|
if (obs_frontend_streaming_active()) {
|
||||||
|
blog(LOG_INFO,
|
||||||
|
"Stopping stream because scene '%s' is active",
|
||||||
|
obs_source_get_name(currentSource));
|
||||||
obs_frontend_streaming_stop();
|
obs_frontend_streaming_stop();
|
||||||
if (obs_frontend_recording_active())
|
}
|
||||||
|
if (obs_frontend_recording_active()) {
|
||||||
|
blog(LOG_INFO,
|
||||||
|
"Stopping record because scene '%s' is active",
|
||||||
|
obs_source_get_name(currentSource));
|
||||||
obs_frontend_recording_stop();
|
obs_frontend_recording_stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
obs_source_release(currentSource);
|
obs_source_release(currentSource);
|
||||||
obs_weak_source_release(ws);
|
obs_weak_source_release(ws);
|
||||||
@@ -226,12 +242,20 @@ void SwitcherData::autoStartStreamRecording()
|
|||||||
if (ws && autoStartScene == ws) {
|
if (ws && autoStartScene == ws) {
|
||||||
if ((switcher->autoStartType == STREAMING ||
|
if ((switcher->autoStartType == STREAMING ||
|
||||||
switcher->autoStartType == RECORINDGSTREAMING) &&
|
switcher->autoStartType == RECORINDGSTREAMING) &&
|
||||||
!obs_frontend_streaming_active())
|
!obs_frontend_streaming_active()) {
|
||||||
|
blog(LOG_INFO,
|
||||||
|
"Starting stream because scene '%s' is active",
|
||||||
|
obs_source_get_name(currentSource));
|
||||||
obs_frontend_streaming_start();
|
obs_frontend_streaming_start();
|
||||||
|
}
|
||||||
if ((switcher->autoStartType == RECORDING ||
|
if ((switcher->autoStartType == RECORDING ||
|
||||||
switcher->autoStartType == RECORINDGSTREAMING) &&
|
switcher->autoStartType == RECORINDGSTREAMING) &&
|
||||||
!obs_frontend_recording_active())
|
!obs_frontend_recording_active()) {
|
||||||
|
blog(LOG_INFO,
|
||||||
|
"Starting record because scene '%s' is active",
|
||||||
|
obs_source_get_name(currentSource));
|
||||||
obs_frontend_recording_start();
|
obs_frontend_recording_start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
obs_source_release(currentSource);
|
obs_source_release(currentSource);
|
||||||
obs_weak_source_release(ws);
|
obs_weak_source_release(ws);
|
||||||
@@ -337,58 +361,56 @@ void AdvSceneSwitcher::on_importSettings_clicked()
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
int findTabIndex(QTabBar *bar, int pos)
|
int findTabIndex(QTabWidget *tabWidget, int pos)
|
||||||
{
|
{
|
||||||
int at = -1;
|
int at = -1;
|
||||||
|
|
||||||
QString tabName = "";
|
QString tabName = "";
|
||||||
switch (pos) {
|
switch (pos) {
|
||||||
case 0:
|
case 0:
|
||||||
tabName = "General";
|
tabName = "generalTab";
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
tabName = "Transition";
|
tabName = "transitionsTab";
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
tabName = "Pause";
|
tabName = "pauseScenesTab";
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
tabName = "Title";
|
tabName = "windowTitleTab";
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
tabName = "Executable";
|
tabName = "executableTab";
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
tabName = "Region";
|
tabName = "screenRegionTab";
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
tabName = "Media";
|
tabName = "mediaTab";
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
tabName = "File";
|
tabName = "fileTab";
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
tabName = "Random";
|
tabName = "randomTab";
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
tabName = "Time";
|
tabName = "timeTab";
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
tabName = "Idle";
|
tabName = "idleTab";
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
tabName = "Sequence";
|
tabName = "sceneSequenceTab";
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
tabName = "Audio";
|
tabName = "audioTab";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < bar->count(); ++i) {
|
QWidget *page = tabWidget->findChild<QWidget *>(tabName);
|
||||||
if (bar->tabText(i).compare(tabName) == 0) {
|
if (page) {
|
||||||
at = i;
|
at = tabWidget->indexOf(page);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (at == -1)
|
if (at == -1)
|
||||||
blog(LOG_INFO, "failed to find tab %s",
|
blog(LOG_INFO, "failed to find tab %s",
|
||||||
@@ -401,7 +423,7 @@ void AdvSceneSwitcher::setTabOrder()
|
|||||||
{
|
{
|
||||||
QTabBar *bar = ui->tabWidget->tabBar();
|
QTabBar *bar = ui->tabWidget->tabBar();
|
||||||
for (int i = 0; i < bar->count(); ++i) {
|
for (int i = 0; i < bar->count(); ++i) {
|
||||||
int curPos = findTabIndex(bar, switcher->tabOrder[i]);
|
int curPos = findTabIndex(ui->tabWidget, switcher->tabOrder[i]);
|
||||||
|
|
||||||
if (i != curPos && curPos != -1)
|
if (i != curPos && curPos != -1)
|
||||||
bar->moveTab(curPos, i);
|
bar->moveTab(curPos, i);
|
||||||
@@ -417,6 +439,15 @@ void AdvSceneSwitcher::on_tabMoved(int from, int to)
|
|||||||
std::swap(switcher->tabOrder[from], switcher->tabOrder[to]);
|
std::swap(switcher->tabOrder[from], switcher->tabOrder[to]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::on_tabWidget_currentChanged(int index)
|
||||||
|
{
|
||||||
|
UNUSED_PARAMETER(index);
|
||||||
|
|
||||||
|
switcher->showFrame = false;
|
||||||
|
clearFrames(ui->screenRegionSwitches);
|
||||||
|
SetShowFrames();
|
||||||
|
}
|
||||||
|
|
||||||
void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
obs_data_set_int(obj, "interval", switcher->interval);
|
obs_data_set_int(obj, "interval", switcher->interval);
|
||||||
@@ -427,6 +458,7 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
|||||||
nonMatchingSceneName.c_str());
|
nonMatchingSceneName.c_str());
|
||||||
obs_data_set_int(obj, "switch_if_not_matching",
|
obs_data_set_int(obj, "switch_if_not_matching",
|
||||||
switcher->switchIfNotMatching);
|
switcher->switchIfNotMatching);
|
||||||
|
obs_data_set_double(obj, "noMatchDelay", switcher->noMatchDelay);
|
||||||
|
|
||||||
obs_data_set_bool(obj, "active", !switcher->stop);
|
obs_data_set_bool(obj, "active", !switcher->stop);
|
||||||
obs_data_set_int(obj, "startup_behavior", switcher->startupBehavior);
|
obs_data_set_int(obj, "startup_behavior", switcher->startupBehavior);
|
||||||
@@ -468,6 +500,14 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
|||||||
|
|
||||||
obs_data_set_int(obj, "threadPriority", switcher->threadPriority);
|
obs_data_set_int(obj, "threadPriority", switcher->threadPriority);
|
||||||
|
|
||||||
|
// After fresh install of OBS the vector can be empty
|
||||||
|
// as save() might be called before first load()
|
||||||
|
if (switcher->tabOrder.size() < 13) {
|
||||||
|
switcher->tabOrder = std::vector<int>(13);
|
||||||
|
std::iota(switcher->tabOrder.begin(), switcher->tabOrder.end(),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
obs_data_set_int(obj, "generalTabPos", switcher->tabOrder[0]);
|
obs_data_set_int(obj, "generalTabPos", switcher->tabOrder[0]);
|
||||||
obs_data_set_int(obj, "transitionTabPos", switcher->tabOrder[1]);
|
obs_data_set_int(obj, "transitionTabPos", switcher->tabOrder[1]);
|
||||||
obs_data_set_int(obj, "pauseTabPos", switcher->tabOrder[2]);
|
obs_data_set_int(obj, "pauseTabPos", switcher->tabOrder[2]);
|
||||||
@@ -495,6 +535,7 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
obs_data_get_string(obj, "non_matching_scene");
|
obs_data_get_string(obj, "non_matching_scene");
|
||||||
switcher->nonMatchingScene =
|
switcher->nonMatchingScene =
|
||||||
GetWeakSourceByName(nonMatchingScene.c_str());
|
GetWeakSourceByName(nonMatchingScene.c_str());
|
||||||
|
switcher->noMatchDelay = obs_data_get_double(obj, "noMatchDelay");
|
||||||
|
|
||||||
switcher->stop = !obs_data_get_bool(obj, "active");
|
switcher->stop = !obs_data_get_bool(obj, "active");
|
||||||
switcher->startupBehavior =
|
switcher->startupBehavior =
|
||||||
@@ -605,6 +646,29 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
(int)(obs_data_get_int(obj, "audioTabPos")));
|
(int)(obs_data_get_int(obj, "audioTabPos")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwitcherData::checkNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
||||||
|
OBSWeakSource &transition, int &sleep)
|
||||||
|
{
|
||||||
|
if (match) {
|
||||||
|
noMatchCount = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((noMatchCount * interval) / 1000.0 < noMatchDelay) {
|
||||||
|
noMatchCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switchIfNotMatching == SWITCH && nonMatchingScene) {
|
||||||
|
match = true;
|
||||||
|
scene = nonMatchingScene;
|
||||||
|
transition = nullptr;
|
||||||
|
}
|
||||||
|
if (switchIfNotMatching == RANDOM_SWITCH) {
|
||||||
|
checkRandom(match, scene, transition, sleep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::setupGeneralTab()
|
void AdvSceneSwitcher::setupGeneralTab()
|
||||||
{
|
{
|
||||||
populateSceneSelection(ui->noMatchSwitchScene, false);
|
populateSceneSelection(ui->noMatchSwitchScene, false);
|
||||||
@@ -623,6 +687,9 @@ void AdvSceneSwitcher::setupGeneralTab()
|
|||||||
}
|
}
|
||||||
ui->noMatchSwitchScene->setCurrentText(
|
ui->noMatchSwitchScene->setCurrentText(
|
||||||
GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
||||||
|
ui->noMatchDelay->setValue(switcher->noMatchDelay);
|
||||||
|
ui->noMatchDelay->setToolTip(
|
||||||
|
"Will only ever be as accurate as the configured check interval.");
|
||||||
ui->checkInterval->setValue(switcher->interval);
|
ui->checkInterval->setValue(switcher->interval);
|
||||||
|
|
||||||
ui->autoStopSceneCheckBox->setChecked(switcher->autoStopEnable);
|
ui->autoStopSceneCheckBox->setChecked(switcher->autoStopEnable);
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ public:
|
|||||||
void SetStarted();
|
void SetStarted();
|
||||||
void SetStopped();
|
void SetStopped();
|
||||||
|
|
||||||
|
void SetShowFrames();
|
||||||
|
void SetHideFrames();
|
||||||
|
void clearFrames(QListWidget *list);
|
||||||
|
|
||||||
int PauseScenesFindByData(const QString &scene);
|
int PauseScenesFindByData(const QString &scene);
|
||||||
int PauseWindowsFindByData(const QString &window);
|
int PauseWindowsFindByData(const QString &window);
|
||||||
int IgnoreWindowsFindByData(const QString &window);
|
int IgnoreWindowsFindByData(const QString &window);
|
||||||
@@ -82,11 +86,13 @@ public slots:
|
|||||||
void on_noMatchDontSwitch_clicked();
|
void on_noMatchDontSwitch_clicked();
|
||||||
void on_noMatchSwitch_clicked();
|
void on_noMatchSwitch_clicked();
|
||||||
void on_noMatchRandomSwitch_clicked();
|
void on_noMatchRandomSwitch_clicked();
|
||||||
|
void on_noMatchDelay_valueChanged(double i);
|
||||||
void on_startupBehavior_currentIndexChanged(int index);
|
void on_startupBehavior_currentIndexChanged(int index);
|
||||||
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
||||||
void on_checkInterval_valueChanged(int value);
|
void on_checkInterval_valueChanged(int value);
|
||||||
void on_toggleStartButton_clicked();
|
void on_toggleStartButton_clicked();
|
||||||
void on_tabMoved(int from, int to);
|
void on_tabMoved(int from, int to);
|
||||||
|
void on_tabWidget_currentChanged(int index);
|
||||||
|
|
||||||
void on_screenRegionSwitches_currentRowChanged(int idx);
|
void on_screenRegionSwitches_currentRowChanged(int idx);
|
||||||
void on_showFrame_clicked();
|
void on_showFrame_clicked();
|
||||||
@@ -228,10 +234,8 @@ void setNextTransition(OBSWeakSource &targetScene, obs_source_t *currentSource,
|
|||||||
void overwriteTransitionOverride(obs_weak_source_t *sceneWs,
|
void overwriteTransitionOverride(obs_weak_source_t *sceneWs,
|
||||||
obs_source_t *transition, transitionData &td);
|
obs_source_t *transition, transitionData &td);
|
||||||
void restoreTransitionOverride(obs_source_t *scene, transitionData td);
|
void restoreTransitionOverride(obs_source_t *scene, transitionData td);
|
||||||
|
|
||||||
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
|
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||||
bool &transitionOverrideOverride,
|
bool &transitionOverrideOverride);
|
||||||
std::unique_lock<std::mutex> &lock);
|
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* Main SwitcherData
|
* Main SwitcherData
|
||||||
|
|||||||
@@ -18,12 +18,18 @@ struct MediaSwitch : SceneSwitcherEntry {
|
|||||||
bool anyState = false;
|
bool anyState = false;
|
||||||
time_restriction restriction = TIME_RESTRICTION_NONE;
|
time_restriction restriction = TIME_RESTRICTION_NONE;
|
||||||
int64_t time = 0;
|
int64_t time = 0;
|
||||||
|
|
||||||
|
// trigger scene change only once even if media state might trigger repeatedly
|
||||||
|
bool matched = false;
|
||||||
|
|
||||||
std::atomic<bool> stopped = false;
|
std::atomic<bool> stopped = false;
|
||||||
std::atomic<bool> ended = false;
|
std::atomic<bool> ended = false;
|
||||||
|
|
||||||
// workaround to enable use of "ended" to specify end of VLC playlist
|
// workaround to enable use of "ended" to specify end of VLC playlist
|
||||||
bool previousStateEnded = false;
|
bool previousStateEnded = false;
|
||||||
|
|
||||||
|
bool playedToEnd = false;
|
||||||
|
|
||||||
const char *getType() { return "media"; }
|
const char *getType() { return "media"; }
|
||||||
bool initialized();
|
bool initialized();
|
||||||
bool valid();
|
bool valid();
|
||||||
|
|||||||
@@ -57,12 +57,14 @@ struct SwitcherData {
|
|||||||
|
|
||||||
int interval = default_interval;
|
int interval = default_interval;
|
||||||
|
|
||||||
obs_source_t *waitScene = NULL;
|
obs_source_t *waitScene = nullptr;
|
||||||
OBSWeakSource previousScene = NULL;
|
OBSWeakSource previousScene = nullptr;
|
||||||
OBSWeakSource PreviousScene2 = NULL;
|
OBSWeakSource previousScene2 = nullptr;
|
||||||
OBSWeakSource lastRandomScene;
|
OBSWeakSource lastRandomScene;
|
||||||
OBSWeakSource nonMatchingScene;
|
OBSWeakSource nonMatchingScene;
|
||||||
NoMatch switchIfNotMatching = NO_SWITCH;
|
NoMatch switchIfNotMatching = NO_SWITCH;
|
||||||
|
double noMatchDelay;
|
||||||
|
double noMatchCount = 0;
|
||||||
StartupBehavior startupBehavior = PERSIST;
|
StartupBehavior startupBehavior = PERSIST;
|
||||||
|
|
||||||
std::deque<WindowSwitch> windowSwitches;
|
std::deque<WindowSwitch> windowSwitches;
|
||||||
@@ -99,7 +101,7 @@ struct SwitcherData {
|
|||||||
|
|
||||||
std::deque<SceneTransition> sceneTransitions;
|
std::deque<SceneTransition> sceneTransitions;
|
||||||
std::deque<DefaultSceneTransition> defaultSceneTransitions;
|
std::deque<DefaultSceneTransition> defaultSceneTransitions;
|
||||||
bool changedDefTransitionRecently = false;
|
bool checkedDefTransition = false;
|
||||||
|
|
||||||
std::deque<MediaSwitch> mediaSwitches;
|
std::deque<MediaSwitch> mediaSwitches;
|
||||||
|
|
||||||
@@ -143,9 +145,9 @@ struct SwitcherData {
|
|||||||
std::vector<int> tabOrder;
|
std::vector<int> tabOrder;
|
||||||
|
|
||||||
bool hotkeysRegistered = false;
|
bool hotkeysRegistered = false;
|
||||||
obs_hotkey_id startHotkey;
|
obs_hotkey_id startHotkey = 0;
|
||||||
obs_hotkey_id stopHotkey;
|
obs_hotkey_id stopHotkey = 0;
|
||||||
obs_hotkey_id toggleHotkey;
|
obs_hotkey_id toggleHotkey = 0;
|
||||||
|
|
||||||
void Thread();
|
void Thread();
|
||||||
void Start();
|
void Start();
|
||||||
@@ -154,10 +156,12 @@ struct SwitcherData {
|
|||||||
bool sceneChangedDuringWait();
|
bool sceneChangedDuringWait();
|
||||||
bool prioFuncsValid();
|
bool prioFuncsValid();
|
||||||
void writeSceneInfoToFile();
|
void writeSceneInfoToFile();
|
||||||
void setDefaultSceneTransitions();
|
|
||||||
void autoStopStreamAndRecording();
|
void autoStopStreamAndRecording();
|
||||||
void autoStartStreamRecording();
|
void autoStartStreamRecording();
|
||||||
bool checkPause();
|
bool checkPause();
|
||||||
|
void checkDefaultSceneTransitions(bool &match,
|
||||||
|
OBSWeakSource &transition);
|
||||||
|
void setCurrentDefTransition(OBSWeakSource &transition);
|
||||||
void checkSceneSequence(bool &match, OBSWeakSource &scene,
|
void checkSceneSequence(bool &match, OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition,
|
OBSWeakSource &transition,
|
||||||
std::unique_lock<std::mutex> &lock);
|
std::unique_lock<std::mutex> &lock);
|
||||||
@@ -181,6 +185,8 @@ struct SwitcherData {
|
|||||||
OBSWeakSource &transition);
|
OBSWeakSource &transition);
|
||||||
void checkAudioSwitch(bool &match, OBSWeakSource &scene,
|
void checkAudioSwitch(bool &match, OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition);
|
OBSWeakSource &transition);
|
||||||
|
void checkNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
||||||
|
OBSWeakSource &transition, int &sleep);
|
||||||
|
|
||||||
void saveWindowTitleSwitches(obs_data_t *obj);
|
void saveWindowTitleSwitches(obs_data_t *obj);
|
||||||
void saveScreenRegionSwitches(obs_data_t *obj);
|
void saveScreenRegionSwitches(obs_data_t *obj);
|
||||||
@@ -213,6 +219,7 @@ struct SwitcherData {
|
|||||||
void loadHotkeys(obs_data_t *obj);
|
void loadHotkeys(obs_data_t *obj);
|
||||||
|
|
||||||
void Prune();
|
void Prune();
|
||||||
|
|
||||||
inline ~SwitcherData() { Stop(); }
|
inline ~SwitcherData() { Stop(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
1
src/headers/version.h
Normal file
1
src/headers/version.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern const char g_GIT_SHA1[];
|
||||||
@@ -17,15 +17,16 @@ void GetWindowList(std::vector<std::string> &windows)
|
|||||||
for (NSDictionary *app in apps) {
|
for (NSDictionary *app in apps) {
|
||||||
// Construct string from NSString accounting for nil
|
// Construct string from NSString accounting for nil
|
||||||
std::string name([[app objectForKey:@"kCGWindowName"]
|
std::string name([[app objectForKey:@"kCGWindowName"]
|
||||||
UTF8String],
|
UTF8String],
|
||||||
[[app objectForKey:@"kCGWindowName"]
|
[[app objectForKey:@"kCGWindowName"]
|
||||||
lengthOfBytesUsingEncoding:
|
lengthOfBytesUsingEncoding:
|
||||||
NSUTF8StringEncoding]);
|
NSUTF8StringEncoding]);
|
||||||
std::string owner([[app objectForKey:@"kCGWindowOwnerName"]
|
std::string owner(
|
||||||
UTF8String],
|
[[app objectForKey:@"kCGWindowOwnerName"]
|
||||||
[[app objectForKey:@"kCGWindowOwnerName"]
|
UTF8String],
|
||||||
lengthOfBytesUsingEncoding:
|
[[app objectForKey:@"kCGWindowOwnerName"]
|
||||||
NSUTF8StringEncoding]);
|
lengthOfBytesUsingEncoding:
|
||||||
|
NSUTF8StringEncoding]);
|
||||||
|
|
||||||
// Check if name exists
|
// Check if name exists
|
||||||
if (!name.empty() &&
|
if (!name.empty() &&
|
||||||
@@ -53,15 +54,16 @@ void GetWindowList(QStringList &windows)
|
|||||||
for (NSDictionary *app in apps) {
|
for (NSDictionary *app in apps) {
|
||||||
// Construct string from NSString accounting for nil
|
// Construct string from NSString accounting for nil
|
||||||
std::string name([[app objectForKey:@"kCGWindowName"]
|
std::string name([[app objectForKey:@"kCGWindowName"]
|
||||||
UTF8String],
|
UTF8String],
|
||||||
[[app objectForKey:@"kCGWindowName"]
|
[[app objectForKey:@"kCGWindowName"]
|
||||||
lengthOfBytesUsingEncoding:
|
lengthOfBytesUsingEncoding:
|
||||||
NSUTF8StringEncoding]);
|
NSUTF8StringEncoding]);
|
||||||
std::string owner([[app objectForKey:@"kCGWindowOwnerName"]
|
std::string owner(
|
||||||
UTF8String],
|
[[app objectForKey:@"kCGWindowOwnerName"]
|
||||||
[[app objectForKey:@"kCGWindowOwnerName"]
|
UTF8String],
|
||||||
lengthOfBytesUsingEncoding:
|
[[app objectForKey:@"kCGWindowOwnerName"]
|
||||||
NSUTF8StringEncoding]);
|
lengthOfBytesUsingEncoding:
|
||||||
|
NSUTF8StringEncoding]);
|
||||||
|
|
||||||
// Check if name exists
|
// Check if name exists
|
||||||
if (!name.empty() &&
|
if (!name.empty() &&
|
||||||
@@ -144,15 +146,16 @@ bool isFullscreen(std::string &title)
|
|||||||
for (NSDictionary *app in apps) {
|
for (NSDictionary *app in apps) {
|
||||||
// Construct string from NSString accounting for nil
|
// Construct string from NSString accounting for nil
|
||||||
std::string name([[app objectForKey:@"kCGWindowName"]
|
std::string name([[app objectForKey:@"kCGWindowName"]
|
||||||
UTF8String],
|
UTF8String],
|
||||||
[[app objectForKey:@"kCGWindowName"]
|
[[app objectForKey:@"kCGWindowName"]
|
||||||
lengthOfBytesUsingEncoding:
|
lengthOfBytesUsingEncoding:
|
||||||
NSUTF8StringEncoding]);
|
NSUTF8StringEncoding]);
|
||||||
std::string owner([[app objectForKey:@"kCGWindowOwnerName"]
|
std::string owner(
|
||||||
UTF8String],
|
[[app objectForKey:@"kCGWindowOwnerName"]
|
||||||
[[app objectForKey:@"kCGWindowOwnerName"]
|
UTF8String],
|
||||||
lengthOfBytesUsingEncoding:
|
[[app objectForKey:@"kCGWindowOwnerName"]
|
||||||
NSUTF8StringEncoding]);
|
lengthOfBytesUsingEncoding:
|
||||||
|
NSUTF8StringEncoding]);
|
||||||
|
|
||||||
// True if switch equals app
|
// True if switch equals app
|
||||||
bool equals = (title == name || title == owner);
|
bool equals = (title == name || title == owner);
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
|
|
||||||
|
constexpr auto media_played_to_end_idx = 8;
|
||||||
|
constexpr auto media_any_idx = 9;
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_mediaAdd_clicked()
|
void AdvSceneSwitcher::on_mediaAdd_clicked()
|
||||||
{
|
{
|
||||||
ui->mediaAdd->disconnect(addPulse);
|
ui->mediaAdd->disconnect(addPulse);
|
||||||
@@ -110,22 +113,41 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
|
|||||||
// bool matchedEnded = mediaSwitch.state == OBS_MEDIA_STATE_ENDED &&
|
// bool matchedEnded = mediaSwitch.state == OBS_MEDIA_STATE_ENDED &&
|
||||||
// mediaSwitch.ended;
|
// mediaSwitch.ended;
|
||||||
|
|
||||||
bool matchedEnded = false;
|
bool ended = false;
|
||||||
|
|
||||||
if (state == OBS_MEDIA_STATE_ENDED) {
|
if (state == OBS_MEDIA_STATE_ENDED) {
|
||||||
matchedEnded = mediaSwitch.previousStateEnded;
|
ended = mediaSwitch.previousStateEnded;
|
||||||
mediaSwitch.previousStateEnded = true;
|
mediaSwitch.previousStateEnded = true;
|
||||||
} else {
|
} else {
|
||||||
mediaSwitch.previousStateEnded = false;
|
mediaSwitch.previousStateEnded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool matchedEnded =
|
||||||
|
ended && (mediaSwitch.state == OBS_MEDIA_STATE_ENDED);
|
||||||
|
|
||||||
|
// match if playedToEnd was true in last interval
|
||||||
|
// and playback is currently ended
|
||||||
|
bool matchedPlayedToEnd = mediaSwitch.state ==
|
||||||
|
media_played_to_end_idx &&
|
||||||
|
mediaSwitch.playedToEnd && ended;
|
||||||
|
|
||||||
|
// interval * 2 to make sure not to miss any state changes
|
||||||
|
// which happened during check of the conditions
|
||||||
|
mediaSwitch.playedToEnd = mediaSwitch.playedToEnd ||
|
||||||
|
(duration - time <= interval * 2);
|
||||||
|
|
||||||
|
// reset
|
||||||
|
if (ended)
|
||||||
|
mediaSwitch.playedToEnd = false;
|
||||||
|
|
||||||
// reset for next check
|
// reset for next check
|
||||||
mediaSwitch.stopped = false;
|
mediaSwitch.stopped = false;
|
||||||
mediaSwitch.ended = false;
|
mediaSwitch.ended = false;
|
||||||
|
|
||||||
bool matchedState = ((state == mediaSwitch.state) ||
|
bool matchedState = ((state == mediaSwitch.state) ||
|
||||||
mediaSwitch.anyState) ||
|
mediaSwitch.anyState) ||
|
||||||
matchedStopped || matchedEnded;
|
matchedStopped || matchedEnded ||
|
||||||
|
matchedPlayedToEnd;
|
||||||
|
|
||||||
bool matchedTimeNone =
|
bool matchedTimeNone =
|
||||||
(mediaSwitch.restriction == TIME_RESTRICTION_NONE);
|
(mediaSwitch.restriction == TIME_RESTRICTION_NONE);
|
||||||
@@ -151,7 +173,7 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
|
|||||||
|
|
||||||
bool matched = matchedState && matchedTime;
|
bool matched = matchedState && matchedTime;
|
||||||
|
|
||||||
if (matched) {
|
if (matched && !mediaSwitch.matched) {
|
||||||
match = true;
|
match = true;
|
||||||
scene = (mediaSwitch.usePreviousScene)
|
scene = (mediaSwitch.usePreviousScene)
|
||||||
? previousScene
|
? previousScene
|
||||||
@@ -160,8 +182,12 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
|
|||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
mediaSwitch.logMatch();
|
mediaSwitch.logMatch();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mediaSwitch.matched = matched;
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +330,7 @@ inline MediaSwitch::MediaSwitch(OBSWeakSource scene_, OBSWeakSource source_,
|
|||||||
restriction(restriction_),
|
restriction(restriction_),
|
||||||
time(time_)
|
time(time_)
|
||||||
{
|
{
|
||||||
anyState = state > 7;
|
anyState = state == media_any_idx;
|
||||||
obs_source_t *mediasource = obs_weak_source_get_source(source);
|
obs_source_t *mediasource = obs_weak_source_get_source(source);
|
||||||
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
|
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
|
||||||
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
|
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
|
||||||
@@ -320,7 +346,7 @@ MediaSwitch::MediaSwitch(const MediaSwitch &other)
|
|||||||
restriction(other.restriction),
|
restriction(other.restriction),
|
||||||
time(other.time)
|
time(other.time)
|
||||||
{
|
{
|
||||||
anyState = state > 7;
|
anyState = state == media_any_idx;
|
||||||
obs_source_t *mediasource = obs_weak_source_get_source(source);
|
obs_source_t *mediasource = obs_weak_source_get_source(source);
|
||||||
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
|
signal_handler_t *sh = obs_source_get_signal_handler(mediasource);
|
||||||
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
|
signal_handler_connect(sh, "media_stopped", MediaStopped, this);
|
||||||
@@ -396,6 +422,7 @@ void populateMediaStates(QComboBox *list)
|
|||||||
list->addItem("Stopped");
|
list->addItem("Stopped");
|
||||||
list->addItem("Ended");
|
list->addItem("Ended");
|
||||||
list->addItem("Error");
|
list->addItem("Error");
|
||||||
|
list->addItem("Played to end");
|
||||||
list->addItem("Any");
|
list->addItem("Any");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +536,7 @@ void MediaSwitchWidget::StateChanged(int index)
|
|||||||
return;
|
return;
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switchData->state = (obs_media_state)index;
|
switchData->state = (obs_media_state)index;
|
||||||
switchData->anyState = switchData->state > 7;
|
switchData->anyState = switchData->state == media_any_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaSwitchWidget::TimeRestrictionChanged(int index)
|
void MediaSwitchWidget::TimeRestrictionChanged(int index)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ void SwitcherData::checkRandom(bool &match, OBSWeakSource &scene,
|
|||||||
if (!r.initialized())
|
if (!r.initialized())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (r.scene == lastRandomScene)
|
if (r.scene == lastRandomScene && randomSwitches.size() != 1)
|
||||||
continue;
|
continue;
|
||||||
scene = r.scene;
|
scene = r.scene;
|
||||||
transition = r.transition;
|
transition = r.transition;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
static QMetaObject::Connection addPulse;
|
static QMetaObject::Connection addPulse;
|
||||||
|
|
||||||
void clearFrames(QListWidget *list)
|
void AdvSceneSwitcher::clearFrames(QListWidget *list)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < list->count(); ++i) {
|
for (int i = 0; i < list->count(); ++i) {
|
||||||
ScreenRegionWidget *sw =
|
ScreenRegionWidget *sw =
|
||||||
@@ -25,23 +25,32 @@ void showCurrentFrame(QListWidget *list)
|
|||||||
sw->showFrame();
|
sw->showFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::SetShowFrames()
|
||||||
|
{
|
||||||
|
ui->showFrame->setText("Show guide frames");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::SetHideFrames()
|
||||||
|
{
|
||||||
|
ui->showFrame->setText("Hide guide frames");
|
||||||
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_showFrame_clicked()
|
void AdvSceneSwitcher::on_showFrame_clicked()
|
||||||
{
|
{
|
||||||
switcher->showFrame = !switcher->showFrame;
|
switcher->showFrame = !switcher->showFrame;
|
||||||
|
|
||||||
if (switcher->showFrame) {
|
if (switcher->showFrame) {
|
||||||
ui->showFrame->setText("Hide guide frames");
|
SetHideFrames();
|
||||||
showCurrentFrame(ui->screenRegionSwitches);
|
showCurrentFrame(ui->screenRegionSwitches);
|
||||||
} else {
|
} else {
|
||||||
ui->showFrame->setText("Show guide frames");
|
SetShowFrames();
|
||||||
clearFrames(ui->screenRegionSwitches);
|
clearFrames(ui->screenRegionSwitches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_screenRegionSwitches_currentRowChanged(int idx)
|
void AdvSceneSwitcher::on_screenRegionSwitches_currentRowChanged(int idx)
|
||||||
{
|
{
|
||||||
UNUSED_PARAMETER(idx);
|
if (loading || idx == -1)
|
||||||
if (loading)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (switcher->showFrame) {
|
if (switcher->showFrame) {
|
||||||
|
|||||||
@@ -30,10 +30,19 @@ void AdvSceneSwitcher::on_sceneSequenceRemove_clicked()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// might be in waiting state of sequence
|
||||||
|
// causing invalid access after wakeup
|
||||||
|
// thus we need to stop the main thread before delete
|
||||||
|
bool wasRunning = !switcher->stop;
|
||||||
|
switcher->Stop();
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
int idx = ui->sceneSequenceSwitches->currentRow();
|
int idx = ui->sceneSequenceSwitches->currentRow();
|
||||||
auto &switches = switcher->sceneSequenceSwitches;
|
auto &switches = switcher->sceneSequenceSwitches;
|
||||||
switches.erase(switches.begin() + idx);
|
switches.erase(switches.begin() + idx);
|
||||||
|
|
||||||
|
if (wasRunning)
|
||||||
|
switcher->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
delete item;
|
delete item;
|
||||||
@@ -99,8 +108,6 @@ void AdvSceneSwitcher::on_sceneSequenceSave_clicked()
|
|||||||
|
|
||||||
void AdvSceneSwitcher::on_sceneSequenceLoad_clicked()
|
void AdvSceneSwitcher::on_sceneSequenceLoad_clicked()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
|
|
||||||
QString directory = QFileDialog::getOpenFileName(
|
QString directory = QFileDialog::getOpenFileName(
|
||||||
this, tr("Select a file to read Scene Sequence from ..."),
|
this, tr("Select a file to read Scene Sequence from ..."),
|
||||||
QDir::currentPath(), tr("Text files (*.txt)"));
|
QDir::currentPath(), tr("Text files (*.txt)"));
|
||||||
@@ -121,7 +128,18 @@ void AdvSceneSwitcher::on_sceneSequenceLoad_clicked()
|
|||||||
Msgbox.exec();
|
Msgbox.exec();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// might be in waiting state of sequence
|
||||||
|
// causing invalid access after wakeup
|
||||||
|
// thus we need to stop the main thread before delete
|
||||||
|
bool wasRunning = !switcher->stop;
|
||||||
|
switcher->Stop();
|
||||||
|
|
||||||
switcher->loadSceneSequenceSwitches(obj);
|
switcher->loadSceneSequenceSwitches(obj);
|
||||||
|
|
||||||
|
if (wasRunning)
|
||||||
|
switcher->Start();
|
||||||
|
|
||||||
obs_data_release(obj);
|
obs_data_release(obj);
|
||||||
|
|
||||||
QMessageBox Msgbox;
|
QMessageBox Msgbox;
|
||||||
@@ -165,7 +183,10 @@ void SwitcherData::checkSceneSequence(bool &match, OBSWeakSource &scene,
|
|||||||
transition = s.transition;
|
transition = s.transition;
|
||||||
if (verbose)
|
if (verbose)
|
||||||
s.logMatch();
|
s.logMatch();
|
||||||
|
} else if (verbose) {
|
||||||
|
blog(LOG_INFO, "sequence canceled");
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_source_release(currentSource2);
|
obs_source_release(currentSource2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,9 +143,10 @@ void AdvSceneSwitcher::on_defaultTransitionsDown_clicked()
|
|||||||
switcher->defaultSceneTransitions[index + 1]);
|
switcher->defaultSceneTransitions[index + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::setDefaultSceneTransitions()
|
void SwitcherData::checkDefaultSceneTransitions(bool &match,
|
||||||
|
OBSWeakSource &transition)
|
||||||
{
|
{
|
||||||
if (changedDefTransitionRecently)
|
if (checkedDefTransition)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||||
@@ -156,22 +157,25 @@ void SwitcherData::setDefaultSceneTransitions()
|
|||||||
if (!s.initialized())
|
if (!s.initialized())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
obs_source_t *transition =
|
match = true;
|
||||||
obs_weak_source_get_source(s.transition);
|
transition = s.transition;
|
||||||
//This might cancel the current transition
|
|
||||||
//There is no way to be sure when the previous transition finished
|
|
||||||
obs_frontend_set_current_transition(transition);
|
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
s.logMatch();
|
s.logMatch();
|
||||||
|
|
||||||
obs_source_release(transition);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
obs_source_release(currentSource);
|
obs_source_release(currentSource);
|
||||||
obs_weak_source_release(ws);
|
obs_weak_source_release(ws);
|
||||||
changedDefTransitionRecently = true;
|
|
||||||
|
checkedDefTransition = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwitcherData::setCurrentDefTransition(OBSWeakSource &transition)
|
||||||
|
{
|
||||||
|
obs_source_t *transitionSource = obs_weak_source_get_source(transition);
|
||||||
|
obs_frontend_set_current_transition(transitionSource);
|
||||||
|
obs_source_release(transitionSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_transitionOverridecheckBox_stateChanged(int state)
|
void AdvSceneSwitcher::on_transitionOverridecheckBox_stateChanged(int state)
|
||||||
|
|||||||
@@ -89,6 +89,9 @@ void GetWindowList(QStringList &windows)
|
|||||||
for (auto window : w) {
|
for (auto window : w) {
|
||||||
windows << QString::fromStdString(window);
|
windows << QString::fromStdString(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add entry for OBS Studio itself, see GetCurrentWindowTitle
|
||||||
|
windows << QString("OBS");
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetCurrentWindowTitle(std::string &title)
|
void GetCurrentWindowTitle(std::string &title)
|
||||||
@@ -97,10 +100,10 @@ void GetCurrentWindowTitle(std::string &title)
|
|||||||
DWORD pid;
|
DWORD pid;
|
||||||
DWORD thid;
|
DWORD thid;
|
||||||
thid = GetWindowThreadProcessId(window, &pid);
|
thid = GetWindowThreadProcessId(window, &pid);
|
||||||
/*GetWindowText will freeze if the control it is reading was created in another thread.
|
// GetWindowText will freeze if the control it is reading was created in another thread.
|
||||||
It does not directly read the control.Instead,
|
// It does not directly read the control.
|
||||||
it waits for the thread that created the control to process a WM_GETTEXT message.
|
// Instead it waits for the thread that created the control to process a WM_GETTEXT message.
|
||||||
So if that thread is frozen in a WaitFor... call you have a deadlock.*/
|
// So if that thread is frozen in a WaitFor... call you have a deadlock.
|
||||||
if (GetCurrentProcessId() == pid) {
|
if (GetCurrentProcessId() == pid) {
|
||||||
title = "OBS";
|
title = "OBS";
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user